Changeset 72596 in webkit
- Timestamp:
- Nov 23, 2010 4:57:17 AM (13 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r72593 r72596 1 2010-11-23 Yael Aharon <yael.aharon@nokia.com> 2 3 Reviewed by Antonio Gomes. 4 5 Spatial Navigation: Code cleanup 6 https://bugs.webkit.org/show_bug.cgi?id=49442 7 8 Remove code that is not used anymore after http://trac.webkit.org/changeset/72522. 9 Added const to canBeScrolledIntoView. 10 No new tests because this is only code cleanup. 11 12 * page/FocusController.cpp: 13 * page/FocusController.h: 14 * page/SpatialNavigation.cpp: 15 (WebCore::canBeScrolledIntoView): 16 * page/SpatialNavigation.h: 17 1 18 2010-11-23 Jeremy Orlow <jorlow@chromium.org> 2 19 -
trunk/WebCore/page/FocusController.cpp
r72522 r72596 293 293 } 294 294 295 static void updateFocusCandidateInSameContainer(const FocusCandidate& candidate, FocusCandidate& closest)296 {297 if (closest.isNull()) {298 closest = candidate;299 return;300 }301 302 if (candidate.alignment == closest.alignment) {303 if (candidate.distance < closest.distance)304 closest = candidate;305 return;306 }307 308 if (candidate.alignment > closest.alignment)309 closest = candidate;310 }311 312 static void updateFocusCandidateIfCloser(Node* focusedNode, const FocusCandidate& candidate, FocusCandidate& closest)313 {314 // First, check the common case: neither candidate nor closest are315 // inside scrollable content, then no need to care about enclosingScrollableBox316 // heuristics or parent{Distance,Alignment}, but only distance and alignment.317 if (!candidate.inScrollableContainer() && !closest.inScrollableContainer()) {318 updateFocusCandidateInSameContainer(candidate, closest);319 return;320 }321 322 bool sameContainer = candidate.document() == closest.document() && candidate.enclosingScrollableBox == closest.enclosingScrollableBox;323 324 // Second, if candidate and closest are in the same "container" (i.e. {i}frame or any325 // scrollable block element), we can handle them as common case.326 if (sameContainer) {327 updateFocusCandidateInSameContainer(candidate, closest);328 return;329 }330 331 // Last, we are considering moving to a candidate located in a different enclosing332 // scrollable box than closest.333 bool isInInnerDocument = !isInRootDocument(focusedNode);334 335 bool sameContainerAsCandidate = isInInnerDocument ? focusedNode->document() == candidate.document() :336 focusedNode->isDescendantOf(candidate.enclosingScrollableBox);337 338 bool sameContainerAsClosest = isInInnerDocument ? focusedNode->document() == closest.document() :339 focusedNode->isDescendantOf(closest.enclosingScrollableBox);340 341 // sameContainerAsCandidate and sameContainerAsClosest are mutually exclusive.342 ASSERT(!(sameContainerAsCandidate && sameContainerAsClosest));343 344 if (sameContainerAsCandidate) {345 closest = candidate;346 return;347 }348 349 if (sameContainerAsClosest) {350 // Nothing to be done.351 return;352 }353 354 // NOTE: !sameContainerAsCandidate && !sameContainerAsClosest355 // If distance is shorter, and we are talking about scrollable container,356 // lets compare parent distance and alignment before anything.357 if (candidate.distance < closest.distance) {358 if (candidate.alignment >= closest.parentAlignment359 || candidate.parentAlignment == closest.parentAlignment) {360 closest = candidate;361 return;362 }363 364 } else if (candidate.parentDistance < closest.distance) {365 if (candidate.parentAlignment >= closest.alignment) {366 closest = candidate;367 return;368 }369 }370 }371 372 void FocusController::findFocusableNodeInDirection(Node* outer, Node* focusedNode,373 FocusDirection direction, KeyboardEvent* event,374 FocusCandidate& closest, const FocusCandidate& candidateParent)375 {376 ASSERT(outer);377 ASSERT(candidateParent.isNull()378 || candidateParent.node->hasTagName(frameTag)379 || candidateParent.node->hasTagName(iframeTag)380 || isScrollableContainerNode(candidateParent.node));381 382 // Walk all the child nodes and update closest if we find a nearer node.383 Node* node = outer;384 while (node) {385 386 // Inner documents case.387 if (node->isFrameOwnerElement()) {388 deepFindFocusableNodeInDirection(node, focusedNode, direction, event, closest);389 390 // Scrollable block elements (e.g. <div>, etc) case.391 } else if (isScrollableContainerNode(node)) {392 deepFindFocusableNodeInDirection(node, focusedNode, direction, event, closest);393 node = node->traverseNextSibling();394 continue;395 396 } else if (node != focusedNode && node->isKeyboardFocusable(event)) {397 FocusCandidate candidate(node);398 399 // There are two ways to identify we are in a recursive call from deepFindFocusableNodeInDirection400 // (i.e. processing an element in an iframe, frame or a scrollable block element):401 402 // 1) If candidateParent is not null, and it holds the distance and alignment data of the403 // parent container element itself;404 // 2) Parent of outer is <frame> or <iframe>;405 // 3) Parent is any other scrollable block element.406 if (!candidateParent.isNull()) {407 candidate.parentAlignment = candidateParent.alignment;408 candidate.parentDistance = candidateParent.distance;409 candidate.enclosingScrollableBox = candidateParent.node;410 411 } else if (!isInRootDocument(outer)) {412 if (Document* document = static_cast<Document*>(outer->parentNode()))413 candidate.enclosingScrollableBox = static_cast<Node*>(document->ownerElement());414 415 } else if (isScrollableContainerNode(outer->parentNode()))416 candidate.enclosingScrollableBox = outer->parentNode();417 418 // Get distance and alignment from current candidate.419 distanceDataForNode(direction, focusedNode, candidate);420 421 // Bail out if distance is maximum.422 if (candidate.distance == maxDistance()) {423 node = node->traverseNextNode(outer->parentNode());424 continue;425 }426 427 updateFocusCandidateIfCloser(focusedNode, candidate, closest);428 }429 430 node = node->traverseNextNode(outer->parentNode());431 }432 }433 434 void FocusController::deepFindFocusableNodeInDirection(Node* container, Node* focusedNode,435 FocusDirection direction, KeyboardEvent* event,436 FocusCandidate& closest)437 {438 ASSERT(container->hasTagName(frameTag)439 || container->hasTagName(iframeTag)440 || isScrollableContainerNode(container));441 442 // Track if focusedNode is a descendant of the current container node being processed.443 bool descendantOfContainer = false;444 Node* firstChild = 0;445 446 // Iframe or Frame.447 if (container->hasTagName(frameTag) || container->hasTagName(iframeTag)) {448 449 HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(container);450 if (!owner->contentFrame())451 return;452 453 Document* innerDocument = owner->contentFrame()->document();454 if (!innerDocument)455 return;456 457 descendantOfContainer = isNodeDeepDescendantOfDocument(focusedNode, innerDocument);458 firstChild = innerDocument->firstChild();459 460 // Scrollable block elements (e.g. <div>, etc)461 } else if (isScrollableContainerNode(container)) {462 463 firstChild = container->firstChild();464 descendantOfContainer = focusedNode->isDescendantOf(container);465 }466 467 if (descendantOfContainer) {468 findFocusableNodeInDirection(firstChild, focusedNode, direction, event, closest);469 return;470 }471 472 // Check if the current container element itself is a good candidate473 // to move focus to. If it is, then we traverse its inner nodes.474 FocusCandidate candidateParent = FocusCandidate(container);475 distanceDataForNode(direction, focusedNode, candidateParent);476 477 // Bail out if distance is maximum.478 if (candidateParent.distance == maxDistance())479 return;480 481 // FIXME: Consider alignment?482 if (candidateParent.distance < closest.distance)483 findFocusableNodeInDirection(firstChild, focusedNode, direction, event, closest, candidateParent);484 }485 486 295 static bool relinquishesEditingFocus(Node *node) 487 296 { -
trunk/WebCore/page/FocusController.h
r72522 r72596 64 64 bool advanceFocusInDocumentOrder(FocusDirection, KeyboardEvent*, bool initialFocus); 65 65 66 void findFocusableNodeInDirection(Node* outter, Node*, FocusDirection, KeyboardEvent*,67 FocusCandidate& closestFocusCandidate,68 const FocusCandidate& parentCandidate = FocusCandidate());69 void deepFindFocusableNodeInDirection(Node* container, Node* focused, FocusDirection, KeyboardEvent*, FocusCandidate&);70 71 66 bool advanceFocusDirectionallyInContainer(Node* container, const IntRect& startingRect, FocusDirection, KeyboardEvent*); 72 67 void findFocusCandidateInContainer(Node* container, const IntRect& startingRect, FocusDirection, KeyboardEvent*, FocusCandidate& closest); -
trunk/WebCore/page/SpatialNavigation.cpp
r72522 r72596 42 42 namespace WebCore { 43 43 44 static long long spatialDistance(FocusDirection, const IntRect&, const IntRect&);45 static IntRect renderRectRelativeToRootDocument(RenderObject*);46 44 static RectsAlignment alignmentForRects(FocusDirection, const IntRect&, const IntRect&, const IntSize& viewSize); 47 45 static bool areRectsFullyAligned(FocusDirection, const IntRect&, const IntRect&); … … 50 48 static bool isRectInDirection(FocusDirection, const IntRect&, const IntRect&); 51 49 static void deflateIfOverlapped(IntRect&, IntRect&); 52 static bool checkNegativeCoordsForNode(Node*, const IntRect&);53 50 static IntRect rectToAbsoluteCoordinates(Frame* initialFrame, const IntRect& rect); 54 51 static void entryAndExitPointsForDirection(FocusDirection direction, const IntRect& startingRect, const IntRect& potentialRect, IntPoint& exitPoint, IntPoint& entryPoint); … … 69 66 { 70 67 return (frame && frame->settings() && frame->settings()->isSpatialNavigationEnabled()); 71 }72 73 void distanceDataForNode(FocusDirection direction, Node* start, FocusCandidate& candidate)74 {75 RenderObject* startRender = start->renderer();76 if (!startRender) {77 candidate.distance = maxDistance();78 return;79 }80 81 RenderObject* destRender = candidate.node->renderer();82 if (!destRender) {83 candidate.distance = maxDistance();84 return;85 }86 87 IntRect curRect = renderRectRelativeToRootDocument(startRender);88 IntRect targetRect = renderRectRelativeToRootDocument(destRender);89 90 // The bounding rectangle of two consecutive nodes can overlap. In such cases,91 // deflate both.92 deflateIfOverlapped(curRect, targetRect);93 94 // If empty rects or negative width or height, bail out.95 if (curRect.isEmpty() || targetRect.isEmpty()96 || targetRect.width() <= 0 || targetRect.height() <= 0) {97 candidate.distance = maxDistance();98 return;99 }100 101 // Negative coordinates can be used if node is scrolled up offscreen.102 if (!checkNegativeCoordsForNode(start, curRect)) {103 candidate.distance = maxDistance();104 return;105 }106 107 if (!checkNegativeCoordsForNode(candidate.node, targetRect)) {108 candidate.distance = maxDistance();109 return;110 }111 112 if (!isRectInDirection(direction, curRect, targetRect)) {113 candidate.distance = maxDistance();114 return;115 }116 117 // The distance between two nodes is not to be considered alone when evaluating/looking118 // for the best focus candidate node. Alignment of rects can be also a good point to be119 // considered in order to make the algorithm to behavior in a more intuitive way.120 IntSize viewSize = candidate.node->document()->page()->mainFrame()->view()->visibleContentRect().size();121 candidate.alignment = alignmentForRects(direction, curRect, targetRect, viewSize);122 candidate.distance = spatialDistance(direction, curRect, targetRect);123 }124 125 // FIXME: This function does not behave correctly with transformed frames.126 static IntRect renderRectRelativeToRootDocument(RenderObject* render)127 {128 ASSERT(render && render->node());129 130 IntRect rect = render->node()->getRect();131 132 // In cases when the |render|'s associated node is in a scrollable inner133 // document, we only consider its scrollOffset if it is not offscreen.134 Node* node = render->node();135 Document* mainDocument = node->document()->page()->mainFrame()->document();136 bool considerScrollOffset = !(hasOffscreenRect(node) && node->document() != mainDocument);137 138 if (considerScrollOffset) {139 if (FrameView* frameView = render->node()->document()->view())140 rect.move(-frameView->scrollOffset());141 }142 143 // Handle nested frames.144 for (Frame* frame = render->document()->frame(); frame; frame = frame->tree()->parent()) {145 if (Element* element = static_cast<Element*>(frame->ownerElement())) {146 do {147 rect.move(element->offsetLeft(), element->offsetTop());148 } while ((element = element->offsetParent()));149 }150 }151 152 return rect;153 68 } 154 69 … … 329 244 } 330 245 331 // * a = Current focused node's rect.332 // * b = Focus candidate node's rect.333 static long long spatialDistance(FocusDirection direction, const IntRect& a, const IntRect& b)334 {335 int x1 = 0, y1 = 0, x2 = 0, y2 = 0;336 337 if (direction == FocusDirectionLeft) {338 // #1 |--|339 //340 // #2 |--| |--|341 //342 // #3 |--|343 344 x1 = a.x();345 x2 = b.right();346 347 if (below(a, b)) {348 // #1 The a rect is below b.349 y1 = a.y();350 y2 = b.bottom();351 } else if (below(b, a)) {352 // #3 The b rect is below a.353 y1 = a.bottom();354 y2 = b.y();355 } else {356 // #2 Both b and a share some common y's.357 y1 = 0;358 y2 = 0;359 }360 } else if (direction == FocusDirectionRight) {361 // |--| #1362 //363 // |--| |--| #2364 //365 // |--| #3366 367 x1 = a.right();368 x2 = b.x();369 370 if (below(a, b)) {371 // #1 The b rect is above a.372 y1 = a.y();373 y2 = b.bottom();374 } else if (below(b, a)) {375 // #3 The b rect is below a.376 y1 = a.bottom();377 y2 = b.y();378 } else {379 // #2 Both b and a share some common y's.380 y1 = 0;381 y2 = 0;382 }383 } else if (direction == FocusDirectionUp) {384 //385 // #1 #2 #3386 //387 // |--| |--| |--|388 //389 // |--|390 391 y1 = a.y();392 y2 = b.bottom();393 394 if (rightOf(a, b)) {395 // #1 The b rect is to the left of a.396 x1 = a.x();397 x2 = b.right();398 } else if (rightOf(b, a)) {399 // #3 The b rect is to the right of a.400 x1 = a.right();401 x2 = b.x();402 } else {403 // #2 Both b and a share some common x's.404 x1 = 0;405 x2 = 0;406 }407 } else if (direction == FocusDirectionDown) {408 // |--|409 //410 // |--| |--| |--|411 //412 // #1 #2 #3413 414 y1 = a.bottom();415 y2 = b.y();416 417 if (rightOf(a, b)) {418 // #1 The b rect is to the left of a.419 x1 = a.x();420 x2 = b.right();421 } else if (rightOf(b, a)) {422 // #3 The b rect is to the right of a423 x1 = a.right();424 x2 = b.x();425 } else {426 // #2 Both b and a share some common x's.427 x1 = 0;428 x2 = 0;429 }430 }431 432 long long dx = x1 - x2;433 long long dy = y1 - y2;434 435 long long distance = (dx * dx) + (dy * dy);436 437 if (distance < 0)438 distance *= -1;439 440 return distance;441 }442 443 246 static bool isRectInDirection(FocusDirection direction, const IntRect& curRect, const IntRect& targetRect) 444 247 { … … 573 376 } 574 377 575 void scrollIntoView(Element* element)576 {577 // NOTE: Element's scrollIntoView method could had been used here, but578 // it is preferable to inflate |element|'s bounding rect a bit before579 // scrolling it for accurate reason.580 // Element's scrollIntoView method does not provide this flexibility.581 IntRect bounds = element->getRect();582 bounds.inflate(fudgeFactor());583 element->renderer()->enclosingLayer()->scrollRectToVisible(bounds);584 }585 586 bool isInRootDocument(Node* node)587 {588 if (!node)589 return false;590 591 Document* rootDocument = node->document()->page()->mainFrame()->document();592 return node->document() == rootDocument;593 }594 595 378 static void deflateIfOverlapped(IntRect& a, IntRect& b) 596 379 { … … 608 391 } 609 392 610 static bool checkNegativeCoordsForNode(Node* node, const IntRect& curRect)611 {612 ASSERT(node || node->renderer());613 614 if (curRect.x() >= 0 && curRect.y() >= 0)615 return true;616 617 bool canBeScrolled = false;618 619 RenderObject* renderer = node->renderer();620 for (; renderer; renderer = renderer->parent()) {621 if (renderer->isBox() && toRenderBox(renderer)->canBeScrolledAndHasScrollableArea()) {622 canBeScrolled = true;623 break;624 }625 }626 627 return canBeScrolled;628 }629 630 393 bool isScrollableContainerNode(const Node* node) 631 394 { … … 639 402 640 403 return false; 641 }642 643 bool isNodeDeepDescendantOfDocument(Node* node, Document* baseDocument)644 {645 if (!node || !baseDocument)646 return false;647 648 bool descendant = baseDocument == node->document();649 650 Element* currentElement = static_cast<Element*>(node);651 while (!descendant) {652 Element* documentOwner = currentElement->document()->ownerElement();653 if (!documentOwner)654 break;655 656 descendant = documentOwner->document() == baseDocument;657 currentElement = documentOwner;658 }659 660 return descendant;661 404 } 662 405 … … 878 621 } 879 622 880 bool canBeScrolledIntoView(FocusDirection direction, FocusCandidate& candidate)623 bool canBeScrolledIntoView(FocusDirection direction, const FocusCandidate& candidate) 881 624 { 882 625 ASSERT(candidate.node && hasOffscreenRect(candidate.node)); -
trunk/WebCore/page/SpatialNavigation.h
r72522 r72596 123 123 }; 124 124 125 void distanceDataForNode(FocusDirection direction, Node* start, FocusCandidate& candidate);126 125 bool scrollInDirection(Frame*, FocusDirection); 127 126 bool scrollInDirection(Node* container, FocusDirection); 128 void scrollIntoView(Element*);129 127 bool hasOffscreenRect(Node*, FocusDirection direction = FocusDirectionNone); 130 bool isInRootDocument(Node*);131 128 bool isScrollableContainerNode(const Node*); 132 129 bool isNodeDeepDescendantOfDocument(Node*, Document*); … … 137 134 IntRect frameRectInAbsoluteCoordinates(Frame*); 138 135 void distanceDataForNode(FocusDirection, FocusCandidate& current, FocusCandidate& candidate); 139 bool canBeScrolledIntoView(FocusDirection, FocusCandidate&);136 bool canBeScrolledIntoView(FocusDirection, const FocusCandidate&); 140 137 IntRect virtualRectForDirection(FocusDirection, const IntRect& startingRect); 141 138 } // namspace WebCore
Note: See TracChangeset
for help on using the changeset viewer.