| 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 const LayoutRect&); | 50 const LayoutRect&); |
| 51 static bool IsScrollableNode(const Node*); | 51 static bool IsScrollableNode(const Node*); |
| 52 | 52 |
| 53 FocusCandidate::FocusCandidate(Node* node, WebFocusType type) | 53 FocusCandidate::FocusCandidate(Node* node, WebFocusType type) |
| 54 : visible_node(nullptr), | 54 : visible_node(nullptr), |
| 55 focusable_node(nullptr), | 55 focusable_node(nullptr), |
| 56 enclosing_scrollable_box(nullptr), | 56 enclosing_scrollable_box(nullptr), |
| 57 distance(MaxDistance()), | 57 distance(MaxDistance()), |
| 58 is_offscreen(true), | 58 is_offscreen(true), |
| 59 is_offscreen_after_scrolling(true) { | 59 is_offscreen_after_scrolling(true) { |
| 60 ASSERT(node); | 60 DCHECK(node); |
| 61 ASSERT(node->IsElementNode()); | 61 DCHECK(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->GetLayoutObject()) | 66 if (!image || !image->GetLayoutObject()) |
| 67 return; | 67 return; |
| 68 | 68 |
| 69 visible_node = image; | 69 visible_node = image; |
| 70 rect = VirtualRectForAreaElementAndDirection(area, type); | 70 rect = VirtualRectForAreaElementAndDirection(area, type); |
| 71 } else { | 71 } else { |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 // document. In case it is, one can scroll in direction or take any different | 145 // document. In case it is, one can scroll in direction or take any different |
| 146 // desired action later on. | 146 // desired action later on. |
| 147 bool HasOffscreenRect(Node* node, WebFocusType type) { | 147 bool HasOffscreenRect(Node* node, WebFocusType type) { |
| 148 // Get the FrameView in which |node| is (which means the current viewport if | 148 // Get the FrameView in which |node| is (which means the current viewport if |
| 149 // |node| is not in an inner document), so we can check if its content rect is | 149 // |node| is not in an inner document), so we can check if its content rect is |
| 150 // visible before we actually move the focus to it. | 150 // visible before we actually move the focus to it. |
| 151 FrameView* frame_view = node->GetDocument().View(); | 151 FrameView* frame_view = node->GetDocument().View(); |
| 152 if (!frame_view) | 152 if (!frame_view) |
| 153 return true; | 153 return true; |
| 154 | 154 |
| 155 ASSERT(!frame_view->NeedsLayout()); | 155 DCHECK(!frame_view->NeedsLayout()); |
| 156 | 156 |
| 157 LayoutRect container_viewport_rect(frame_view->VisibleContentRect()); | 157 LayoutRect container_viewport_rect(frame_view->VisibleContentRect()); |
| 158 // We want to select a node if it is currently off screen, but will be | 158 // We want to select a node if it is currently off screen, but will be |
| 159 // exposed after we scroll. Adjust the viewport to post-scrolling position. | 159 // exposed after we scroll. Adjust the viewport to post-scrolling position. |
| 160 // If the container has overflow:hidden, we cannot scroll, so we do not pass | 160 // If the container has overflow:hidden, we cannot scroll, so we do not pass |
| 161 // direction and we do not adjust for scrolling. | 161 // direction and we do not adjust for scrolling. |
| 162 int pixels_per_line_step = | 162 int pixels_per_line_step = |
| 163 ScrollableArea::PixelsPerLineStep(frame_view->GetChromeClient()); | 163 ScrollableArea::PixelsPerLineStep(frame_view->GetChromeClient()); |
| 164 switch (type) { | 164 switch (type) { |
| 165 case kWebFocusTypeLeft: | 165 case kWebFocusTypeLeft: |
| (...skipping 25 matching lines...) Expand all Loading... |
| 191 return true; | 191 return true; |
| 192 | 192 |
| 193 LayoutRect rect(layout_object->AbsoluteVisualRect()); | 193 LayoutRect rect(layout_object->AbsoluteVisualRect()); |
| 194 if (rect.IsEmpty()) | 194 if (rect.IsEmpty()) |
| 195 return true; | 195 return true; |
| 196 | 196 |
| 197 return !container_viewport_rect.Intersects(rect); | 197 return !container_viewport_rect.Intersects(rect); |
| 198 } | 198 } |
| 199 | 199 |
| 200 bool ScrollInDirection(LocalFrame* frame, WebFocusType type) { | 200 bool ScrollInDirection(LocalFrame* frame, WebFocusType type) { |
| 201 ASSERT(frame); | 201 DCHECK(frame); |
| 202 | 202 |
| 203 if (frame && CanScrollInDirection(frame->GetDocument(), type)) { | 203 if (frame && CanScrollInDirection(frame->GetDocument(), type)) { |
| 204 int dx = 0; | 204 int dx = 0; |
| 205 int dy = 0; | 205 int dy = 0; |
| 206 int pixels_per_line_step = | 206 int pixels_per_line_step = |
| 207 ScrollableArea::PixelsPerLineStep(frame->View()->GetChromeClient()); | 207 ScrollableArea::PixelsPerLineStep(frame->View()->GetChromeClient()); |
| 208 switch (type) { | 208 switch (type) { |
| 209 case kWebFocusTypeLeft: | 209 case kWebFocusTypeLeft: |
| 210 dx = -pixels_per_line_step; | 210 dx = -pixels_per_line_step; |
| 211 break; | 211 break; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 223 return false; | 223 return false; |
| 224 } | 224 } |
| 225 | 225 |
| 226 frame->View()->ScrollBy(ScrollOffset(dx, dy), kUserScroll); | 226 frame->View()->ScrollBy(ScrollOffset(dx, dy), kUserScroll); |
| 227 return true; | 227 return true; |
| 228 } | 228 } |
| 229 return false; | 229 return false; |
| 230 } | 230 } |
| 231 | 231 |
| 232 bool ScrollInDirection(Node* container, WebFocusType type) { | 232 bool ScrollInDirection(Node* container, WebFocusType type) { |
| 233 ASSERT(container); | 233 DCHECK(container); |
| 234 if (container->IsDocumentNode()) | 234 if (container->IsDocumentNode()) |
| 235 return ScrollInDirection(ToDocument(container)->GetFrame(), type); | 235 return ScrollInDirection(ToDocument(container)->GetFrame(), type); |
| 236 | 236 |
| 237 if (!container->GetLayoutBox()) | 237 if (!container->GetLayoutBox()) |
| 238 return false; | 238 return false; |
| 239 | 239 |
| 240 if (CanScrollInDirection(container, type)) { | 240 if (CanScrollInDirection(container, type)) { |
| 241 int dx = 0; | 241 int dx = 0; |
| 242 int dy = 0; | 242 int dy = 0; |
| 243 // TODO(leviw): Why are these values truncated (toInt) instead of rounding? | 243 // TODO(leviw): Why are these values truncated (toInt) instead of rounding? |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 if ((a.Width() + 2 * deflate_factor > 0) && | 285 if ((a.Width() + 2 * deflate_factor > 0) && |
| 286 (a.Height() + 2 * deflate_factor > 0)) | 286 (a.Height() + 2 * deflate_factor > 0)) |
| 287 a.Inflate(deflate_factor); | 287 a.Inflate(deflate_factor); |
| 288 | 288 |
| 289 if ((b.Width() + 2 * deflate_factor > 0) && | 289 if ((b.Width() + 2 * deflate_factor > 0) && |
| 290 (b.Height() + 2 * deflate_factor > 0)) | 290 (b.Height() + 2 * deflate_factor > 0)) |
| 291 b.Inflate(deflate_factor); | 291 b.Inflate(deflate_factor); |
| 292 } | 292 } |
| 293 | 293 |
| 294 bool IsScrollableNode(const Node* node) { | 294 bool IsScrollableNode(const Node* node) { |
| 295 ASSERT(!node->IsDocumentNode()); | 295 DCHECK(!node->IsDocumentNode()); |
| 296 | 296 |
| 297 if (!node) | 297 if (!node) |
| 298 return false; | 298 return false; |
| 299 | 299 |
| 300 if (LayoutObject* layout_object = node->GetLayoutObject()) | 300 if (LayoutObject* layout_object = node->GetLayoutObject()) |
| 301 return layout_object->IsBox() && | 301 return layout_object->IsBox() && |
| 302 ToLayoutBox(layout_object)->CanBeScrolledAndHasScrollableArea() && | 302 ToLayoutBox(layout_object)->CanBeScrolledAndHasScrollableArea() && |
| 303 node->hasChildren(); | 303 node->hasChildren(); |
| 304 | 304 |
| 305 return false; | 305 return false; |
| 306 } | 306 } |
| 307 | 307 |
| 308 Node* ScrollableEnclosingBoxOrParentFrameForNodeInDirection(WebFocusType type, | 308 Node* ScrollableEnclosingBoxOrParentFrameForNodeInDirection(WebFocusType type, |
| 309 Node* node) { | 309 Node* node) { |
| 310 ASSERT(node); | 310 DCHECK(node); |
| 311 Node* parent = node; | 311 Node* parent = node; |
| 312 do { | 312 do { |
| 313 // FIXME: Spatial navigation is broken for OOPI. | 313 // FIXME: Spatial navigation is broken for OOPI. |
| 314 if (parent->IsDocumentNode()) | 314 if (parent->IsDocumentNode()) |
| 315 parent = ToDocument(parent)->GetFrame()->DeprecatedLocalOwner(); | 315 parent = ToDocument(parent)->GetFrame()->DeprecatedLocalOwner(); |
| 316 else | 316 else |
| 317 parent = parent->ParentOrShadowHostNode(); | 317 parent = parent->ParentOrShadowHostNode(); |
| 318 } while (parent && !CanScrollInDirection(parent, type) && | 318 } while (parent && !CanScrollInDirection(parent, type) && |
| 319 !parent->IsDocumentNode()); | 319 !parent->IsDocumentNode()); |
| 320 | 320 |
| 321 return parent; | 321 return parent; |
| 322 } | 322 } |
| 323 | 323 |
| 324 bool CanScrollInDirection(const Node* container, WebFocusType type) { | 324 bool CanScrollInDirection(const Node* container, WebFocusType type) { |
| 325 ASSERT(container); | 325 DCHECK(container); |
| 326 if (container->IsDocumentNode()) | 326 if (container->IsDocumentNode()) |
| 327 return CanScrollInDirection(ToDocument(container)->GetFrame(), type); | 327 return CanScrollInDirection(ToDocument(container)->GetFrame(), type); |
| 328 | 328 |
| 329 if (!IsScrollableNode(container)) | 329 if (!IsScrollableNode(container)) |
| 330 return false; | 330 return false; |
| 331 | 331 |
| 332 switch (type) { | 332 switch (type) { |
| 333 case kWebFocusTypeLeft: | 333 case kWebFocusTypeLeft: |
| 334 return (container->GetLayoutObject()->Style()->OverflowX() != | 334 return (container->GetLayoutObject()->Style()->OverflowX() != |
| 335 EOverflow::kHidden && | 335 EOverflow::kHidden && |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 669 break; | 669 break; |
| 670 default: | 670 default: |
| 671 NOTREACHED(); | 671 NOTREACHED(); |
| 672 } | 672 } |
| 673 | 673 |
| 674 return virtual_starting_rect; | 674 return virtual_starting_rect; |
| 675 } | 675 } |
| 676 | 676 |
| 677 LayoutRect VirtualRectForAreaElementAndDirection(HTMLAreaElement& area, | 677 LayoutRect VirtualRectForAreaElementAndDirection(HTMLAreaElement& area, |
| 678 WebFocusType type) { | 678 WebFocusType type) { |
| 679 ASSERT(area.ImageElement()); | 679 DCHECK(area.ImageElement()); |
| 680 // Area elements tend to overlap more than other focusable elements. We | 680 // Area elements tend to overlap more than other focusable elements. We |
| 681 // flatten the rect of the area elements to minimize the effect of overlapping | 681 // flatten the rect of the area elements to minimize the effect of overlapping |
| 682 // areas. | 682 // areas. |
| 683 LayoutRect rect = VirtualRectForDirection( | 683 LayoutRect rect = VirtualRectForDirection( |
| 684 type, | 684 type, |
| 685 RectToAbsoluteCoordinates( | 685 RectToAbsoluteCoordinates( |
| 686 area.GetDocument().GetFrame(), | 686 area.GetDocument().GetFrame(), |
| 687 area.ComputeAbsoluteRect(area.ImageElement()->GetLayoutObject())), | 687 area.ComputeAbsoluteRect(area.ImageElement()->GetLayoutObject())), |
| 688 LayoutUnit(1)); | 688 LayoutUnit(1)); |
| 689 return rect; | 689 return rect; |
| 690 } | 690 } |
| 691 | 691 |
| 692 HTMLFrameOwnerElement* FrameOwnerElement(FocusCandidate& candidate) { | 692 HTMLFrameOwnerElement* FrameOwnerElement(FocusCandidate& candidate) { |
| 693 return candidate.IsFrameOwnerElement() | 693 return candidate.IsFrameOwnerElement() |
| 694 ? ToHTMLFrameOwnerElement(candidate.visible_node) | 694 ? ToHTMLFrameOwnerElement(candidate.visible_node) |
| 695 : nullptr; | 695 : nullptr; |
| 696 }; | 696 }; |
| 697 | 697 |
| 698 } // namespace blink | 698 } // namespace blink |
| OLD | NEW |