| 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 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 SelectedMap() = default; | 155 SelectedMap() = default; |
| 156 SelectedMap(SelectedMap&& other) { | 156 SelectedMap(SelectedMap&& other) { |
| 157 object_map = std::move(other.object_map); | 157 object_map = std::move(other.object_map); |
| 158 block_map = std::move(other.block_map); | 158 block_map = std::move(other.block_map); |
| 159 } | 159 } |
| 160 | 160 |
| 161 private: | 161 private: |
| 162 DISALLOW_COPY_AND_ASSIGN(SelectedMap); | 162 DISALLOW_COPY_AND_ASSIGN(SelectedMap); |
| 163 }; | 163 }; |
| 164 | 164 |
| 165 static SelectedMap CollectSelectedMap( | 165 enum class CollectSelectedMapOption { |
| 166 const SelectionPaintRange& range, | 166 kCollectBlock, |
| 167 LayoutSelection::SelectionPaintInvalidationMode | 167 kNotCollectBlock, |
| 168 block_paint_invalidation_mode) { | 168 }; |
| 169 |
| 170 static SelectedMap CollectSelectedMap(const SelectionPaintRange& range, |
| 171 CollectSelectedMapOption option) { |
| 169 if (range.IsNull()) | 172 if (range.IsNull()) |
| 170 return SelectedMap(); | 173 return SelectedMap(); |
| 171 | 174 |
| 172 SelectedMap selected_map; | 175 SelectedMap selected_map; |
| 173 | 176 |
| 174 LayoutObject* const stop = | 177 LayoutObject* const stop = |
| 175 LayoutObjectAfterPosition(range.EndLayoutObject(), range.EndOffset()); | 178 LayoutObjectAfterPosition(range.EndLayoutObject(), range.EndOffset()); |
| 176 for (LayoutObject* runner = range.StartLayoutObject(); | 179 for (LayoutObject* runner = range.StartLayoutObject(); |
| 177 runner && (runner != stop); runner = runner->NextInPreOrder()) { | 180 runner && (runner != stop); runner = runner->NextInPreOrder()) { |
| 178 if (!runner->CanBeSelectionLeaf() && runner != range.StartLayoutObject() && | 181 if (!runner->CanBeSelectionLeaf() && runner != range.StartLayoutObject() && |
| 179 runner != range.EndLayoutObject()) | 182 runner != range.EndLayoutObject()) |
| 180 continue; | 183 continue; |
| 181 if (runner->GetSelectionState() == SelectionNone) | 184 if (runner->GetSelectionState() == SelectionNone) |
| 182 continue; | 185 continue; |
| 183 | 186 |
| 184 // Blocks are responsible for painting line gaps and margin gaps. They | 187 // Blocks are responsible for painting line gaps and margin gaps. They |
| 185 // must be examined as well. | 188 // must be examined as well. |
| 186 selected_map.object_map.Set(runner, runner->GetSelectionState()); | 189 selected_map.object_map.Set(runner, runner->GetSelectionState()); |
| 187 if (block_paint_invalidation_mode == | 190 if (option == CollectSelectedMapOption::kCollectBlock) { |
| 188 LayoutSelection::kPaintInvalidationNewXOROld) { | |
| 189 LayoutBlock* containing_block = runner->ContainingBlock(); | 191 LayoutBlock* containing_block = runner->ContainingBlock(); |
| 190 while (containing_block && !containing_block->IsLayoutView()) { | 192 while (containing_block && !containing_block->IsLayoutView()) { |
| 191 SelectedBlockMap::AddResult result = selected_map.block_map.insert( | 193 SelectedBlockMap::AddResult result = selected_map.block_map.insert( |
| 192 containing_block, containing_block->GetSelectionState()); | 194 containing_block, containing_block->GetSelectionState()); |
| 193 if (!result.is_new_entry) | 195 if (!result.is_new_entry) |
| 194 break; | 196 break; |
| 195 containing_block = containing_block->ContainingBlock(); | 197 containing_block = containing_block->ContainingBlock(); |
| 196 } | 198 } |
| 197 } | 199 } |
| 198 } | 200 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 214 LayoutObject* const stop = | 216 LayoutObject* const stop = |
| 215 LayoutObjectAfterPosition(range.EndLayoutObject(), range.EndOffset()); | 217 LayoutObjectAfterPosition(range.EndLayoutObject(), range.EndOffset()); |
| 216 for (LayoutObject* runner = range.StartLayoutObject(); | 218 for (LayoutObject* runner = range.StartLayoutObject(); |
| 217 runner && runner != stop; runner = runner->NextInPreOrder()) { | 219 runner && runner != stop; runner = runner->NextInPreOrder()) { |
| 218 if (runner != range.StartLayoutObject() && | 220 if (runner != range.StartLayoutObject() && |
| 219 runner != range.EndLayoutObject() && runner->CanBeSelectionLeaf()) | 221 runner != range.EndLayoutObject() && runner->CanBeSelectionLeaf()) |
| 220 runner->SetSelectionStateIfNeeded(SelectionInside); | 222 runner->SetSelectionStateIfNeeded(SelectionInside); |
| 221 } | 223 } |
| 222 } | 224 } |
| 223 | 225 |
| 224 void LayoutSelection::SetSelection( | 226 // Set SetSelectionState and ShouldInvalidateSelection flag of LayoutObjects |
| 225 const SelectionPaintRange& new_range, | 227 // comparing them in |new_range| and |old_range|. |
| 226 SelectionPaintInvalidationMode block_paint_invalidation_mode) { | 228 static void UpdateLayoutObjectState(const SelectionPaintRange& new_range, |
| 227 DCHECK(!new_range.IsNull()); | 229 const SelectionPaintRange& old_range) { |
| 228 | |
| 229 // Just return if the selection hasn't changed. | |
| 230 if (paint_range_ == new_range) | |
| 231 return; | |
| 232 | |
| 233 DCHECK(frame_selection_->GetDocument().GetLayoutView()->GetFrameView()); | |
| 234 DCHECK(!frame_selection_->GetDocument().NeedsLayoutTreeUpdate()); | |
| 235 | |
| 236 SelectedMap old_selected_map = | 230 SelectedMap old_selected_map = |
| 237 CollectSelectedMap(paint_range_, block_paint_invalidation_mode); | 231 CollectSelectedMap(old_range, CollectSelectedMapOption::kCollectBlock); |
| 238 | 232 |
| 239 // Now clear the selection. | 233 // Now clear the selection. |
| 240 for (auto layout_object : old_selected_map.object_map.Keys()) | 234 for (auto layout_object : old_selected_map.object_map.Keys()) |
| 241 layout_object->SetSelectionStateIfNeeded(SelectionNone); | 235 layout_object->SetSelectionStateIfNeeded(SelectionNone); |
| 242 | 236 |
| 243 SetSelectionState(new_range); | 237 SetSelectionState(new_range); |
| 244 | 238 |
| 245 // Now that the selection state has been updated for the new objects, walk | 239 // Now that the selection state has been updated for the new objects, walk |
| 246 // them again and put them in the new objects list. | 240 // them again and put them in the new objects list. |
| 247 // TODO(editing-dev): |new_selected_map| doesn't really need to store the | 241 // TODO(editing-dev): |new_selected_map| doesn't really need to store the |
| 248 // SelectionState, it's just more convenient to have it use the same data | 242 // SelectionState, it's just more convenient to have it use the same data |
| 249 // structure as |old_selected_map|. | 243 // structure as |old_selected_map|. |
| 250 SelectedMap new_selected_map = | 244 SelectedMap new_selected_map = |
| 251 CollectSelectedMap(new_range, kPaintInvalidationNewXOROld); | 245 CollectSelectedMap(new_range, CollectSelectedMapOption::kCollectBlock); |
| 252 | 246 |
| 253 // Have any of the old selected objects changed compared to the new selection? | 247 // Have any of the old selected objects changed compared to the new selection? |
| 254 for (const auto& pair : old_selected_map.object_map) { | 248 for (const auto& pair : old_selected_map.object_map) { |
| 255 LayoutObject* obj = pair.key; | 249 LayoutObject* obj = pair.key; |
| 256 SelectionState new_selection_state = obj->GetSelectionState(); | 250 SelectionState new_selection_state = obj->GetSelectionState(); |
| 257 SelectionState old_selection_state = pair.value; | 251 SelectionState old_selection_state = pair.value; |
| 258 if (new_selection_state != old_selection_state || | 252 if (new_selection_state != old_selection_state || |
| 259 (new_range.StartLayoutObject() == obj && | 253 (new_range.StartLayoutObject() == obj && |
| 260 new_range.StartOffset() != paint_range_.StartOffset()) || | 254 new_range.StartOffset() != old_range.StartOffset()) || |
| 261 (new_range.EndLayoutObject() == obj && | 255 (new_range.EndLayoutObject() == obj && |
| 262 new_range.EndOffset() != paint_range_.EndOffset())) { | 256 new_range.EndOffset() != old_range.EndOffset())) { |
| 263 obj->SetShouldInvalidateSelection(); | 257 obj->SetShouldInvalidateSelection(); |
| 264 new_selected_map.object_map.erase(obj); | 258 new_selected_map.object_map.erase(obj); |
| 265 } | 259 } |
| 266 } | 260 } |
| 267 | 261 |
| 268 // Any new objects that remain were not found in the old objects dict, and so | 262 // Any new objects that remain were not found in the old objects dict, and so |
| 269 // they need to be updated. | 263 // they need to be updated. |
| 270 for (auto layout_object : new_selected_map.object_map.Keys()) | 264 for (auto layout_object : new_selected_map.object_map.Keys()) |
| 271 layout_object->SetShouldInvalidateSelection(); | 265 layout_object->SetShouldInvalidateSelection(); |
| 272 | 266 |
| 273 // Have any of the old blocks changed? | 267 // Have any of the old blocks changed? |
| 274 for (const auto& pair : old_selected_map.block_map) { | 268 for (const auto& pair : old_selected_map.block_map) { |
| 275 LayoutBlock* block = pair.key; | 269 LayoutBlock* block = pair.key; |
| 276 SelectionState new_selection_state = block->GetSelectionState(); | 270 SelectionState new_selection_state = block->GetSelectionState(); |
| 277 SelectionState old_selection_state = pair.value; | 271 SelectionState old_selection_state = pair.value; |
| 278 if (new_selection_state != old_selection_state) { | 272 if (new_selection_state != old_selection_state) { |
| 279 block->SetShouldInvalidateSelection(); | 273 block->SetShouldInvalidateSelection(); |
| 280 new_selected_map.block_map.erase(block); | 274 new_selected_map.block_map.erase(block); |
| 281 } | 275 } |
| 282 } | 276 } |
| 283 | 277 |
| 284 // Any new blocks that remain were not found in the old blocks dict, and so | 278 // Any new blocks that remain were not found in the old blocks dict, and so |
| 285 // they need to be updated. | 279 // they need to be updated. |
| 286 for (auto layout_object : new_selected_map.block_map.Keys()) | 280 for (auto layout_object : new_selected_map.block_map.Keys()) |
| 287 layout_object->SetShouldInvalidateSelection(); | 281 layout_object->SetShouldInvalidateSelection(); |
| 288 | |
| 289 paint_range_ = new_range; | |
| 290 } | 282 } |
| 291 | 283 |
| 292 std::pair<int, int> LayoutSelection::SelectionStartEnd() { | 284 std::pair<int, int> LayoutSelection::SelectionStartEnd() { |
| 293 Commit(); | 285 Commit(); |
| 294 if (paint_range_.IsNull()) | 286 if (paint_range_.IsNull()) |
| 295 return std::make_pair(-1, -1); | 287 return std::make_pair(-1, -1); |
| 296 return std::make_pair(paint_range_.StartOffset(), paint_range_.EndOffset()); | 288 return std::make_pair(paint_range_.StartOffset(), paint_range_.EndOffset()); |
| 297 } | 289 } |
| 298 | 290 |
| 299 void LayoutSelection::ClearSelection() { | 291 void LayoutSelection::ClearSelection() { |
| 300 // For querying Layer::compositingState() | 292 // For querying Layer::compositingState() |
| 301 // This is correct, since destroying layout objects needs to cause eager paint | 293 // This is correct, since destroying layout objects needs to cause eager paint |
| 302 // invalidations. | 294 // invalidations. |
| 303 DisableCompositingQueryAsserts disabler; | 295 DisableCompositingQueryAsserts disabler; |
| 304 | 296 |
| 305 // Just return if the selection is already empty. | 297 // Just return if the selection is already empty. |
| 306 if (paint_range_.IsNull()) | 298 if (paint_range_.IsNull()) |
| 307 return; | 299 return; |
| 308 | 300 |
| 309 const SelectedMap& old_selected_map = | 301 const SelectedMap& old_selected_map = CollectSelectedMap( |
| 310 CollectSelectedMap(paint_range_, kPaintInvalidationNewMinusOld); | 302 paint_range_, CollectSelectedMapOption::kNotCollectBlock); |
| 311 // Clear SelectionState and invalidation. | 303 // Clear SelectionState and invalidation. |
| 312 for (auto layout_object : old_selected_map.object_map.Keys()) { | 304 for (auto layout_object : old_selected_map.object_map.Keys()) { |
| 313 const SelectionState old_state = layout_object->GetSelectionState(); | 305 const SelectionState old_state = layout_object->GetSelectionState(); |
| 314 layout_object->SetSelectionStateIfNeeded(SelectionNone); | 306 layout_object->SetSelectionStateIfNeeded(SelectionNone); |
| 315 if (layout_object->GetSelectionState() == old_state) | 307 if (layout_object->GetSelectionState() == old_state) |
| 316 continue; | 308 continue; |
| 317 layout_object->SetShouldInvalidateSelection(); | 309 layout_object->SetShouldInvalidateSelection(); |
| 318 } | 310 } |
| 319 | 311 |
| 320 // Reset selection. | 312 // Reset selection. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 if (start_pos.IsNull() || end_pos.IsNull() || | 354 if (start_pos.IsNull() || end_pos.IsNull() || |
| 363 selection.VisibleStart().DeepEquivalent() == | 355 selection.VisibleStart().DeepEquivalent() == |
| 364 selection.VisibleEnd().DeepEquivalent()) | 356 selection.VisibleEnd().DeepEquivalent()) |
| 365 return; | 357 return; |
| 366 DCHECK_LE(start_pos, end_pos); | 358 DCHECK_LE(start_pos, end_pos); |
| 367 LayoutObject* start_layout_object = start_pos.AnchorNode()->GetLayoutObject(); | 359 LayoutObject* start_layout_object = start_pos.AnchorNode()->GetLayoutObject(); |
| 368 LayoutObject* end_layout_object = end_pos.AnchorNode()->GetLayoutObject(); | 360 LayoutObject* end_layout_object = end_pos.AnchorNode()->GetLayoutObject(); |
| 369 if (!start_layout_object || !end_layout_object) | 361 if (!start_layout_object || !end_layout_object) |
| 370 return; | 362 return; |
| 371 DCHECK(start_layout_object->View() == end_layout_object->View()); | 363 DCHECK(start_layout_object->View() == end_layout_object->View()); |
| 372 SetSelection( | 364 |
| 373 SelectionPaintRange(start_layout_object, start_pos.ComputeEditingOffset(), | 365 const SelectionPaintRange new_range( |
| 374 end_layout_object, end_pos.ComputeEditingOffset())); | 366 start_layout_object, start_pos.ComputeEditingOffset(), end_layout_object, |
| 367 end_pos.ComputeEditingOffset()); |
| 368 // Just return if the selection hasn't changed. |
| 369 if (paint_range_ == new_range) |
| 370 return; |
| 371 |
| 372 DCHECK(frame_selection_->GetDocument().GetLayoutView()->GetFrameView()); |
| 373 DCHECK(!frame_selection_->GetDocument().NeedsLayoutTreeUpdate()); |
| 374 UpdateLayoutObjectState(new_range, paint_range_); |
| 375 paint_range_ = new_range; |
| 375 } | 376 } |
| 376 | 377 |
| 377 void LayoutSelection::OnDocumentShutdown() { | 378 void LayoutSelection::OnDocumentShutdown() { |
| 378 has_pending_selection_ = false; | 379 has_pending_selection_ = false; |
| 379 paint_range_ = SelectionPaintRange(); | 380 paint_range_ = SelectionPaintRange(); |
| 380 } | 381 } |
| 381 | 382 |
| 382 static LayoutRect SelectionRectForLayoutObject(const LayoutObject* object) { | 383 static LayoutRect SelectionRectForLayoutObject(const LayoutObject* object) { |
| 383 if (!object->IsRooted()) | 384 if (!object->IsRooted()) |
| 384 return LayoutRect(); | 385 return LayoutRect(); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 | 444 |
| 444 o->SetShouldInvalidateSelection(); | 445 o->SetShouldInvalidateSelection(); |
| 445 } | 446 } |
| 446 } | 447 } |
| 447 | 448 |
| 448 DEFINE_TRACE(LayoutSelection) { | 449 DEFINE_TRACE(LayoutSelection) { |
| 449 visitor->Trace(frame_selection_); | 450 visitor->Trace(frame_selection_); |
| 450 } | 451 } |
| 451 | 452 |
| 452 } // namespace blink | 453 } // namespace blink |
| OLD | NEW |