| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) | 2 * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) |
| 3 * Copyright (C) 2009 Antonio Gomes <tonikitoo@webkit.org> | 3 * Copyright (C) 2009 Antonio Gomes <tonikitoo@webkit.org> |
| 4 * | 4 * |
| 5 * All rights reserved. | 5 * All rights reserved. |
| 6 * | 6 * |
| 7 * Redistribution and use in source and binary forms, with or without | 7 * Redistribution and use in source and binary forms, with or without |
| 8 * modification, are permitted provided that the following conditions | 8 * modification, are permitted provided that the following conditions |
| 9 * are met: | 9 * are met: |
| 10 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 , distance(maxDistance()) | 56 , distance(maxDistance()) |
| 57 , isOffscreen(true) | 57 , isOffscreen(true) |
| 58 , isOffscreenAfterScrolling(true) | 58 , isOffscreenAfterScrolling(true) |
| 59 { | 59 { |
| 60 ASSERT(node); | 60 ASSERT(node); |
| 61 ASSERT(node->isElementNode()); | 61 ASSERT(node->isElementNode()); |
| 62 | 62 |
| 63 if (isHTMLAreaElement(*node)) { | 63 if (isHTMLAreaElement(*node)) { |
| 64 HTMLAreaElement& area = toHTMLAreaElement(*node); | 64 HTMLAreaElement& area = toHTMLAreaElement(*node); |
| 65 HTMLImageElement* image = area.imageElement(); | 65 HTMLImageElement* image = area.imageElement(); |
| 66 if (!image || !image->renderer()) | 66 if (!image || !image->layoutObject()) |
| 67 return; | 67 return; |
| 68 | 68 |
| 69 visibleNode = image; | 69 visibleNode = image; |
| 70 rect = virtualRectForAreaElementAndDirection(area, type); | 70 rect = virtualRectForAreaElementAndDirection(area, type); |
| 71 } else { | 71 } else { |
| 72 if (!node->renderer()) | 72 if (!node->layoutObject()) |
| 73 return; | 73 return; |
| 74 | 74 |
| 75 visibleNode = node; | 75 visibleNode = node; |
| 76 rect = nodeRectInAbsoluteCoordinates(node, true /* ignore border */); | 76 rect = nodeRectInAbsoluteCoordinates(node, true /* ignore border */); |
| 77 } | 77 } |
| 78 | 78 |
| 79 focusableNode = node; | 79 focusableNode = node; |
| 80 isOffscreen = hasOffscreenRect(visibleNode); | 80 isOffscreen = hasOffscreenRect(visibleNode); |
| 81 isOffscreenAfterScrolling = hasOffscreenRect(visibleNode, type); | 81 isOffscreenAfterScrolling = hasOffscreenRect(visibleNode, type); |
| 82 } | 82 } |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 containerViewportRect.setY(containerViewportRect.y() - ScrollableArea::p
ixelsPerLineStep()); | 172 containerViewportRect.setY(containerViewportRect.y() - ScrollableArea::p
ixelsPerLineStep()); |
| 173 containerViewportRect.setHeight(containerViewportRect.height() + Scrolla
bleArea::pixelsPerLineStep()); | 173 containerViewportRect.setHeight(containerViewportRect.height() + Scrolla
bleArea::pixelsPerLineStep()); |
| 174 break; | 174 break; |
| 175 case WebFocusTypeDown: | 175 case WebFocusTypeDown: |
| 176 containerViewportRect.setHeight(containerViewportRect.height() + Scrolla
bleArea::pixelsPerLineStep()); | 176 containerViewportRect.setHeight(containerViewportRect.height() + Scrolla
bleArea::pixelsPerLineStep()); |
| 177 break; | 177 break; |
| 178 default: | 178 default: |
| 179 break; | 179 break; |
| 180 } | 180 } |
| 181 | 181 |
| 182 LayoutObject* render = node->renderer(); | 182 LayoutObject* render = node->layoutObject(); |
| 183 if (!render) | 183 if (!render) |
| 184 return true; | 184 return true; |
| 185 | 185 |
| 186 LayoutRect rect(render->absoluteClippedOverflowRect()); | 186 LayoutRect rect(render->absoluteClippedOverflowRect()); |
| 187 if (rect.isEmpty()) | 187 if (rect.isEmpty()) |
| 188 return true; | 188 return true; |
| 189 | 189 |
| 190 return !containerViewportRect.intersects(rect); | 190 return !containerViewportRect.intersects(rect); |
| 191 } | 191 } |
| 192 | 192 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 b.inflate(deflateFactor); | 275 b.inflate(deflateFactor); |
| 276 } | 276 } |
| 277 | 277 |
| 278 bool isScrollableNode(const Node* node) | 278 bool isScrollableNode(const Node* node) |
| 279 { | 279 { |
| 280 ASSERT(!node->isDocumentNode()); | 280 ASSERT(!node->isDocumentNode()); |
| 281 | 281 |
| 282 if (!node) | 282 if (!node) |
| 283 return false; | 283 return false; |
| 284 | 284 |
| 285 if (LayoutObject* renderer = node->renderer()) | 285 if (LayoutObject* renderer = node->layoutObject()) |
| 286 return renderer->isBox() && toLayoutBox(renderer)->canBeScrolledAndHasSc
rollableArea() && node->hasChildren(); | 286 return renderer->isBox() && toLayoutBox(renderer)->canBeScrolledAndHasSc
rollableArea() && node->hasChildren(); |
| 287 | 287 |
| 288 return false; | 288 return false; |
| 289 } | 289 } |
| 290 | 290 |
| 291 Node* scrollableEnclosingBoxOrParentFrameForNodeInDirection(WebFocusType type, N
ode* node) | 291 Node* scrollableEnclosingBoxOrParentFrameForNodeInDirection(WebFocusType type, N
ode* node) |
| 292 { | 292 { |
| 293 ASSERT(node); | 293 ASSERT(node); |
| 294 Node* parent = node; | 294 Node* parent = node; |
| 295 do { | 295 do { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 307 { | 307 { |
| 308 ASSERT(container); | 308 ASSERT(container); |
| 309 if (container->isDocumentNode()) | 309 if (container->isDocumentNode()) |
| 310 return canScrollInDirection(toDocument(container)->frame(), type); | 310 return canScrollInDirection(toDocument(container)->frame(), type); |
| 311 | 311 |
| 312 if (!isScrollableNode(container)) | 312 if (!isScrollableNode(container)) |
| 313 return false; | 313 return false; |
| 314 | 314 |
| 315 switch (type) { | 315 switch (type) { |
| 316 case WebFocusTypeLeft: | 316 case WebFocusTypeLeft: |
| 317 return (container->renderer()->style()->overflowX() != OHIDDEN && contai
ner->layoutBox()->scrollLeft() > 0); | 317 return (container->layoutObject()->style()->overflowX() != OHIDDEN && co
ntainer->layoutBox()->scrollLeft() > 0); |
| 318 case WebFocusTypeUp: | 318 case WebFocusTypeUp: |
| 319 return (container->renderer()->style()->overflowY() != OHIDDEN && contai
ner->layoutBox()->scrollTop() > 0); | 319 return (container->layoutObject()->style()->overflowY() != OHIDDEN && co
ntainer->layoutBox()->scrollTop() > 0); |
| 320 case WebFocusTypeRight: | 320 case WebFocusTypeRight: |
| 321 return (container->renderer()->style()->overflowX() != OHIDDEN && contai
ner->layoutBox()->scrollLeft() + container->layoutBox()->clientWidth() < contain
er->layoutBox()->scrollWidth()); | 321 return (container->layoutObject()->style()->overflowX() != OHIDDEN && co
ntainer->layoutBox()->scrollLeft() + container->layoutBox()->clientWidth() < con
tainer->layoutBox()->scrollWidth()); |
| 322 case WebFocusTypeDown: | 322 case WebFocusTypeDown: |
| 323 return (container->renderer()->style()->overflowY() != OHIDDEN && contai
ner->layoutBox()->scrollTop() + container->layoutBox()->clientHeight() < contain
er->layoutBox()->scrollHeight()); | 323 return (container->layoutObject()->style()->overflowY() != OHIDDEN && co
ntainer->layoutBox()->scrollTop() + container->layoutBox()->clientHeight() < con
tainer->layoutBox()->scrollHeight()); |
| 324 default: | 324 default: |
| 325 ASSERT_NOT_REACHED(); | 325 ASSERT_NOT_REACHED(); |
| 326 return false; | 326 return false; |
| 327 } | 327 } |
| 328 } | 328 } |
| 329 | 329 |
| 330 bool canScrollInDirection(const LocalFrame* frame, WebFocusType type) | 330 bool canScrollInDirection(const LocalFrame* frame, WebFocusType type) |
| 331 { | 331 { |
| 332 if (!frame->view()) | 332 if (!frame->view()) |
| 333 return false; | 333 return false; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 for (; element; element = element->offsetParent()) | 369 for (; element; element = element->offsetParent()) |
| 370 rect.move(element->offsetLeft(), element->offsetTop()); | 370 rect.move(element->offsetLeft(), element->offsetTop()); |
| 371 rect.move((-toLocalFrame(frame)->view()->scrollOffset())); | 371 rect.move((-toLocalFrame(frame)->view()->scrollOffset())); |
| 372 } | 372 } |
| 373 } | 373 } |
| 374 return rect; | 374 return rect; |
| 375 } | 375 } |
| 376 | 376 |
| 377 LayoutRect nodeRectInAbsoluteCoordinates(Node* node, bool ignoreBorder) | 377 LayoutRect nodeRectInAbsoluteCoordinates(Node* node, bool ignoreBorder) |
| 378 { | 378 { |
| 379 ASSERT(node && node->renderer() && !node->document().view()->needsLayout()); | 379 ASSERT(node && node->layoutObject() && !node->document().view()->needsLayout
()); |
| 380 | 380 |
| 381 if (node->isDocumentNode()) | 381 if (node->isDocumentNode()) |
| 382 return frameRectInAbsoluteCoordinates(toDocument(node)->frame()); | 382 return frameRectInAbsoluteCoordinates(toDocument(node)->frame()); |
| 383 LayoutRect rect = rectToAbsoluteCoordinates(node->document().frame(), node->
boundingBox()); | 383 LayoutRect rect = rectToAbsoluteCoordinates(node->document().frame(), node->
boundingBox()); |
| 384 | 384 |
| 385 // For authors that use border instead of outline in their CSS, we compensat
e by ignoring the border when calculating | 385 // For authors that use border instead of outline in their CSS, we compensat
e by ignoring the border when calculating |
| 386 // the rect of the focused element. | 386 // the rect of the focused element. |
| 387 if (ignoreBorder) { | 387 if (ignoreBorder) { |
| 388 rect.move(node->renderer()->style()->borderLeftWidth(), node->renderer()
->style()->borderTopWidth()); | 388 rect.move(node->layoutObject()->style()->borderLeftWidth(), node->layout
Object()->style()->borderTopWidth()); |
| 389 rect.setWidth(rect.width() - node->renderer()->style()->borderLeftWidth(
) - node->renderer()->style()->borderRightWidth()); | 389 rect.setWidth(rect.width() - node->layoutObject()->style()->borderLeftWi
dth() - node->layoutObject()->style()->borderRightWidth()); |
| 390 rect.setHeight(rect.height() - node->renderer()->style()->borderTopWidth
() - node->renderer()->style()->borderBottomWidth()); | 390 rect.setHeight(rect.height() - node->layoutObject()->style()->borderTopW
idth() - node->layoutObject()->style()->borderBottomWidth()); |
| 391 } | 391 } |
| 392 return rect; | 392 return rect; |
| 393 } | 393 } |
| 394 | 394 |
| 395 LayoutRect frameRectInAbsoluteCoordinates(LocalFrame* frame) | 395 LayoutRect frameRectInAbsoluteCoordinates(LocalFrame* frame) |
| 396 { | 396 { |
| 397 return rectToAbsoluteCoordinates(frame, LayoutRect(frame->view()->visibleCon
tentRect())); | 397 return rectToAbsoluteCoordinates(frame, LayoutRect(frame->view()->visibleCon
tentRect())); |
| 398 } | 398 } |
| 399 | 399 |
| 400 // This method calculates the exitPoint from the startingRect and the entryPoint
into the candidate rect. | 400 // This method calculates the exitPoint from the startingRect and the entryPoint
into the candidate rect. |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 default: | 478 default: |
| 479 ASSERT_NOT_REACHED(); | 479 ASSERT_NOT_REACHED(); |
| 480 } | 480 } |
| 481 } | 481 } |
| 482 | 482 |
| 483 bool areElementsOnSameLine(const FocusCandidate& firstCandidate, const FocusCand
idate& secondCandidate) | 483 bool areElementsOnSameLine(const FocusCandidate& firstCandidate, const FocusCand
idate& secondCandidate) |
| 484 { | 484 { |
| 485 if (firstCandidate.isNull() || secondCandidate.isNull()) | 485 if (firstCandidate.isNull() || secondCandidate.isNull()) |
| 486 return false; | 486 return false; |
| 487 | 487 |
| 488 if (!firstCandidate.visibleNode->renderer() || !secondCandidate.visibleNode-
>renderer()) | 488 if (!firstCandidate.visibleNode->layoutObject() || !secondCandidate.visibleN
ode->layoutObject()) |
| 489 return false; | 489 return false; |
| 490 | 490 |
| 491 if (!firstCandidate.rect.intersects(secondCandidate.rect)) | 491 if (!firstCandidate.rect.intersects(secondCandidate.rect)) |
| 492 return false; | 492 return false; |
| 493 | 493 |
| 494 if (isHTMLAreaElement(*firstCandidate.focusableNode) || isHTMLAreaElement(*s
econdCandidate.focusableNode)) | 494 if (isHTMLAreaElement(*firstCandidate.focusableNode) || isHTMLAreaElement(*s
econdCandidate.focusableNode)) |
| 495 return false; | 495 return false; |
| 496 | 496 |
| 497 if (!firstCandidate.visibleNode->renderer()->isLayoutInline() || !secondCand
idate.visibleNode->renderer()->isLayoutInline()) | 497 if (!firstCandidate.visibleNode->layoutObject()->isLayoutInline() || !second
Candidate.visibleNode->layoutObject()->isLayoutInline()) |
| 498 return false; | 498 return false; |
| 499 | 499 |
| 500 if (firstCandidate.visibleNode->renderer()->containingBlock() != secondCandi
date.visibleNode->renderer()->containingBlock()) | 500 if (firstCandidate.visibleNode->layoutObject()->containingBlock() != secondC
andidate.visibleNode->layoutObject()->containingBlock()) |
| 501 return false; | 501 return false; |
| 502 | 502 |
| 503 return true; | 503 return true; |
| 504 } | 504 } |
| 505 | 505 |
| 506 void distanceDataForNode(WebFocusType type, const FocusCandidate& current, Focus
Candidate& candidate) | 506 void distanceDataForNode(WebFocusType type, const FocusCandidate& current, Focus
Candidate& candidate) |
| 507 { | 507 { |
| 508 if (areElementsOnSameLine(current, candidate)) { | 508 if (areElementsOnSameLine(current, candidate)) { |
| 509 if ((type == WebFocusTypeUp && current.rect.y() > candidate.rect.y()) ||
(type == WebFocusTypeDown && candidate.rect.y() > current.rect.y())) { | 509 if ((type == WebFocusTypeUp && current.rect.y() > candidate.rect.y()) ||
(type == WebFocusTypeDown && candidate.rect.y() > current.rect.y())) { |
| 510 candidate.distance = 0; | 510 candidate.distance = 0; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 568 candidate.distance = sqrt(euclidianDistancePow2) + navigationAxisDistance +
weightedOrthogonalAxisDistance - sqrt(overlap); | 568 candidate.distance = sqrt(euclidianDistancePow2) + navigationAxisDistance +
weightedOrthogonalAxisDistance - sqrt(overlap); |
| 569 } | 569 } |
| 570 | 570 |
| 571 bool canBeScrolledIntoView(WebFocusType type, const FocusCandidate& candidate) | 571 bool canBeScrolledIntoView(WebFocusType type, const FocusCandidate& candidate) |
| 572 { | 572 { |
| 573 ASSERT(candidate.visibleNode && candidate.isOffscreen); | 573 ASSERT(candidate.visibleNode && candidate.isOffscreen); |
| 574 LayoutRect candidateRect = candidate.rect; | 574 LayoutRect candidateRect = candidate.rect; |
| 575 for (Node* parentNode = candidate.visibleNode->parentNode(); parentNode; par
entNode = parentNode->parentNode()) { | 575 for (Node* parentNode = candidate.visibleNode->parentNode(); parentNode; par
entNode = parentNode->parentNode()) { |
| 576 LayoutRect parentRect = nodeRectInAbsoluteCoordinates(parentNode); | 576 LayoutRect parentRect = nodeRectInAbsoluteCoordinates(parentNode); |
| 577 if (!candidateRect.intersects(parentRect)) { | 577 if (!candidateRect.intersects(parentRect)) { |
| 578 if (((type == WebFocusTypeLeft || type == WebFocusTypeRight) && pare
ntNode->renderer()->style()->overflowX() == OHIDDEN) | 578 if (((type == WebFocusTypeLeft || type == WebFocusTypeRight) && pare
ntNode->layoutObject()->style()->overflowX() == OHIDDEN) |
| 579 || ((type == WebFocusTypeUp || type == WebFocusTypeDown) && pare
ntNode->renderer()->style()->overflowY() == OHIDDEN)) | 579 || ((type == WebFocusTypeUp || type == WebFocusTypeDown) && pare
ntNode->layoutObject()->style()->overflowY() == OHIDDEN)) |
| 580 return false; | 580 return false; |
| 581 } | 581 } |
| 582 if (parentNode == candidate.enclosingScrollableBox) | 582 if (parentNode == candidate.enclosingScrollableBox) |
| 583 return canScrollInDirection(parentNode, type); | 583 return canScrollInDirection(parentNode, type); |
| 584 } | 584 } |
| 585 return true; | 585 return true; |
| 586 } | 586 } |
| 587 | 587 |
| 588 // The starting rect is the rect of the focused node, in document coordinates. | 588 // The starting rect is the rect of the focused node, in document coordinates. |
| 589 // Compose a virtual starting rect if there is no focused node or if it is off s
creen. | 589 // Compose a virtual starting rect if there is no focused node or if it is off s
creen. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 612 } | 612 } |
| 613 | 613 |
| 614 return virtualStartingRect; | 614 return virtualStartingRect; |
| 615 } | 615 } |
| 616 | 616 |
| 617 LayoutRect virtualRectForAreaElementAndDirection(HTMLAreaElement& area, WebFocus
Type type) | 617 LayoutRect virtualRectForAreaElementAndDirection(HTMLAreaElement& area, WebFocus
Type type) |
| 618 { | 618 { |
| 619 ASSERT(area.imageElement()); | 619 ASSERT(area.imageElement()); |
| 620 // Area elements tend to overlap more than other focusable elements. We flat
ten the rect of the area elements | 620 // Area elements tend to overlap more than other focusable elements. We flat
ten the rect of the area elements |
| 621 // to minimize the effect of overlapping areas. | 621 // to minimize the effect of overlapping areas. |
| 622 LayoutRect rect = virtualRectForDirection(type, rectToAbsoluteCoordinates(ar
ea.document().frame(), area.computeRect(area.imageElement()->renderer())), 1); | 622 LayoutRect rect = virtualRectForDirection(type, rectToAbsoluteCoordinates(ar
ea.document().frame(), area.computeRect(area.imageElement()->layoutObject())), 1
); |
| 623 return rect; | 623 return rect; |
| 624 } | 624 } |
| 625 | 625 |
| 626 HTMLFrameOwnerElement* frameOwnerElement(FocusCandidate& candidate) | 626 HTMLFrameOwnerElement* frameOwnerElement(FocusCandidate& candidate) |
| 627 { | 627 { |
| 628 return candidate.isFrameOwnerElement() ? toHTMLFrameOwnerElement(candidate.v
isibleNode) : nullptr; | 628 return candidate.isFrameOwnerElement() ? toHTMLFrameOwnerElement(candidate.v
isibleNode) : nullptr; |
| 629 }; | 629 }; |
| 630 | 630 |
| 631 } // namespace blink | 631 } // namespace blink |
| OLD | NEW |