Changeset 206795 in webkit
- Timestamp:
- Oct 4, 2016 4:42:18 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r206791 r206795 1 2016-10-03 Ryosuke Niwa <rniwa@webkit.org> 2 3 ShadowRoot interface should have elementFromPoint 4 https://bugs.webkit.org/show_bug.cgi?id=162882 5 6 Reviewed by Chris Dumez. 7 8 Add a W3C style testharness.js test for elementFromPoint on ShadowRoot. 9 10 * fast/shadow-dom/DocumentOrShadowRoot-prototype-elementFromPoint-expected.txt: Added. 11 * fast/shadow-dom/DocumentOrShadowRoot-prototype-elementFromPoint.html: Added. 12 1 13 2016-10-04 Myles C. Maxfield <mmaxfield@apple.com> 2 14 -
trunk/Source/WebCore/CMakeLists.txt
r206679 r206795 392 392 dom/Document.idl 393 393 dom/DocumentFragment.idl 394 dom/DocumentOrShadowRoot.idl 394 395 dom/DocumentType.idl 395 396 dom/Element.idl -
trunk/Source/WebCore/ChangeLog
r206791 r206795 1 2016-10-03 Ryosuke Niwa <rniwa@webkit.org> 2 3 ShadowRoot interface should have elementFromPoint 4 https://bugs.webkit.org/show_bug.cgi?id=162882 5 6 Reviewed by Chris Dumez. 7 8 Add elementFromPoint to ShadowRoot's prototype as specified at: 9 https://www.w3.org/TR/shadow-dom/#extensions-to-the-documentorshadowroot-mixin 10 with changes proposed at https://github.com/w3c/csswg-drafts/issues/556 11 12 Added TreeScope::retargetToScope which implements 13 14 This patch also factors DocumentOrShadowRoot.idl out of Document and ShadowRoot interfaces to better match 15 the latest DOM specification: https://dom.spec.whatwg.org/#mixin-documentorshadowroot 16 17 Test: fast/shadow-dom/Document-prototype-elementFromPoint.html 18 19 * CMakeLists.txt: 20 * DerivedSources.make: 21 * WebCore.xcodeproj/project.pbxproj: 22 * dom/Document.cpp: 23 (WebCore::Document::nodeFromPoint): Moved to TreeScope. 24 (WebCore::Document::elementFromPoint): Moved to TreeScope. 25 * dom/Document.h: 26 * dom/Document.idl: Moved elementFromPoint and activeElement to DocumentOrShadowRoot.idl. 27 * dom/DocumentOrShadowRoot.idl: Added. 28 * dom/EventPath.cpp: 29 (WebCore::RelatedNodeRetargeter::checkConsistency): Use newly added TreeScope::retargetToScope. 30 * dom/ShadowRoot.idl: Moved activeElement to DocumentOrShadowRoot.idl. 31 * dom/TreeScope.cpp: 32 (WebCore::TreeScope::retargetToScope): Added. Implements https://dom.spec.whatwg.org/#retarget efficiently. 33 Instead of checking whether A (node) is a shadow-including inclusive ancestor of B (this scope) at each 34 parent, find the lowest ancestor which contains both A and B, and return the self-inclusive ancestor of B 35 in that tree. To find the lowest common ancestor in O(n), traverse all ancestors of A and B separately and 36 do a top-down traversal. The last tree scope in which A's ancestor and B's ancestor match is the lowest 37 common ancestor. 38 (WebCore::TreeScope::nodeFromPoint): Moved from Document. 39 (WebCore::TreeScope::elementFromPoint): Moved from Document. Use retargetToScope and parentInComposedTree 40 instead of parentNode and ancestorInThisScope to match the semantics proposed in 41 https://github.com/w3c/csswg-drafts/issues/556 42 * dom/TreeScope.h: 43 1 44 2016-10-04 Myles C. Maxfield <mmaxfield@apple.com> 2 45 -
trunk/Source/WebCore/DerivedSources.make
r206440 r206795 302 302 $(WebCore)/dom/Document.idl \ 303 303 $(WebCore)/dom/DocumentFragment.idl \ 304 $(WebCore)/dom/DocumentOrShadowRoot.idl \ 304 305 $(WebCore)/dom/DocumentType.idl \ 305 306 $(WebCore)/dom/Element.idl \ -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r206717 r206795 10878 10878 9B03D8061BB3110D00B764E8 /* WritableStreamBuiltins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WritableStreamBuiltins.h; sourceTree = "<group>"; }; 10879 10879 9B03D8061BB3110D00B764E9 /* WritableStreamInternalsBuiltins.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WritableStreamInternalsBuiltins.h; sourceTree = "<group>"; }; 10880 9B0FE8731D9E02DF004A8ACB /* DocumentOrShadowRoot.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DocumentOrShadowRoot.idl; sourceTree = "<group>"; }; 10880 10881 9B19B67E1B964E5200348745 /* ShadowRoot.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ShadowRoot.idl; sourceTree = "<group>"; }; 10881 10882 9B1AB0791648C69D0051F3F2 /* HTMLFormControlsCollection.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = HTMLFormControlsCollection.idl; sourceTree = "<group>"; }; … … 23015 23016 CE057FA31220731100A476D5 /* DocumentMarkerController.cpp */, 23016 23017 CE057FA41220731100A476D5 /* DocumentMarkerController.h */, 23018 9B0FE8731D9E02DF004A8ACB /* DocumentOrShadowRoot.idl */, 23017 23019 14947FFB12F80CD200A0F631 /* DocumentOrderedMap.cpp */, 23018 23020 14947FFC12F80CD200A0F631 /* DocumentOrderedMap.h */, -
trunk/Source/WebCore/dom/Document.cpp
r206753 r206795 1426 1426 } 1427 1427 1428 Node* Document::nodeFromPoint(const LayoutPoint& clientPoint, LayoutPoint* localPoint)1429 {1430 if (!frame() || !view())1431 return nullptr;1432 1433 Frame& frame = *this->frame();1434 1435 float scaleFactor = frame.pageZoomFactor() * frame.frameScaleFactor();1436 1437 LayoutPoint contentsPoint = clientPoint;1438 contentsPoint.scale(scaleFactor, scaleFactor);1439 contentsPoint.moveBy(view()->contentsScrollPosition());1440 1441 LayoutRect visibleRect;1442 #if PLATFORM(IOS)1443 visibleRect = view()->unobscuredContentRect();1444 #else1445 visibleRect = view()->visibleContentRect();1446 #endif1447 if (!visibleRect.contains(contentsPoint))1448 return nullptr;1449 1450 HitTestResult result(contentsPoint);1451 renderView()->hitTest(HitTestRequest(), result);1452 1453 if (localPoint)1454 *localPoint = result.localPoint();1455 1456 return result.innerNode();1457 }1458 1459 Element* Document::elementFromPoint(const LayoutPoint& clientPoint)1460 {1461 if (!hasLivingRenderTree())1462 return nullptr;1463 1464 Node* node = nodeFromPoint(clientPoint);1465 while (node && !is<Element>(*node))1466 node = node->parentNode();1467 1468 if (node)1469 node = ancestorInThisScope(node);1470 1471 return downcast<Element>(node);1472 }1473 1474 1428 RefPtr<Range> Document::caretRangeFromPoint(int x, int y) 1475 1429 { -
trunk/Source/WebCore/dom/Document.h
r206753 r206795 398 398 NamedFlowCollection& namedFlows(); 399 399 400 Element* elementFromPoint(int x, int y) { return elementFromPoint(LayoutPoint(x, y)); }401 WEBCORE_EXPORT Element* elementFromPoint(const LayoutPoint& clientPoint);402 403 400 WEBCORE_EXPORT RefPtr<Range> caretRangeFromPoint(int x, int y); 404 401 RefPtr<Range> caretRangeFromPoint(const LayoutPoint& clientPoint); … … 1364 1361 PageVisibilityState pageVisibilityState() const; 1365 1362 1366 Node* nodeFromPoint(const LayoutPoint& clientPoint, LayoutPoint* localPoint = nullptr);1367 1368 1363 template <CollectionType collectionType> 1369 1364 Ref<HTMLCollection> ensureCachedCollection(); -
trunk/Source/WebCore/dom/Document.idl
r206723 r206795 127 127 readonly attribute DOMString readyState; 128 128 129 Element elementFromPoint(optional long x = 0, optional long y = 0);130 129 Range caretRangeFromPoint(optional long x = 0, optional long y = 0); 131 130 … … 142 141 HTMLCollection getElementsByClassName(DOMString classNames); 143 142 144 readonly attribute Element? activeElement;145 143 boolean hasFocus(); 146 144 … … 215 213 Document implements ParentNode; 216 214 Document implements NonElementParentNode; 215 Document implements DocumentOrShadowRoot; 217 216 Document implements GlobalEventHandlers; -
trunk/Source/WebCore/dom/EventPath.cpp
r206463 r206795 361 361 void RelatedNodeRetargeter::checkConsistency(Node& currentTarget) 362 362 { 363 ASSERT(!m_retargetedRelatedNode || currentTarget.isUnclosedNode(*m_retargetedRelatedNode)); 364 365 // http://w3c.github.io/webcomponents/spec/shadow/#dfn-retargeting-algorithm 366 Node& base = currentTarget; 367 for (Node* targetAncestor = &m_relatedNode; targetAncestor; targetAncestor = targetAncestor->parentOrShadowHostNode()) { 368 if (targetAncestor->rootNode().containsIncludingShadowDOM(&base)) { 369 ASSERT(m_retargetedRelatedNode == targetAncestor); 370 return; 371 } 372 } 373 ASSERT(!m_retargetedRelatedNode || m_hasDifferentTreeRoot); 374 } 375 #endif 376 377 } 363 if (!m_retargetedRelatedNode) 364 return; 365 ASSERT(currentTarget.isUnclosedNode(*m_retargetedRelatedNode)); 366 ASSERT(m_retargetedRelatedNode == ¤tTarget.treeScope().retargetToScope(m_relatedNode)); 367 } 368 #endif 369 370 } -
trunk/Source/WebCore/dom/ShadowRoot.idl
r206723 r206795 29 29 ] interface ShadowRoot : DocumentFragment { 30 30 readonly attribute ShadowRootMode mode; 31 readonly attribute Element activeElement;32 31 readonly attribute Element host; 33 32 … … 37 36 // "user-agent" is a WebKit extension that is not exposed to the Web. 38 37 enum ShadowRootMode { "user-agent", "closed", "open" }; 38 39 ShadowRoot implements DocumentOrShadowRoot; -
trunk/Source/WebCore/dom/TreeScope.cpp
r203324 r206795 33 33 #include "FocusController.h" 34 34 #include "Frame.h" 35 #include "FrameView.h" 35 36 #include "HTMLAnchorElement.h" 36 37 #include "HTMLFrameOwnerElement.h" … … 40 41 #include "IdTargetObserverRegistry.h" 41 42 #include "Page.h" 43 #include "RenderView.h" 42 44 #include "RuntimeEnabledFeatures.h" 43 45 #include "ShadowRoot.h" … … 167 169 return; 168 170 m_elementsByName->remove(name, element); 171 } 172 173 174 Node& TreeScope::retargetToScope(Node& node) const 175 { 176 auto& scope = node.treeScope(); 177 if (LIKELY(this == &scope || !node.isInShadowTree())) 178 return node; 179 ASSERT(is<ShadowRoot>(scope.rootNode())); 180 181 Vector<TreeScope*, 8> nodeTreeScopes; 182 for (auto* currentScope = &scope; currentScope; currentScope = currentScope->parentTreeScope()) 183 nodeTreeScopes.append(currentScope); 184 ASSERT(nodeTreeScopes.size() >= 2); 185 186 Vector<const TreeScope*, 8> ancestorScopes; 187 for (auto* currentScope = this; currentScope; currentScope = currentScope->parentTreeScope()) 188 ancestorScopes.append(currentScope); 189 190 size_t i = nodeTreeScopes.size(); 191 size_t j = ancestorScopes.size(); 192 while (i > 0 && j > 0 && nodeTreeScopes[i - 1] == ancestorScopes[j - 1]) { 193 --i; 194 --j; 195 } 196 197 bool nodeIsInOuterTreeScope = !i; 198 if (nodeIsInOuterTreeScope) 199 return node; 200 201 ShadowRoot& shadowRootInLowestCommonTreeScope = downcast<ShadowRoot>(nodeTreeScopes[i - 1]->rootNode()); 202 return *shadowRootInLowestCommonTreeScope.host(); 169 203 } 170 204 … … 244 278 245 279 return m_labelsByForAttribute->getElementByLabelForAttribute(*forAttributeValue.impl(), *this); 280 } 281 282 Node* TreeScope::nodeFromPoint(const LayoutPoint& clientPoint, LayoutPoint* localPoint) 283 { 284 auto* frame = documentScope().frame(); 285 auto* view = documentScope().view(); 286 if (!frame || !view) 287 return nullptr; 288 289 float scaleFactor = frame->pageZoomFactor() * frame->frameScaleFactor(); 290 291 LayoutPoint contentsPoint = clientPoint; 292 contentsPoint.scale(scaleFactor, scaleFactor); 293 contentsPoint.moveBy(view->contentsScrollPosition()); 294 295 LayoutRect visibleRect; 296 #if PLATFORM(IOS) 297 visibleRect = view->unobscuredContentRect(); 298 #else 299 visibleRect = view->visibleContentRect(); 300 #endif 301 if (!visibleRect.contains(contentsPoint)) 302 return nullptr; 303 304 HitTestResult result(contentsPoint); 305 documentScope().renderView()->hitTest(HitTestRequest(), result); 306 307 if (localPoint) 308 *localPoint = result.localPoint(); 309 310 return result.innerNode(); 311 } 312 313 Element* TreeScope::elementFromPoint(int x, int y) 314 { 315 Document& document = documentScope(); 316 if (!document.hasLivingRenderTree()) 317 return nullptr; 318 319 Node* node = nodeFromPoint(LayoutPoint(x, y), nullptr); 320 if (!node) 321 return nullptr; 322 323 node = &retargetToScope(*node); 324 while (!is<Element>(*node)) { 325 node = node->parentInComposedTree(); 326 if (!node) 327 break; 328 node = &retargetToScope(*node); 329 } 330 331 return downcast<Element>(node); 246 332 } 247 333 -
trunk/Source/WebCore/dom/TreeScope.h
r204717 r206795 72 72 static ptrdiff_t documentScopeMemoryOffset() { return OBJECT_OFFSETOF(TreeScope, m_documentScope); } 73 73 74 // https://dom.spec.whatwg.org/#retarget 75 Node& retargetToScope(Node&) const; 76 74 77 Node* ancestorInThisScope(Node*) const; 75 78 … … 83 86 void removeLabel(const AtomicStringImpl& forAttributeValue, HTMLLabelElement&); 84 87 HTMLLabelElement* labelElementForId(const AtomicString& forAttributeValue); 88 89 WEBCORE_EXPORT Element* elementFromPoint(int x, int y); 85 90 86 91 DOMSelection* getSelection() const; … … 111 116 m_documentScope = document; 112 117 } 118 119 Node* nodeFromPoint(const LayoutPoint& clientPoint, LayoutPoint* localPoint); 113 120 114 121 private: -
trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
r206665 r206795 3214 3214 3215 3215 #if ENABLE(CUSTOM_ELEMENTS) 3216 RuntimeEnabledFeatures::sharedFeatures().setCustomElementsEnabled( store.getBoolValueForKey(WebPreferencesKey::customElementsEnabledKey()));3216 RuntimeEnabledFeatures::sharedFeatures().setCustomElementsEnabled(true || store.getBoolValueForKey(WebPreferencesKey::customElementsEnabledKey())); 3217 3217 #endif 3218 3218
Note: See TracChangeset
for help on using the changeset viewer.