| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 Element* const editable = rootEditableElement(); | 160 Element* const editable = rootEditableElement(); |
| 161 if (!editable) | 161 if (!editable) |
| 162 return; | 162 return; |
| 163 | 163 |
| 164 const VisiblePosition position = | 164 const VisiblePosition position = |
| 165 visiblePositionForContentsPoint(point, frame()); | 165 visiblePositionForContentsPoint(point, frame()); |
| 166 SelectionInDOMTree::Builder builder; | 166 SelectionInDOMTree::Builder builder; |
| 167 builder.setIsDirectional(selection().isDirectional()); | 167 builder.setIsDirectional(selection().isDirectional()); |
| 168 if (position.isNotNull()) | 168 if (position.isNotNull()) |
| 169 builder.collapse(position.toPositionWithAffinity()); | 169 builder.collapse(position.toPositionWithAffinity()); |
| 170 setSelection(builder.build(), CloseTyping | ClearTypingStyle | UserTriggered); | 170 setSelection(builder.build(), |
| 171 CloseTyping | ClearTypingStyle | UserTriggered | HandleVisible); |
| 171 } | 172 } |
| 172 | 173 |
| 173 // TODO(xiaochengh): We should not use reference to return value. | 174 // TODO(xiaochengh): We should not use reference to return value. |
| 174 template <typename Strategy> | 175 template <typename Strategy> |
| 175 static void adjustEndpointsAtBidiBoundary( | 176 static void adjustEndpointsAtBidiBoundary( |
| 176 VisiblePositionTemplate<Strategy>& visibleBase, | 177 VisiblePositionTemplate<Strategy>& visibleBase, |
| 177 VisiblePositionTemplate<Strategy>& visibleExtent) { | 178 VisiblePositionTemplate<Strategy>& visibleExtent) { |
| 178 DCHECK(visibleBase.isValid()); | 179 DCHECK(visibleBase.isValid()); |
| 179 DCHECK(visibleExtent.isValid()); | 180 DCHECK(visibleExtent.isValid()); |
| 180 | 181 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 base.rightBoundaryOfBidiRun(extent.bidiLevelOnLeft()))) { | 220 base.rightBoundaryOfBidiRun(extent.bidiLevelOnLeft()))) { |
| 220 visibleExtent = createVisiblePosition(fromPositionInDOMTree<Strategy>( | 221 visibleExtent = createVisiblePosition(fromPositionInDOMTree<Strategy>( |
| 221 extent.positionAtRightBoundaryOfBiDiRun())); | 222 extent.positionAtRightBoundaryOfBiDiRun())); |
| 222 return; | 223 return; |
| 223 } | 224 } |
| 224 } | 225 } |
| 225 | 226 |
| 226 void FrameSelection::setNonDirectionalSelectionIfNeeded( | 227 void FrameSelection::setNonDirectionalSelectionIfNeeded( |
| 227 const VisibleSelectionInFlatTree& passedNewSelection, | 228 const VisibleSelectionInFlatTree& passedNewSelection, |
| 228 TextGranularity granularity, | 229 TextGranularity granularity, |
| 229 EndPointsAdjustmentMode endpointsAdjustmentMode) { | 230 EndPointsAdjustmentMode endpointsAdjustmentMode, |
| 231 HandleVisibility handleVisibility) { |
| 230 VisibleSelectionInFlatTree newSelection = passedNewSelection; | 232 VisibleSelectionInFlatTree newSelection = passedNewSelection; |
| 231 bool isDirectional = shouldAlwaysUseDirectionalSelection(m_frame) || | 233 bool isDirectional = shouldAlwaysUseDirectionalSelection(m_frame) || |
| 232 newSelection.isDirectional(); | 234 newSelection.isDirectional(); |
| 233 | 235 |
| 234 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets | 236 // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets |
| 235 // needs to be audited. See http://crbug.com/590369 for more details. | 237 // needs to be audited. See http://crbug.com/590369 for more details. |
| 236 document().updateStyleAndLayoutIgnorePendingStylesheets(); | 238 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 237 | 239 |
| 238 const PositionInFlatTree basePosition = | 240 const PositionInFlatTree basePosition = |
| 239 m_originalBaseInFlatTree.deepEquivalent(); | 241 m_originalBaseInFlatTree.deepEquivalent(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 257 newSelection.setExtent(newExtent); | 259 newSelection.setExtent(newExtent); |
| 258 } else if (originalBase.isNotNull()) { | 260 } else if (originalBase.isNotNull()) { |
| 259 if (visibleSelection<EditingInFlatTreeStrategy>().base() == | 261 if (visibleSelection<EditingInFlatTreeStrategy>().base() == |
| 260 newSelection.base()) | 262 newSelection.base()) |
| 261 newSelection.setBase(originalBase); | 263 newSelection.setBase(originalBase); |
| 262 m_originalBaseInFlatTree = VisiblePositionInFlatTree(); | 264 m_originalBaseInFlatTree = VisiblePositionInFlatTree(); |
| 263 } | 265 } |
| 264 | 266 |
| 265 // Adjusting base and extent will make newSelection always directional | 267 // Adjusting base and extent will make newSelection always directional |
| 266 newSelection.setIsDirectional(isDirectional); | 268 newSelection.setIsDirectional(isDirectional); |
| 267 if (visibleSelection<EditingInFlatTreeStrategy>() == newSelection) | 269 if (visibleSelection<EditingInFlatTreeStrategy>() == newSelection && |
| 270 m_handleVisibility == handleVisibility) |
| 268 return; | 271 return; |
| 269 | 272 |
| 270 const SetSelectionOptions options = CloseTyping | ClearTypingStyle; | 273 SetSelectionOptions options = CloseTyping | ClearTypingStyle; |
| 274 if (handleVisibility == HandleVisibility::Visible) |
| 275 options |= HandleVisible; |
| 271 setSelection(newSelection, options, CursorAlignOnScroll::IfNeeded, | 276 setSelection(newSelection, options, CursorAlignOnScroll::IfNeeded, |
| 272 granularity); | 277 granularity); |
| 273 } | 278 } |
| 274 | 279 |
| 275 template <typename Strategy> | 280 template <typename Strategy> |
| 276 void FrameSelection::setSelectionAlgorithm( | 281 void FrameSelection::setSelectionAlgorithm( |
| 277 const VisibleSelectionTemplate<Strategy>& newSelection, | 282 const VisibleSelectionTemplate<Strategy>& newSelection, |
| 278 SetSelectionOptions options, | 283 SetSelectionOptions options, |
| 279 CursorAlignOnScroll align, | 284 CursorAlignOnScroll align, |
| 280 TextGranularity granularity) { | 285 TextGranularity granularity) { |
| 281 DCHECK(isAvailable()); | 286 DCHECK(isAvailable()); |
| 282 DCHECK(newSelection.isValidFor(document())); | 287 DCHECK(newSelection.isValidFor(document())); |
| 283 const Document& currentDocument = document(); | 288 const Document& currentDocument = document(); |
| 284 if (m_granularityStrategy && | 289 if (m_granularityStrategy && |
| 285 (options & FrameSelection::DoNotClearStrategy) == 0) | 290 (options & FrameSelection::DoNotClearStrategy) == 0) |
| 286 m_granularityStrategy->Clear(); | 291 m_granularityStrategy->Clear(); |
| 287 bool closeTyping = options & CloseTyping; | 292 bool closeTyping = options & CloseTyping; |
| 288 bool shouldClearTypingStyle = options & ClearTypingStyle; | 293 bool shouldClearTypingStyle = options & ClearTypingStyle; |
| 294 const HandleVisibility handleVisibility = options & HandleVisible |
| 295 ? HandleVisibility::Visible |
| 296 : HandleVisibility::NotVisible; |
| 289 EUserTriggered userTriggered = selectionOptionsToUserTriggered(options); | 297 EUserTriggered userTriggered = selectionOptionsToUserTriggered(options); |
| 290 | 298 |
| 291 // TODO(editing-dev): We should rename variable |s| to another name to avoid | 299 // TODO(editing-dev): We should rename variable |s| to another name to avoid |
| 292 // using one letter variable name. | 300 // using one letter variable name. |
| 293 VisibleSelectionTemplate<Strategy> s = newSelection; | 301 VisibleSelectionTemplate<Strategy> s = newSelection; |
| 294 if (shouldAlwaysUseDirectionalSelection(m_frame)) | 302 if (shouldAlwaysUseDirectionalSelection(m_frame)) |
| 295 s.setIsDirectional(true); | 303 s.setIsDirectional(true); |
| 296 | 304 |
| 297 m_granularity = granularity; | 305 m_granularity = granularity; |
| 298 | 306 |
| 299 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to | 307 // TODO(yosin): We should move to call |TypingCommand::closeTyping()| to |
| 300 // |Editor| class. | 308 // |Editor| class. |
| 301 if (closeTyping) | 309 if (closeTyping) |
| 302 TypingCommand::closeTyping(m_frame); | 310 TypingCommand::closeTyping(m_frame); |
| 303 | 311 |
| 304 if (shouldClearTypingStyle) | 312 if (shouldClearTypingStyle) |
| 305 clearTypingStyle(); | 313 clearTypingStyle(); |
| 306 | 314 |
| 307 if (m_selectionEditor->visibleSelection<Strategy>() == s) { | 315 if (m_selectionEditor->visibleSelection<Strategy>() == s && |
| 316 m_handleVisibility == handleVisibility) { |
| 308 // Even if selection was not changed, selection offsets may have been | 317 // Even if selection was not changed, selection offsets may have been |
| 309 // changed. | 318 // changed. |
| 310 m_frame->inputMethodController().cancelCompositionIfSelectionIsInvalid(); | 319 m_frame->inputMethodController().cancelCompositionIfSelectionIsInvalid(); |
| 311 notifyLayoutObjectOfSelectionChange(userTriggered); | 320 notifyLayoutObjectOfSelectionChange(userTriggered); |
| 312 return; | 321 return; |
| 313 } | 322 } |
| 314 | 323 |
| 315 const VisibleSelectionTemplate<Strategy> oldSelection = | 324 const VisibleSelectionTemplate<Strategy> oldSelection = |
| 316 visibleSelection<Strategy>(); | 325 visibleSelection<Strategy>(); |
| 317 const Position& oldSelectionStart = selection().start(); | 326 const Position& oldSelectionStart = selection().start(); |
| 318 | 327 |
| 328 m_handleVisibility = handleVisibility; |
| 319 m_selectionEditor->setVisibleSelection(s, options); | 329 m_selectionEditor->setVisibleSelection(s, options); |
| 320 m_frameCaret->setCaretRectNeedsUpdate(); | 330 m_frameCaret->setCaretRectNeedsUpdate(); |
| 321 | 331 |
| 322 if (!s.isNone() && !(options & DoNotSetFocus)) { | 332 if (!s.isNone() && !(options & DoNotSetFocus)) { |
| 323 setFocusedNodeIfNeeded(); | 333 setFocusedNodeIfNeeded(); |
| 324 // |setFocusedNodeIfNeeded()| dispatches sync events "FocusOut" and | 334 // |setFocusedNodeIfNeeded()| dispatches sync events "FocusOut" and |
| 325 // "FocusIn", |m_frame| may associate to another document. | 335 // "FocusIn", |m_frame| may associate to another document. |
| 326 if (!isAvailable() || document() != currentDocument) { | 336 if (!isAvailable() || document() != currentDocument) { |
| 327 // Once we get test case to reach here, we should change this | 337 // Once we get test case to reach here, we should change this |
| 328 // if-statement to |DCHECK()|. | 338 // if-statement to |DCHECK()|. |
| (...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 843 | 853 |
| 844 void FrameSelection::dataWillChange(const CharacterData& node) { | 854 void FrameSelection::dataWillChange(const CharacterData& node) { |
| 845 m_frameCaret->dataWillChange(node); | 855 m_frameCaret->dataWillChange(node); |
| 846 } | 856 } |
| 847 | 857 |
| 848 void FrameSelection::paintCaret(GraphicsContext& context, | 858 void FrameSelection::paintCaret(GraphicsContext& context, |
| 849 const LayoutPoint& paintOffset) { | 859 const LayoutPoint& paintOffset) { |
| 850 m_frameCaret->paintCaret(context, paintOffset); | 860 m_frameCaret->paintCaret(context, paintOffset); |
| 851 } | 861 } |
| 852 | 862 |
| 853 bool FrameSelection::contains(const LayoutPoint& point) { | 863 bool FrameSelection::contains(const HitTestResult& result) { |
| 854 if (document().layoutViewItem().isNull()) | |
| 855 return false; | |
| 856 | |
| 857 // Treat a collapsed selection like no selection. | 864 // Treat a collapsed selection like no selection. |
| 858 const VisibleSelectionInFlatTree& visibleSelection = | 865 const VisibleSelectionInFlatTree& visibleSelection = |
| 859 this->visibleSelection<EditingInFlatTreeStrategy>(); | 866 this->visibleSelection<EditingInFlatTreeStrategy>(); |
| 860 if (!visibleSelection.isRange()) | 867 if (!visibleSelection.isRange()) |
| 861 return false; | 868 return false; |
| 862 | 869 |
| 863 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active); | |
| 864 HitTestResult result(request, point); | |
| 865 document().layoutViewItem().hitTest(result); | |
| 866 Node* innerNode = result.innerNode(); | 870 Node* innerNode = result.innerNode(); |
| 867 if (!innerNode || !innerNode->layoutObject()) | 871 if (!innerNode || !innerNode->layoutObject()) |
| 868 return false; | 872 return false; |
| 869 | 873 |
| 870 const VisiblePositionInFlatTree& visiblePos = | 874 const VisiblePositionInFlatTree& visiblePos = |
| 871 createVisiblePosition(fromPositionInDOMTree<EditingInFlatTreeStrategy>( | 875 createVisiblePosition(fromPositionInDOMTree<EditingInFlatTreeStrategy>( |
| 872 innerNode->layoutObject()->positionForPoint(result.localPoint()))); | 876 innerNode->layoutObject()->positionForPoint(result.localPoint()))); |
| 873 if (visiblePos.isNull()) | 877 if (visiblePos.isNull()) |
| 874 return false; | 878 return false; |
| 875 | 879 |
| 876 const VisiblePositionInFlatTree& visibleStart = | 880 const VisiblePositionInFlatTree& visibleStart = |
| 877 visibleSelection.visibleStart(); | 881 visibleSelection.visibleStart(); |
| 878 const VisiblePositionInFlatTree& visibleEnd = visibleSelection.visibleEnd(); | 882 const VisiblePositionInFlatTree& visibleEnd = visibleSelection.visibleEnd(); |
| 879 if (visibleStart.isNull() || visibleEnd.isNull()) | 883 if (visibleStart.isNull() || visibleEnd.isNull()) |
| 880 return false; | 884 return false; |
| 881 | 885 |
| 882 const PositionInFlatTree& start = visibleStart.deepEquivalent(); | 886 const PositionInFlatTree& start = visibleStart.deepEquivalent(); |
| 883 const PositionInFlatTree& end = visibleEnd.deepEquivalent(); | 887 const PositionInFlatTree& end = visibleEnd.deepEquivalent(); |
| 884 const PositionInFlatTree& pos = visiblePos.deepEquivalent(); | 888 const PositionInFlatTree& pos = visiblePos.deepEquivalent(); |
| 885 return start.compareTo(pos) <= 0 && pos.compareTo(end) <= 0; | 889 return start.compareTo(pos) <= 0 && pos.compareTo(end) <= 0; |
| 886 } | 890 } |
| 887 | 891 |
| 892 bool FrameSelection::contains(const LayoutPoint& point) { |
| 893 if (document().layoutViewItem().isNull()) |
| 894 return false; |
| 895 |
| 896 HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active); |
| 897 HitTestResult result(request, point); |
| 898 document().layoutViewItem().hitTest(result); |
| 899 |
| 900 return contains(result); |
| 901 } |
| 902 |
| 888 // Workaround for the fact that it's hard to delete a frame. | 903 // Workaround for the fact that it's hard to delete a frame. |
| 889 // Call this after doing user-triggered selections to make it easy to delete the | 904 // Call this after doing user-triggered selections to make it easy to delete the |
| 890 // frame you entirely selected. Can't do this implicitly as part of every | 905 // frame you entirely selected. Can't do this implicitly as part of every |
| 891 // setSelection call because in some contexts it might not be good for the focus | 906 // setSelection call because in some contexts it might not be good for the focus |
| 892 // to move to another frame. So instead we call it from places where we are | 907 // to move to another frame. So instead we call it from places where we are |
| 893 // selecting with the mouse or the keyboard after setting the selection. | 908 // selecting with the mouse or the keyboard after setting the selection. |
| 894 void FrameSelection::selectFrameElementInParentIfFullySelected() { | 909 void FrameSelection::selectFrameElementInParentIfFullySelected() { |
| 895 // Find the parent frame; if there is none, then we have nothing to do. | 910 // Find the parent frame; if there is none, then we have nothing to do. |
| 896 Frame* parent = m_frame->tree().parent(); | 911 Frame* parent = m_frame->tree().parent(); |
| 897 if (!parent) | 912 if (!parent) |
| (...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1417 } | 1432 } |
| 1418 | 1433 |
| 1419 void FrameSelection::moveRangeSelectionExtent(const IntPoint& contentsPoint) { | 1434 void FrameSelection::moveRangeSelectionExtent(const IntPoint& contentsPoint) { |
| 1420 if (isNone()) | 1435 if (isNone()) |
| 1421 return; | 1436 return; |
| 1422 | 1437 |
| 1423 VisibleSelection newSelection = | 1438 VisibleSelection newSelection = |
| 1424 granularityStrategy()->updateExtent(contentsPoint, m_frame); | 1439 granularityStrategy()->updateExtent(contentsPoint, m_frame); |
| 1425 setSelection(newSelection, | 1440 setSelection(newSelection, |
| 1426 FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle | | 1441 FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle | |
| 1427 FrameSelection::DoNotClearStrategy | UserTriggered, | 1442 FrameSelection::DoNotClearStrategy | UserTriggered | |
| 1443 FrameSelection::HandleVisible, |
| 1428 CursorAlignOnScroll::IfNeeded, CharacterGranularity); | 1444 CursorAlignOnScroll::IfNeeded, CharacterGranularity); |
| 1429 } | 1445 } |
| 1430 | 1446 |
| 1431 void FrameSelection::moveRangeSelection(const VisiblePosition& basePosition, | 1447 void FrameSelection::moveRangeSelection(const VisiblePosition& basePosition, |
| 1432 const VisiblePosition& extentPosition, | 1448 const VisiblePosition& extentPosition, |
| 1433 TextGranularity granularity) { | 1449 TextGranularity granularity) { |
| 1434 VisibleSelection newSelection = | 1450 VisibleSelection newSelection = |
| 1435 createVisibleSelection(basePosition, extentPosition); | 1451 createVisibleSelection(basePosition, extentPosition); |
| 1436 newSelection.expandUsingGranularity(granularity); | 1452 newSelection.expandUsingGranularity(granularity); |
| 1437 | 1453 |
| 1438 if (newSelection.isNone()) | 1454 if (newSelection.isNone()) |
| 1439 return; | 1455 return; |
| 1440 | 1456 |
| 1441 setSelection(newSelection, CloseTyping | ClearTypingStyle, | 1457 SetSelectionOptions options = CloseTyping | ClearTypingStyle; |
| 1442 CursorAlignOnScroll::IfNeeded, granularity); | 1458 if (isHandleVisible()) |
| 1459 options |= HandleVisible; |
| 1460 setSelection(newSelection, options, CursorAlignOnScroll::IfNeeded, |
| 1461 granularity); |
| 1443 } | 1462 } |
| 1444 | 1463 |
| 1445 void FrameSelection::updateIfNeeded() { | 1464 void FrameSelection::updateIfNeeded() { |
| 1446 DCHECK(!m_frame->document()->needsLayoutTreeUpdate()); | 1465 DCHECK(!m_frame->document()->needsLayoutTreeUpdate()); |
| 1447 m_selectionEditor->updateIfNeeded(); | 1466 m_selectionEditor->updateIfNeeded(); |
| 1448 } | 1467 } |
| 1449 | 1468 |
| 1450 void FrameSelection::setCaretVisible(bool caretIsVisible) { | 1469 void FrameSelection::setCaretVisible(bool caretIsVisible) { |
| 1451 m_frameCaret->setCaretVisibility(caretIsVisible ? CaretVisibility::Visible | 1470 m_frameCaret->setCaretVisibility(caretIsVisible ? CaretVisibility::Visible |
| 1452 : CaretVisibility::Hidden); | 1471 : CaretVisibility::Hidden); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1485 } | 1504 } |
| 1486 | 1505 |
| 1487 void showTree(const blink::FrameSelection* sel) { | 1506 void showTree(const blink::FrameSelection* sel) { |
| 1488 if (sel) | 1507 if (sel) |
| 1489 sel->showTreeForThis(); | 1508 sel->showTreeForThis(); |
| 1490 else | 1509 else |
| 1491 LOG(INFO) << "Cannot showTree for <null> FrameSelection."; | 1510 LOG(INFO) << "Cannot showTree for <null> FrameSelection."; |
| 1492 } | 1511 } |
| 1493 | 1512 |
| 1494 #endif | 1513 #endif |
| OLD | NEW |