Changeset 248750 in webkit
- Timestamp:
- Aug 15, 2019 3:18:56 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r248746 r248750 1 2019-08-15 Zalan Bujtas <zalan@apple.com> 2 3 [ContentChangeObserver] Dispatch synthetic click when the visibility candidate element becomes hidden again. 4 https://bugs.webkit.org/show_bug.cgi?id=200773 5 <rdar://problem/54351728> 6 7 Reviewed by Simon Fraser. 8 9 * fast/events/touch/ios/content-observation/going-from-hidden-to-visible-and-to-hidden-expected.html: Added. 10 * fast/events/touch/ios/content-observation/going-from-hidden-to-visible-and-to-hidden.html: Added. 11 1 12 2019-08-15 Robin Morisset <rmorisset@apple.com> 2 13 -
trunk/Source/WebCore/ChangeLog
r248749 r248750 1 2019-08-15 Zalan Bujtas <zalan@apple.com> 2 3 [ContentChangeObserver] Dispatch synthetic click when the visibility candidate element becomes hidden again. 4 https://bugs.webkit.org/show_bug.cgi?id=200773 5 <rdar://problem/54351728> 6 7 Reviewed by Simon Fraser. 8 9 This patch fixes the case when the candidate element (going from hidden to visible) becomes hidden by the end of the observation window. It essentially means that no visible change has happened 10 and we should proceed with dispatching the synthetic click event. 11 We now keep track of the candidate element and reset the visiblity state when it loses its renderer. 12 13 Test: fast/events/touch/ios/content-observation/going-from-hidden-to-visible-and-to-hidden.html 14 15 * page/ios/ContentChangeObserver.cpp: 16 (WebCore::ContentChangeObserver::didAddTransition): 17 (WebCore::ContentChangeObserver::didFinishTransition): 18 (WebCore::ContentChangeObserver::didInstallDOMTimer): 19 (WebCore::ContentChangeObserver::reset): 20 (WebCore::ContentChangeObserver::rendererWillBeDestroyed): 21 (WebCore::ContentChangeObserver::contentVisibilityDidChange): 22 (WebCore::ContentChangeObserver::touchEventDidStart): 23 (WebCore::ContentChangeObserver::touchEventDidFinish): 24 (WebCore::ContentChangeObserver::mouseMovedDidStart): 25 (WebCore::ContentChangeObserver::mouseMovedDidFinish): 26 (WebCore::ContentChangeObserver::adjustObservedState): 27 (WebCore::ContentChangeObserver::StyleChangeScope::~StyleChangeScope): 28 (WebCore::ContentChangeObserver::hasDeterminateState const): Deleted. 29 * page/ios/ContentChangeObserver.h: 30 (WebCore::ContentChangeObserver::hasObservedTransition const): 31 (WebCore::ContentChangeObserver::setTouchEventIsBeingDispatched): 32 (WebCore::ContentChangeObserver::isTouchEventBeingDispatched const): 33 (WebCore::ContentChangeObserver::setMouseMovedEventIsBeingDispatched): 34 (WebCore::ContentChangeObserver::isMouseMovedEventBeingDispatched const): 35 (WebCore::ContentChangeObserver::isObservingContentChanges const): 36 1 37 2019-08-15 Justin Fan <justin_fan@apple.com> 2 38 -
trunk/Source/WebCore/page/ios/ContentChangeObserver.cpp
r248695 r248750 215 215 if (hasVisibleChangeState()) 216 216 return; 217 if (!isObservingContentChanges()) 218 return; 217 219 if (!isObservingTransitions()) 218 220 return; … … 252 254 } 253 255 if (isConsideredClickable(*targetElement, ElementHadRenderer::Yes)) 254 weakThis->contentVisibilityDidChange( );256 weakThis->contentVisibilityDidChange(*targetElement); 255 257 weakThis->adjustObservedState(Event::CompletedTransition); 256 258 }); … … 272 274 if (!m_document.settings().contentChangeObserverEnabled()) 273 275 return; 276 if (!isObservingContentChanges()) 277 return; 278 if (!isObservingDOMTimerScheduling()) 279 return; 280 if (hasVisibleChangeState()) 281 return; 274 282 if (m_document.activeDOMObjectsAreSuspended()) 275 283 return; 276 284 if (timeout > maximumDelayForTimers || !singleShot) 277 return;278 if (!isObservingDOMTimerScheduling())279 return;280 if (hasVisibleChangeState())281 285 return; 282 286 LOG_WITH_STREAM(ContentObservation, stream << "didInstallDOMTimer: register this timer: (" << &timer << ") and observe when it fires."); … … 360 364 stopObservingPendingActivities(); 361 365 setHasNoChangeState(); 366 367 setTouchEventIsBeingDispatched(false); 362 368 setIsBetweenTouchEndAndMouseMoved(false); 363 364 m_touchEventIsBeingDispatched = false; 369 setMouseMovedEventIsBeingDispatched(false); 370 365 371 m_isInObservedStyleRecalc = false; 366 372 m_observedDomTimerIsBeingExecuted = false; 367 m_mouseMovedEventIsBeingDispatched = false; 373 374 m_visibilityCandidateElement = { }; 368 375 369 376 m_contentObservationTimer.stop(); … … 390 397 if (!isObservingContentChanges()) 391 398 return; 392 if (hasVisibleChangeState())393 return;394 399 LOG_WITH_STREAM(ContentObservation, stream << "rendererWillBeDestroyed element: " << &element); 395 400 396 401 if (!isVisuallyHidden(element)) 397 402 m_elementsWithDestroyedVisibleRenderer.add(&element); 398 } 399 400 void ContentChangeObserver::contentVisibilityDidChange() 403 // Candidate element is no longer visible. 404 if (m_visibilityCandidateElement == &element) { 405 // FIXME: We should also check for other type of visiblity changes. 406 ASSERT(hasVisibleChangeState()); 407 m_visibilityCandidateElement = { }; 408 setHasIndeterminateState(); 409 } 410 } 411 412 void ContentChangeObserver::contentVisibilityDidChange(const Element& element) 401 413 { 402 414 LOG(ContentObservation, "contentVisibilityDidChange: visible content change did happen."); 415 // FIXME: This should evolve into a list of candidate elements. 416 m_visibilityCandidateElement = makeWeakPtr(element); 403 417 adjustObservedState(Event::ContentVisibilityChanged); 404 418 } … … 412 426 return; 413 427 LOG(ContentObservation, "touchEventDidStart: touch start event started."); 414 m_touchEventIsBeingDispatched = true;428 setTouchEventIsBeingDispatched(true); 415 429 adjustObservedState(Event::StartedTouchStartEventDispatching); 416 430 #else … … 422 436 { 423 437 #if ENABLE(TOUCH_EVENTS) 424 if (! m_touchEventIsBeingDispatched)438 if (!isTouchEventBeingDispatched()) 425 439 return; 426 440 ASSERT(m_document.settings().contentChangeObserverEnabled()); 427 441 LOG(ContentObservation, "touchEventDidFinish: touch start event finished."); 428 m_touchEventIsBeingDispatched = false;442 setTouchEventIsBeingDispatched(false); 429 443 adjustObservedState(Event::EndedTouchStartEventDispatching); 430 444 #endif … … 436 450 return; 437 451 LOG(ContentObservation, "mouseMovedDidStart: mouseMoved started."); 438 m_mouseMovedEventIsBeingDispatched = true;452 setMouseMovedEventIsBeingDispatched(true); 439 453 adjustObservedState(Event::StartedMouseMovedEventDispatching); 440 454 } … … 442 456 void ContentChangeObserver::mouseMovedDidFinish() 443 457 { 444 if (! m_mouseMovedEventIsBeingDispatched)458 if (!isMouseMovedEventBeingDispatched()) 445 459 return; 446 460 ASSERT(m_document.settings().contentChangeObserverEnabled()); 447 461 LOG(ContentObservation, "mouseMovedDidFinish: mouseMoved finished."); 448 462 adjustObservedState(Event::EndedMouseMovedEventDispatching); 449 m_mouseMovedEventIsBeingDispatched = false;463 setMouseMovedEventIsBeingDispatched(false); 450 464 } 451 465 … … 455 469 LOG(ContentObservation, "Wait until next style recalc fires."); 456 470 m_isWaitingForStyleRecalc = shouldObserve; 457 }458 459 bool ContentChangeObserver::hasDeterminateState() const460 {461 if (hasVisibleChangeState())462 return true;463 return observedContentChange() == WKContentNoChange && !hasPendingActivity();464 471 } 465 472 … … 478 485 479 486 auto notifyClientIfNeeded = [&] { 480 // First demote to "no change" if there's no pending activity anymore. 481 if (observedContentChange() == WKContentIndeterminateChange && !hasPendingActivity()) 487 if (isTouchEventBeingDispatched()) { 488 LOG(ContentObservation, "notifyClientIfNeeded: Touch event is being dispatched. No need to notify the client."); 489 return; 490 } 491 if (isBetweenTouchEndAndMouseMoved()) { 492 LOG(ContentObservation, "notifyClientIfNeeded: Not reached mouseMoved yet. No need to notify the client."); 493 return; 494 } 495 if (isMouseMovedEventBeingDispatched()) { 496 LOG(ContentObservation, "notifyClientIfNeeded: in mouseMoved call. No need to notify the client."); 497 return; 498 } 499 if (isObservationTimeWindowActive()) { 500 LOG(ContentObservation, "notifyClientIfNeeded: Inside the fixed window observation. No need to notify the client."); 501 return; 502 } 503 504 // The fixed observation window (which is the final step in content observation) is closed and now we check if are still waiting for timers or animations to finish. 505 if (hasPendingActivity()) { 506 LOG(ContentObservation, "notifyClientIfNeeded: We are still waiting on some events."); 507 return; 508 } 509 510 // First demote to "no change" because we've got no pending activity anymore. 511 if (observedContentChange() == WKContentIndeterminateChange) 482 512 setHasNoChangeState(); 483 513 484 if (isBetweenTouchEndAndMouseMoved()) { 485 LOG(ContentObservation, "adjustStateAndNotifyContentChangeIfNeeded: Not reached mouseMoved yet. No need to notify the client."); 486 return; 487 } 488 if (m_mouseMovedEventIsBeingDispatched) { 489 LOG(ContentObservation, "adjustStateAndNotifyContentChangeIfNeeded: in mouseMoved call. No need to notify the client."); 490 return; 491 } 492 if (isObservationTimeWindowActive()) { 493 LOG(ContentObservation, "adjustStateAndNotifyContentChangeIfNeeded: Inside the fixed window observation. No need to notify the client."); 494 return; 495 } 496 if (!hasDeterminateState()) { 497 LOG(ContentObservation, "adjustStateAndNotifyContentChangeIfNeeded: not in a determined state yet."); 498 return; 499 } 500 LOG_WITH_STREAM(ContentObservation, stream << "adjustStateAndNotifyContentChangeIfNeeded: sending observedContentChange ->" << observedContentChange()); 514 LOG_WITH_STREAM(ContentObservation, stream << "notifyClientIfNeeded: sending observedContentChange ->" << observedContentChange()); 501 515 ASSERT(m_document.page()); 502 516 ASSERT(m_document.frame()); … … 596 610 // Either the page decided to call preventDefault on the touch action or the tap gesture evolved to some other gesture (long press, double tap). 597 611 if (event == Event::WillNotProceedWithClick) { 598 reset();612 stopContentObservation(); 599 613 return; 600 614 } … … 629 643 630 644 if (changedFromHiddenToVisible() && isConsideredClickable(m_element, m_hadRenderer ? ElementHadRenderer::Yes : ElementHadRenderer::No)) 631 m_contentChangeObserver.contentVisibilityDidChange( );645 m_contentChangeObserver.contentVisibilityDidChange(m_element); 632 646 } 633 647 -
trunk/Source/WebCore/page/ios/ContentChangeObserver.h
r248695 r248750 129 129 void didRecognizeLongPress(); 130 130 131 void contentVisibilityDidChange( );131 void contentVisibilityDidChange(const Element&); 132 132 133 133 void setShouldObserveDOMTimerSchedulingAndTransitions(bool); … … 160 160 bool hasObservedDOMTimer() const { return !m_DOMTimerList.isEmpty(); } 161 161 bool hasObservedTransition() const { return !m_elementsWithTransition.isEmpty(); } 162 bool hasDeterminateState() const;163 162 164 163 void setIsBetweenTouchEndAndMouseMoved(bool isBetween) { m_isBetweenTouchEndAndMouseMoved = isBetween; } 165 164 bool isBetweenTouchEndAndMouseMoved() const { return m_isBetweenTouchEndAndMouseMoved; } 165 166 void setTouchEventIsBeingDispatched(bool dispatching) { m_touchEventIsBeingDispatched = dispatching; } 167 bool isTouchEventBeingDispatched() const { return m_touchEventIsBeingDispatched; } 168 169 void setMouseMovedEventIsBeingDispatched(bool dispatching) { m_mouseMovedEventIsBeingDispatched = dispatching; } 170 bool isMouseMovedEventBeingDispatched() const { return m_mouseMovedEventIsBeingDispatched; } 166 171 167 172 bool hasPendingActivity() const { return hasObservedDOMTimer() || hasObservedTransition() || m_isWaitingForStyleRecalc || isObservationTimeWindowActive(); } … … 203 208 WKContentChange m_observedContentState { WKContentNoChange }; 204 209 WeakPtr<Element> m_hiddenTouchTargetElement; 210 WeakPtr<Element> m_visibilityCandidateElement; 205 211 bool m_touchEventIsBeingDispatched { false }; 206 212 bool m_isWaitingForStyleRecalc { false }; … … 215 221 inline bool ContentChangeObserver::isObservingContentChanges() const 216 222 { 217 return m_touchEventIsBeingDispatched218 || m_isBetweenTouchEndAndMouseMoved219 || m_mouseMovedEventIsBeingDispatched223 return isTouchEventBeingDispatched() 224 || isBetweenTouchEndAndMouseMoved() 225 || isMouseMovedEventBeingDispatched() 220 226 || m_observedDomTimerIsBeingExecuted 221 227 || m_isInObservedStyleRecalc
Note: See TracChangeset
for help on using the changeset viewer.