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 |