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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 int SelectionPaintRange::EndOffset() const { | 72 int SelectionPaintRange::EndOffset() const { |
73 DCHECK(!IsNull()); | 73 DCHECK(!IsNull()); |
74 return end_offset_; | 74 return end_offset_; |
75 } | 75 } |
76 | 76 |
77 LayoutSelection::LayoutSelection(FrameSelection& frame_selection) | 77 LayoutSelection::LayoutSelection(FrameSelection& frame_selection) |
78 : frame_selection_(&frame_selection), | 78 : frame_selection_(&frame_selection), |
79 has_pending_selection_(false), | 79 has_pending_selection_(false), |
80 paint_range_(SelectionPaintRange()) {} | 80 paint_range_(SelectionPaintRange()) {} |
81 | 81 |
82 SelectionInFlatTree LayoutSelection::CalcVisibleSelection( | 82 static SelectionInFlatTree CalcSelection( |
83 const VisibleSelectionInFlatTree& original_selection) const { | 83 const VisibleSelectionInFlatTree& original_selection, |
| 84 bool should_show_blok_cursor) { |
84 const PositionInFlatTree& start = original_selection.Start(); | 85 const PositionInFlatTree& start = original_selection.Start(); |
85 const PositionInFlatTree& end = original_selection.end(); | 86 const PositionInFlatTree& end = original_selection.end(); |
86 SelectionType selection_type = original_selection.GetSelectionType(); | 87 SelectionType selection_type = original_selection.GetSelectionType(); |
87 const TextAffinity affinity = original_selection.Affinity(); | 88 const TextAffinity affinity = original_selection.Affinity(); |
88 | 89 |
89 bool paint_block_cursor = | 90 bool paint_block_cursor = |
90 frame_selection_->ShouldShowBlockCursor() && | 91 should_show_blok_cursor && |
91 selection_type == SelectionType::kCaretSelection && | 92 selection_type == SelectionType::kCaretSelection && |
92 !IsLogicalEndOfLine(CreateVisiblePosition(end, affinity)); | 93 !IsLogicalEndOfLine(CreateVisiblePosition(end, affinity)); |
93 if (EnclosingTextControl(start.ComputeContainerNode())) { | 94 if (EnclosingTextControl(start.ComputeContainerNode())) { |
94 // TODO(yosin) We should use |PositionMoveType::CodePoint| to avoid | 95 // TODO(yosin) We should use |PositionMoveType::CodePoint| to avoid |
95 // ending paint at middle of character. | 96 // ending paint at middle of character. |
96 PositionInFlatTree end_position = | 97 PositionInFlatTree end_position = |
97 paint_block_cursor ? NextPositionOf(original_selection.Extent(), | 98 paint_block_cursor ? NextPositionOf(original_selection.Extent(), |
98 PositionMoveType::kCodeUnit) | 99 PositionMoveType::kCodeUnit) |
99 : end; | 100 : end; |
100 return SelectionInFlatTree::Builder() | 101 return SelectionInFlatTree::Builder() |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 layout_object->SetSelectionStateIfNeeded(SelectionState::kNone); | 309 layout_object->SetSelectionStateIfNeeded(SelectionState::kNone); |
309 if (layout_object->GetSelectionState() == old_state) | 310 if (layout_object->GetSelectionState() == old_state) |
310 continue; | 311 continue; |
311 layout_object->SetShouldInvalidateSelection(); | 312 layout_object->SetShouldInvalidateSelection(); |
312 } | 313 } |
313 | 314 |
314 // Reset selection. | 315 // Reset selection. |
315 paint_range_ = SelectionPaintRange(); | 316 paint_range_ = SelectionPaintRange(); |
316 } | 317 } |
317 | 318 |
318 void LayoutSelection::Commit() { | 319 static SelectionPaintRange CalcSelectionPaintRange( |
319 if (!HasPendingSelection()) | 320 const FrameSelection& frame_selection) { |
320 return; | |
321 has_pending_selection_ = false; | |
322 | |
323 const VisibleSelectionInFlatTree& original_selection = | 321 const VisibleSelectionInFlatTree& original_selection = |
324 frame_selection_->ComputeVisibleSelectionInFlatTree(); | 322 frame_selection.ComputeVisibleSelectionInFlatTree(); |
325 | |
326 // Construct a new VisibleSolution, since visibleSelection() is not | 323 // Construct a new VisibleSolution, since visibleSelection() is not |
327 // necessarily valid, and the following steps assume a valid selection. See | 324 // necessarily valid, and the following steps assume a valid selection. See |
328 // <https://bugs.webkit.org/show_bug.cgi?id=69563> and | 325 // <https://bugs.webkit.org/show_bug.cgi?id=69563> and |
329 // <rdar://problem/10232866>. | 326 // <rdar://problem/10232866>. |
| 327 const SelectionInFlatTree& new_selection = CalcSelection( |
| 328 original_selection, frame_selection.ShouldShowBlockCursor()); |
330 const VisibleSelectionInFlatTree& selection = | 329 const VisibleSelectionInFlatTree& selection = |
331 CreateVisibleSelection(CalcVisibleSelection(original_selection)); | 330 CreateVisibleSelection(new_selection); |
332 | 331 |
333 if (!selection.IsRange() || frame_selection_->IsHidden()) { | 332 if (!selection.IsRange() || frame_selection.IsHidden()) |
334 ClearSelection(); | 333 return SelectionPaintRange(); |
335 return; | 334 |
336 } | |
337 DCHECK(!selection.IsNone()); | 335 DCHECK(!selection.IsNone()); |
338 // Use the rightmost candidate for the start of the selection, and the | 336 // Use the rightmost candidate for the start of the selection, and the |
339 // leftmost candidate for the end of the selection. Example: foo <a>bar</a>. | 337 // leftmost candidate for the end of the selection. Example: foo <a>bar</a>. |
340 // Imagine that a line wrap occurs after 'foo', and that 'bar' is selected. | 338 // Imagine that a line wrap occurs after 'foo', and that 'bar' is selected. |
341 // If we pass [foo, 3] as the start of the selection, the selection painting | 339 // If we pass [foo, 3] as the start of the selection, the selection painting |
342 // code will think that content on the line containing 'foo' is selected | 340 // code will think that content on the line containing 'foo' is selected |
343 // and will fill the gap before 'bar'. | 341 // and will fill the gap before 'bar'. |
344 PositionInFlatTree start_pos = selection.Start(); | 342 PositionInFlatTree start_pos = selection.Start(); |
345 const PositionInFlatTree most_forward_start = | 343 const PositionInFlatTree most_forward_start = |
346 MostForwardCaretPosition(start_pos); | 344 MostForwardCaretPosition(start_pos); |
347 if (IsVisuallyEquivalentCandidate(most_forward_start)) | 345 if (IsVisuallyEquivalentCandidate(most_forward_start)) |
348 start_pos = most_forward_start; | 346 start_pos = most_forward_start; |
349 PositionInFlatTree end_pos = selection.end(); | 347 PositionInFlatTree end_pos = selection.end(); |
350 const PositionInFlatTree most_backward = MostBackwardCaretPosition(end_pos); | 348 const PositionInFlatTree most_backward = MostBackwardCaretPosition(end_pos); |
351 if (IsVisuallyEquivalentCandidate(most_backward)) | 349 if (IsVisuallyEquivalentCandidate(most_backward)) |
352 end_pos = most_backward; | 350 end_pos = most_backward; |
353 | 351 |
354 DCHECK(start_pos.IsNotNull()); | 352 DCHECK(start_pos.IsNotNull()); |
355 DCHECK(end_pos.IsNotNull()); | 353 DCHECK(end_pos.IsNotNull()); |
356 DCHECK_LE(start_pos, end_pos); | 354 DCHECK_LE(start_pos, end_pos); |
357 LayoutObject* start_layout_object = start_pos.AnchorNode()->GetLayoutObject(); | 355 LayoutObject* start_layout_object = start_pos.AnchorNode()->GetLayoutObject(); |
358 LayoutObject* end_layout_object = end_pos.AnchorNode()->GetLayoutObject(); | 356 LayoutObject* end_layout_object = end_pos.AnchorNode()->GetLayoutObject(); |
359 DCHECK(start_layout_object); | 357 DCHECK(start_layout_object); |
360 DCHECK(end_layout_object); | 358 DCHECK(end_layout_object); |
361 DCHECK(start_layout_object->View() == end_layout_object->View()); | 359 DCHECK(start_layout_object->View() == end_layout_object->View()); |
362 | 360 |
363 const SelectionPaintRange new_range( | 361 return SelectionPaintRange(start_layout_object, |
364 start_layout_object, start_pos.ComputeEditingOffset(), end_layout_object, | 362 start_pos.ComputeEditingOffset(), |
365 end_pos.ComputeEditingOffset()); | 363 end_layout_object, end_pos.ComputeEditingOffset()); |
| 364 } |
| 365 |
| 366 void LayoutSelection::Commit() { |
| 367 if (!HasPendingSelection()) |
| 368 return; |
| 369 has_pending_selection_ = false; |
| 370 |
| 371 const SelectionPaintRange& new_range = |
| 372 CalcSelectionPaintRange(*frame_selection_); |
| 373 if (new_range.IsNull()) { |
| 374 ClearSelection(); |
| 375 return; |
| 376 } |
366 // Just return if the selection hasn't changed. | 377 // Just return if the selection hasn't changed. |
367 if (paint_range_ == new_range) | 378 if (paint_range_ == new_range) |
368 return; | 379 return; |
369 | 380 |
370 DCHECK(frame_selection_->GetDocument().GetLayoutView()->GetFrameView()); | 381 DCHECK(frame_selection_->GetDocument().GetLayoutView()->GetFrameView()); |
371 DCHECK(!frame_selection_->GetDocument().NeedsLayoutTreeUpdate()); | 382 DCHECK(!frame_selection_->GetDocument().NeedsLayoutTreeUpdate()); |
372 UpdateLayoutObjectState(new_range, paint_range_); | 383 UpdateLayoutObjectState(new_range, paint_range_); |
373 paint_range_ = new_range; | 384 paint_range_ = new_range; |
374 } | 385 } |
375 | 386 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 | 453 |
443 o->SetShouldInvalidateSelection(); | 454 o->SetShouldInvalidateSelection(); |
444 } | 455 } |
445 } | 456 } |
446 | 457 |
447 DEFINE_TRACE(LayoutSelection) { | 458 DEFINE_TRACE(LayoutSelection) { |
448 visitor->Trace(frame_selection_); | 459 visitor->Trace(frame_selection_); |
449 } | 460 } |
450 | 461 |
451 } // namespace blink | 462 } // namespace blink |
OLD | NEW |