OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights | 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights |
4 * reserved. | 4 * reserved. |
5 * | 5 * |
6 * This library is free software; you can redistribute it and/or | 6 * This library is free software; you can redistribute it and/or |
7 * modify it under the terms of the GNU Library General Public | 7 * modify it under the terms of the GNU Library General Public |
8 * License as published by the Free Software Foundation; either | 8 * License as published by the Free Software Foundation; either |
9 * version 2 of the License, or (at your option) any later version. | 9 * version 2 of the License, or (at your option) any later version. |
10 * | 10 * |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 | 102 |
103 current_ = nullptr; | 103 current_ = nullptr; |
104 return *this; | 104 return *this; |
105 } | 105 } |
106 | 106 |
107 LayoutSelection::LayoutSelection(FrameSelection& frame_selection) | 107 LayoutSelection::LayoutSelection(FrameSelection& frame_selection) |
108 : frame_selection_(&frame_selection), | 108 : frame_selection_(&frame_selection), |
109 has_pending_selection_(false), | 109 has_pending_selection_(false), |
110 paint_range_(SelectionPaintRange()) {} | 110 paint_range_(SelectionPaintRange()) {} |
111 | 111 |
112 static SelectionInFlatTree CalcSelection( | 112 static bool ShouldShowBlockCursor(const FrameSelection& frame_selection, |
113 const VisibleSelectionInFlatTree& original_selection, | 113 const VisibleSelectionInFlatTree& selection) { |
114 bool should_show_blok_cursor) { | 114 if (!frame_selection.ShouldShowBlockCursor()) |
115 const PositionInFlatTree& start = original_selection.Start(); | 115 return false; |
116 const PositionInFlatTree& end = original_selection.End(); | 116 if (selection.GetSelectionType() != SelectionType::kCaretSelection) |
117 SelectionType selection_type = original_selection.GetSelectionType(); | 117 return false; |
118 const TextAffinity affinity = original_selection.Affinity(); | 118 if (IsLogicalEndOfLine(selection.VisibleEnd())) |
119 | 119 return false; |
120 bool paint_block_cursor = | 120 return true; |
121 should_show_blok_cursor && | |
122 selection_type == SelectionType::kCaretSelection && | |
123 !IsLogicalEndOfLine(CreateVisiblePosition(end, affinity)); | |
124 if (EnclosingTextControl(start.ComputeContainerNode())) { | |
125 // TODO(yosin) We should use |PositionMoveType::CodePoint| to avoid | |
126 // ending paint at middle of character. | |
127 PositionInFlatTree end_position = | |
128 paint_block_cursor ? NextPositionOf(original_selection.Extent(), | |
129 PositionMoveType::kCodeUnit) | |
130 : end; | |
131 return SelectionInFlatTree::Builder() | |
132 .SetBaseAndExtent(start, end_position) | |
133 .Build(); | |
134 } | |
135 | |
136 const VisiblePositionInFlatTree& visible_start = CreateVisiblePosition( | |
137 start, selection_type == SelectionType::kRangeSelection | |
138 ? TextAffinity::kDownstream | |
139 : affinity); | |
140 if (visible_start.IsNull()) | |
141 return SelectionInFlatTree(); | |
142 if (paint_block_cursor) { | |
143 const VisiblePositionInFlatTree visible_extent = NextPositionOf( | |
144 CreateVisiblePosition(end, affinity), kCanSkipOverEditingBoundary); | |
145 if (visible_extent.IsNull()) | |
146 return SelectionInFlatTree(); | |
147 SelectionInFlatTree::Builder builder; | |
148 builder.Collapse(visible_start.ToPositionWithAffinity()); | |
149 builder.Extend(visible_extent.DeepEquivalent()); | |
150 return builder.Build(); | |
151 } | |
152 const VisiblePositionInFlatTree visible_end = CreateVisiblePosition( | |
153 end, selection_type == SelectionType::kRangeSelection | |
154 ? TextAffinity::kUpstream | |
155 : affinity); | |
156 if (visible_end.IsNull()) | |
157 return SelectionInFlatTree(); | |
158 SelectionInFlatTree::Builder builder; | |
159 builder.Collapse(visible_start.ToPositionWithAffinity()); | |
160 builder.Extend(visible_end.DeepEquivalent()); | |
161 return builder.Build(); | |
162 } | 121 } |
163 | 122 |
| 123 static VisibleSelectionInFlatTree CalcSelection( |
| 124 const FrameSelection& frame_selection) { |
| 125 const VisibleSelectionInFlatTree& original_selection = |
| 126 frame_selection.ComputeVisibleSelectionInFlatTree(); |
164 | 127 |
| 128 if (!ShouldShowBlockCursor(frame_selection, original_selection)) |
| 129 return original_selection; |
| 130 |
| 131 const PositionInFlatTree end_position = NextPositionOf( |
| 132 original_selection.Start(), PositionMoveType::kGraphemeCluster); |
| 133 return CreateVisibleSelection( |
| 134 SelectionInFlatTree::Builder() |
| 135 .SetBaseAndExtent(original_selection.Start(), end_position) |
| 136 .Build()); |
| 137 } |
165 | 138 |
166 // Objects each have a single selection rect to examine. | 139 // Objects each have a single selection rect to examine. |
167 using SelectedObjectMap = HashMap<LayoutObject*, SelectionState>; | 140 using SelectedObjectMap = HashMap<LayoutObject*, SelectionState>; |
168 // Blocks contain selected objects and fill gaps between them, either on the | 141 // Blocks contain selected objects and fill gaps between them, either on the |
169 // left, right, or in between lines and blocks. | 142 // left, right, or in between lines and blocks. |
170 // In order to get the visual rect right, we have to examine left, middle, and | 143 // In order to get the visual rect right, we have to examine left, middle, and |
171 // right rects individually, since otherwise the union of those rects might | 144 // right rects individually, since otherwise the union of those rects might |
172 // remain the same even when changes have occurred. | 145 // remain the same even when changes have occurred. |
173 using SelectedBlockMap = HashMap<LayoutBlock*, SelectionState>; | 146 using SelectedBlockMap = HashMap<LayoutBlock*, SelectionState>; |
174 struct SelectedMap { | 147 struct SelectedMap { |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 paint_range_ = SelectionPaintRange(); | 290 paint_range_ = SelectionPaintRange(); |
318 } | 291 } |
319 | 292 |
320 static SelectionPaintRange CalcSelectionPaintRange( | 293 static SelectionPaintRange CalcSelectionPaintRange( |
321 const FrameSelection& frame_selection) { | 294 const FrameSelection& frame_selection) { |
322 const SelectionInDOMTree& selection_in_dom = | 295 const SelectionInDOMTree& selection_in_dom = |
323 frame_selection.GetSelectionInDOMTree(); | 296 frame_selection.GetSelectionInDOMTree(); |
324 if (selection_in_dom.IsNone()) | 297 if (selection_in_dom.IsNone()) |
325 return SelectionPaintRange(); | 298 return SelectionPaintRange(); |
326 | 299 |
327 const VisibleSelectionInFlatTree& original_selection = | 300 const VisibleSelectionInFlatTree& selection = CalcSelection(frame_selection); |
328 frame_selection.ComputeVisibleSelectionInFlatTree(); | |
329 // Construct a new VisibleSolution, since visibleSelection() is not | |
330 // necessarily valid, and the following steps assume a valid selection. See | |
331 // <https://bugs.webkit.org/show_bug.cgi?id=69563> and | |
332 // <rdar://problem/10232866>. | |
333 const SelectionInFlatTree& new_selection = CalcSelection( | |
334 original_selection, frame_selection.ShouldShowBlockCursor()); | |
335 const VisibleSelectionInFlatTree& selection = | |
336 CreateVisibleSelection(new_selection); | |
337 | |
338 if (!selection.IsRange() || frame_selection.IsHidden()) | 301 if (!selection.IsRange() || frame_selection.IsHidden()) |
339 return SelectionPaintRange(); | 302 return SelectionPaintRange(); |
340 | 303 |
341 DCHECK(!selection.IsNone()); | 304 DCHECK(!selection.IsNone()); |
342 const PositionInFlatTree start_pos = selection.Start(); | 305 const PositionInFlatTree start_pos = selection.Start(); |
343 const PositionInFlatTree end_pos = selection.End(); | 306 const PositionInFlatTree end_pos = selection.End(); |
344 DCHECK_LE(start_pos, end_pos); | 307 DCHECK_LE(start_pos, end_pos); |
345 LayoutObject* start_layout_object = start_pos.AnchorNode()->GetLayoutObject(); | 308 LayoutObject* start_layout_object = start_pos.AnchorNode()->GetLayoutObject(); |
346 LayoutObject* end_layout_object = end_pos.AnchorNode()->GetLayoutObject(); | 309 LayoutObject* end_layout_object = end_pos.AnchorNode()->GetLayoutObject(); |
347 DCHECK(start_layout_object); | 310 DCHECK(start_layout_object); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 | 378 |
416 runner->SetShouldInvalidateSelection(); | 379 runner->SetShouldInvalidateSelection(); |
417 } | 380 } |
418 } | 381 } |
419 | 382 |
420 DEFINE_TRACE(LayoutSelection) { | 383 DEFINE_TRACE(LayoutSelection) { |
421 visitor->Trace(frame_selection_); | 384 visitor->Trace(frame_selection_); |
422 } | 385 } |
423 | 386 |
424 } // namespace blink | 387 } // namespace blink |
OLD | NEW |