Changeset 163920 in webkit
- Timestamp:
- Feb 11, 2014 5:53:03 PM (10 years ago)
- Location:
- trunk/Source
- Files:
-
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r163919 r163920 1 2014-02-11 Ryosuke Niwa <rniwa@webkit.org> 2 3 Frame::rectForSelection shouldn't instantiate FrameSelection 4 https://bugs.webkit.org/show_bug.cgi?id=128587 5 6 Reviewed by Enrica Casucci. 7 8 Made VisiblePosition::absoluteCaretBounds more interoperable with the one in FrameSelection and made 9 iOS's Frame::rectForScrollToVisible use that function instead. 10 11 The above change allows us to remove: 12 - suppressCloseTyping(), restoreCloseTyping(), and m_closeTypingSuppressions in FrameSelection 13 - suppressSelectionNotifications() and restoreSelectionNotifications() in EditorClient 14 15 See inline comments below for more details. 16 17 * Source/WebCore/WebCore.exp.in: 18 19 * editing/FrameSelection.cpp: 20 (WebCore::FrameSelection::FrameSelection): 21 (WebCore::FrameSelection::setSelectionWithoutUpdatingAppearance): 22 (WebCore::CaretBase::updateCaretRect): 23 (WebCore::FrameSelection::caretRendererWithoutUpdatingLayout): 24 (WebCore::DragCaretController::caretRenderer): 25 (WebCore::repaintCaretForLocalRect): 26 (WebCore::FrameSelection::recomputeCaretRect): Merged FrameSelection::localCaretRect(). Modified 27 the code to update caretNode when and only when caret rect is updated. Also added an assertion to 28 ensure absoluteCaretBounds() on FrameSelection and VisiblePosition yield the same result. 29 30 (WebCore::CaretBase::paintCaret): 31 * editing/FrameSelection.h: 32 33 * editing/VisiblePosition.cpp: 34 (WebCore::VisiblePosition::absoluteCaretBounds): Fixed the bug where the old code wasn't respecting 35 the convention to use containing block as the renderer to paint caret. 36 37 * editing/htmlediting.cpp: 38 (WebCore::caretRendersInsideNode): Moved from FrameSelection.cpp. 39 (WebCore::rendererForCaretPainting): Ditto and renamed from caretRenderer. 40 (WebCore::localCaretRectInRendererForCaretPainting): Extracted from FrameSelection::updateCaretRect. 41 (WebCore::absoluteBoundsForLocalCaretRect): Ditto from CaretBase::absoluteBoundsForLocalRect. 42 * editing/htmlediting.h: 43 44 * loader/EmptyClients.h: 45 * page/EditorClient.h: 46 * page/Frame.h: 47 48 * page/ios/FrameIOS.mm: 49 (WebCore::Frame::rectForScrollToVisible): Reimplemented in its simplest form using VisiblePosition's 50 absoluteCaretBounds(). 51 1 52 2014-02-11 Enrica Casucci <enrica@apple.com> 2 53 -
trunk/Source/WebCore/WebCore.exp.in
r163919 r163920 2538 2538 __ZNK7WebCore5Frame15innerLineHeightEP7DOMNode 2539 2539 __ZNK7WebCore5Frame15preferredHeightEv 2540 __ZNK7WebCore5Frame16rectForSelectionERNS_16VisibleSelectionE2541 2540 __ZNK7WebCore5Frame18renderRectForPointE7CGPointPbPf 2542 2541 __ZNK7WebCore5Frame19rangedSelectionBaseEv -
trunk/Source/WebCore/editing/FrameSelection.cpp
r163739 r163920 120 120 , m_updateAppearanceEnabled(false) 121 121 , m_caretBlinks(true) 122 , m_closeTypingSuppressions(0)123 122 , m_scrollingSuppressCount(0) 124 123 #endif … … 279 278 m_granularity = granularity; 280 279 281 #if PLATFORM(IOS)282 if (closeTyping && m_closeTypingSuppressions == 0)283 #else284 280 if (closeTyping) 285 #endif286 281 TypingCommand::closeTyping(m_frame); 287 282 … … 1288 1283 } 1289 1284 1290 static inline bool caretRendersInsideNode(Node* node)1291 {1292 return node && !isRenderedTable(node) && !editingIgnoresContent(node);1293 }1294 1295 static RenderObject* caretRenderer(Node* node)1296 {1297 if (!node)1298 return 0;1299 1300 RenderObject* renderer = node->renderer();1301 if (!renderer)1302 return 0;1303 1304 // if caretNode is a block and caret is inside it then caret should be painted by that block1305 bool paintedByBlock = renderer->isRenderBlockFlow() && caretRendersInsideNode(node);1306 return paintedByBlock ? renderer : renderer->containingBlock();1307 }1308 1309 1285 bool CaretBase::updateCaretRect(Document* document, const VisiblePosition& caretPosition) 1310 1286 { 1311 1287 document->updateLayoutIgnorePendingStylesheets(); 1312 m_caretLocalRect = LayoutRect();1313 1314 1288 m_caretRectNeedsUpdate = false; 1315 1316 if (caretPosition.isNull())1317 return false;1318 1319 ASSERT(caretPosition.deepEquivalent().deprecatedNode()->renderer());1320 1321 // First compute a rect local to the renderer at the selection start.1322 1289 RenderObject* renderer; 1323 LayoutRect localRect = caretPosition.localCaretRect(renderer); 1324 1325 // Get the renderer that will be responsible for painting the caret 1326 // (which is either the renderer we just found, or one of its containers). 1327 RenderObject* caretPainter = caretRenderer(caretPosition.deepEquivalent().deprecatedNode()); 1328 1329 // Compute an offset between the renderer and the caretPainter. 1330 bool unrooted = false; 1331 while (renderer != caretPainter) { 1332 RenderObject* containerObject = renderer->container(); 1333 if (!containerObject) { 1334 unrooted = true; 1335 break; 1336 } 1337 localRect.move(renderer->offsetFromContainer(containerObject, localRect.location())); 1338 renderer = containerObject; 1339 } 1340 1341 if (!unrooted) 1342 m_caretLocalRect = localRect; 1343 1344 return true; 1290 m_caretLocalRect = localCaretRectInRendererForCaretPainting(caretPosition, renderer); 1291 return !m_caretLocalRect.isEmpty(); 1345 1292 } 1346 1293 1347 1294 RenderObject* FrameSelection::caretRendererWithoutUpdatingLayout() const 1348 1295 { 1349 return WebCore::caretRenderer(m_selection.start().deprecatedNode());1296 return rendererForCaretPainting(m_selection.start().deprecatedNode()); 1350 1297 } 1351 1298 1352 1299 RenderObject* DragCaretController::caretRenderer() const 1353 1300 { 1354 return WebCore::caretRenderer(m_position.deepEquivalent().deprecatedNode());1301 return rendererForCaretPainting(m_position.deepEquivalent().deprecatedNode()); 1355 1302 } 1356 1303 … … 1360 1307 } 1361 1308 1362 LayoutRect FrameSelection::localCaretRect() 1363 { 1309 IntRect FrameSelection::absoluteCaretBounds() 1310 { 1311 recomputeCaretRect(); 1312 return m_absCaretBounds; 1313 } 1314 1315 static void repaintCaretForLocalRect(Node* node, const LayoutRect& rect) 1316 { 1317 RenderObject* caretPainter = rendererForCaretPainting(node); 1318 if (!caretPainter) 1319 return; 1320 1321 caretPainter->repaintRectangle(rect); 1322 } 1323 1324 bool FrameSelection::recomputeCaretRect() 1325 { 1326 if (!shouldUpdateCaretRect()) 1327 return false; 1328 1329 if (!m_frame) 1330 return false; 1331 1332 FrameView* v = m_frame->document()->view(); 1333 if (!v) 1334 return false; 1335 1336 LayoutRect oldRect = localCaretRectWithoutUpdate(); 1337 1338 RefPtr<Node> caretNode = m_previousCaretNode; 1364 1339 if (shouldUpdateCaretRect()) { 1365 1340 if (!isNonOrphanedCaret(m_selection)) 1366 1341 clearCaretRect(); 1367 else if (updateCaretRect(m_frame->document(), VisiblePosition(m_selection.start(), m_selection.affinity()))) 1368 m_absCaretBoundsDirty = true; 1369 } 1370 1371 return localCaretRectWithoutUpdate(); 1372 } 1373 1374 IntRect CaretBase::absoluteBoundsForLocalRect(Node* node, const LayoutRect& rect) const 1375 { 1376 RenderObject* caretPainter = caretRenderer(node); 1377 if (!caretPainter) 1378 return IntRect(); 1379 1380 LayoutRect localRect(rect); 1381 if (caretPainter->isBox()) 1382 toRenderBox(caretPainter)->flipForWritingMode(localRect); 1383 return caretPainter->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox(); 1384 } 1385 1386 IntRect FrameSelection::absoluteCaretBounds() 1387 { 1388 recomputeCaretRect(); 1389 return m_absCaretBounds; 1390 } 1391 1392 static void repaintCaretForLocalRect(Node* node, const LayoutRect& rect) 1393 { 1394 RenderObject* caretPainter = caretRenderer(node); 1395 if (!caretPainter) 1396 return; 1397 1398 caretPainter->repaintRectangle(rect); 1399 } 1400 1401 bool FrameSelection::recomputeCaretRect() 1402 { 1403 if (!shouldUpdateCaretRect()) 1404 return false; 1405 1406 if (!m_frame) 1407 return false; 1408 1409 FrameView* v = m_frame->document()->view(); 1410 if (!v) 1411 return false; 1412 1413 Node* caretNode = m_selection.start().deprecatedNode(); 1414 1415 LayoutRect oldRect = localCaretRectWithoutUpdate(); 1416 LayoutRect newRect = localCaretRect(); 1342 else { 1343 VisiblePosition visibleStart = m_selection.visibleStart(); 1344 if (updateCaretRect(m_frame->document(), visibleStart)) { 1345 caretNode = visibleStart.deepEquivalent().deprecatedNode(); 1346 m_absCaretBoundsDirty = true; 1347 } 1348 } 1349 } 1350 LayoutRect newRect = localCaretRectWithoutUpdate(); 1417 1351 1418 1352 if (caretNode == m_previousCaretNode && oldRect == newRect && !m_absCaretBoundsDirty) … … 1420 1354 1421 1355 IntRect oldAbsCaretBounds = m_absCaretBounds; 1422 m_absCaretBounds = absoluteBoundsForLocalRect(caretNode, localCaretRectWithoutUpdate()); 1356 m_absCaretBounds = absoluteBoundsForLocalCaretRect(rendererForCaretPainting(caretNode.get()), newRect); 1357 1358 if (m_absCaretBoundsDirty) // We should be able to always assert this condition. 1359 ASSERT(m_absCaretBounds == m_selection.visibleStart().absoluteCaretBounds()); 1360 1423 1361 m_absCaretBoundsDirty = false; 1424 1362 … … 1433 1371 repaintCaretForLocalRect(m_previousCaretNode.get(), oldRect); 1434 1372 m_previousCaretNode = caretNode; 1435 repaintCaretForLocalRect(caretNode , newRect);1373 repaintCaretForLocalRect(caretNode.get(), newRect); 1436 1374 } 1437 1375 } … … 1493 1431 1494 1432 LayoutRect drawingRect = localCaretRectWithoutUpdate(); 1495 RenderObject* renderer = caretRenderer(node);1433 RenderObject* renderer = rendererForCaretPainting(node); 1496 1434 if (renderer && renderer->isBox()) 1497 1435 toRenderBox(renderer)->flipForWritingMode(drawingRect); -
trunk/Source/WebCore/editing/FrameSelection.h
r163739 r163920 69 69 void clearCaretRect(); 70 70 bool updateCaretRect(Document*, const VisiblePosition& caretPosition); 71 IntRect absoluteBoundsForLocalRect(Node*, const LayoutRect&) const;72 71 bool shouldRepaintCaret(const RenderView*, bool isContentEditable) const; 73 72 void paintCaret(Node*, GraphicsContext*, const LayoutPoint&, const LayoutRect& clipRect) const; … … 169 168 RenderObject* caretRendererWithoutUpdatingLayout() const; 170 169 171 // Caret rect local to the caret's renderer172 LayoutRect localCaretRect();173 174 170 // Bounds of (possibly transformed) caret in absolute coords 175 171 IntRect absoluteCaretBounds(); … … 230 226 PassRefPtr<Range> rangeByExtendingCurrentSelection(int amount) const; 231 227 void selectRangeOnElement(unsigned location, unsigned length, Node*); 232 void suppressCloseTyping() { ++m_closeTypingSuppressions; }233 void restoreCloseTyping() { --m_closeTypingSuppressions; }234 228 void clearCurrentSelection(); 235 229 void setCaretBlinks(bool caretBlinks = true); … … 343 337 bool m_caretBlinks : 1; 344 338 Color m_caretColor; 345 int m_closeTypingSuppressions;346 339 int m_scrollingSuppressCount; 347 340 #endif -
trunk/Source/WebCore/editing/VisiblePosition.cpp
r161851 r163920 620 620 IntRect VisiblePosition::absoluteCaretBounds() const 621 621 { 622 RenderObject* renderer; 623 LayoutRect localRect = localCaretRect(renderer); 624 if (localRect.isEmpty() || !renderer) 625 return IntRect(); 626 627 return renderer->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox(); 622 RenderObject* renderer = nullptr; 623 LayoutRect localRect = localCaretRectInRendererForCaretPainting(*this, renderer); 624 return absoluteBoundsForLocalCaretRect(renderer, localRect); 628 625 } 629 626 -
trunk/Source/WebCore/editing/htmlediting.cpp
r163617 r163920 46 46 #include "NodeTraversal.h" 47 47 #include "PositionIterator.h" 48 #include "RenderBlock.h" 48 49 #include "RenderElement.h" 49 50 #include "ShadowRoot.h" … … 1261 1262 } 1262 1263 1264 static inline bool caretRendersInsideNode(Node* node) 1265 { 1266 return node && !isRenderedTable(node) && !editingIgnoresContent(node); 1267 } 1268 1269 RenderObject* rendererForCaretPainting(Node* node) 1270 { 1271 if (!node) 1272 return 0; 1273 1274 RenderObject* renderer = node->renderer(); 1275 if (!renderer) 1276 return 0; 1277 1278 // If caretNode is a block and caret is inside it, then caret should be painted by that block. 1279 bool paintedByBlock = renderer->isRenderBlockFlow() && caretRendersInsideNode(node); 1280 return paintedByBlock ? renderer : renderer->containingBlock(); 1281 } 1282 1283 LayoutRect localCaretRectInRendererForCaretPainting(const VisiblePosition& caretPosition, RenderObject*& caretPainter) 1284 { 1285 if (caretPosition.isNull()) 1286 return LayoutRect(); 1287 1288 ASSERT(caretPosition.deepEquivalent().deprecatedNode()->renderer()); 1289 1290 // First compute a rect local to the renderer at the selection start. 1291 RenderObject* renderer; 1292 LayoutRect localRect = caretPosition.localCaretRect(renderer); 1293 1294 // Get the renderer that will be responsible for painting the caret 1295 // (which is either the renderer we just found, or one of its containers). 1296 caretPainter = rendererForCaretPainting(caretPosition.deepEquivalent().deprecatedNode()); 1297 1298 // Compute an offset between the renderer and the caretPainter. 1299 while (renderer != caretPainter) { 1300 RenderObject* containerObject = renderer->container(); 1301 if (!containerObject) 1302 return LayoutRect(); 1303 localRect.move(renderer->offsetFromContainer(containerObject, localRect.location())); 1304 renderer = containerObject; 1305 } 1306 1307 return localRect; 1308 } 1309 1310 IntRect absoluteBoundsForLocalCaretRect(RenderObject* rendererForCaretPainting, const LayoutRect& rect) 1311 { 1312 if (!rendererForCaretPainting || rect.isEmpty()) 1313 return IntRect(); 1314 1315 LayoutRect localRect(rect); 1316 if (rendererForCaretPainting->isBox()) 1317 toRenderBox(rendererForCaretPainting)->flipForWritingMode(localRect); 1318 return rendererForCaretPainting->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox(); 1319 } 1320 1263 1321 } // namespace WebCore -
trunk/Source/WebCore/editing/htmlediting.h
r163617 r163920 257 257 const String& nonBreakingSpaceString(); 258 258 259 // Miscellaaneous functions that for caret rendering 260 261 RenderObject* rendererForCaretPainting(Node*); 262 LayoutRect localCaretRectInRendererForCaretPainting(const VisiblePosition&, RenderObject*&); 263 IntRect absoluteBoundsForLocalCaretRect(RenderObject* rendererForCaretPainting, const LayoutRect&); 264 259 265 } 260 266 -
trunk/Source/WebCore/loader/EmptyClients.h
r163725 r163920 471 471 472 472 #if PLATFORM(IOS) 473 virtual void suppressSelectionNotifications() override { }474 virtual void restoreSelectionNotifications() override { }475 473 virtual void startDelayingAndCoalescingContentChangeNotifications() override { } 476 474 virtual void stopDelayingAndCoalescingContentChangeNotifications() override { } -
trunk/Source/WebCore/page/EditorClient.h
r163725 r163920 120 120 121 121 #if PLATFORM(IOS) 122 virtual void suppressSelectionNotifications() = 0;123 virtual void restoreSelectionNotifications() = 0;124 122 virtual void startDelayingAndCoalescingContentChangeNotifications() = 0; 125 123 virtual void stopDelayingAndCoalescingContentChangeNotifications() = 0; -
trunk/Source/WebCore/page/Frame.h
r163079 r163920 257 257 NSRect caretRect() const; 258 258 NSRect rectForScrollToVisible() const; 259 NSRect rectForSelection(VisibleSelection&) const;260 259 DOMCSSStyleDeclaration* styleAtSelectionStart() const; 261 260 unsigned formElementsCharacterCount() const; -
trunk/Source/WebCore/page/ios/FrameIOS.mm
r163715 r163920 607 607 { 608 608 VisibleSelection selection(this->selection().selection()); 609 return rectForSelection(selection); 610 } 611 612 NSRect Frame::rectForSelection(VisibleSelection& selection) const 613 { 609 614 610 if (selection.isNone()) 615 611 return CGRectZero; … … 618 614 return caretRect(); 619 615 620 EditorClient* client = editor().client(); 621 if (client) 622 client->suppressSelectionNotifications(); 623 624 VisibleSelection originalSelection(selection); 625 Position position; 626 627 // The selection controllers below need to be associated with a frame in order 628 // to calculate geometry. This causes them to do more work here than we would 629 // like. Ideally, we would have a sort offline geometry-only mode for selection 630 // controllers so we could do this kind of work as cheaply as possible. 631 632 position = originalSelection.start(); 633 selection.setBase(position); 634 selection.setExtent(position); 635 FrameSelection startFrameSelection(const_cast<Frame*>(this)); 636 startFrameSelection.suppressCloseTyping(); 637 startFrameSelection.setSelection(selection); 638 FloatRect startRect(startFrameSelection.absoluteCaretBounds()); 639 startFrameSelection.restoreCloseTyping(); 640 641 position = originalSelection.end(); 642 selection.setBase(position); 643 selection.setExtent(position); 644 FrameSelection endFrameSelection(const_cast<Frame*>(this)); 645 endFrameSelection.suppressCloseTyping(); 646 endFrameSelection.setSelection(selection); 647 FloatRect endRect(endFrameSelection.absoluteCaretBounds()); 648 endFrameSelection.restoreCloseTyping(); 649 650 if (client) 651 client->restoreSelectionNotifications(); 652 653 return unionRect(startRect, endRect); 616 return unionRect(selection.visibleStart().absoluteCaretBounds(), selection.visibleEnd().absoluteCaretBounds()); 654 617 } 655 618 -
trunk/Source/WebKit/mac/ChangeLog
r163916 r163920 1 2014-02-11 Ryosuke Niwa <rniwa@webkit.org> 2 3 Frame::rectForSelection shouldn't instantiate FrameSelection 4 https://bugs.webkit.org/show_bug.cgi?id=128587 5 6 Reviewed by Enrica Casucci. 7 8 * WebCoreSupport/WebEditorClient.h: 9 * WebCoreSupport/WebEditorClient.mm: 10 (WebEditorClient::WebEditorClient): 11 (WebEditorClient::respondToChangedSelection): 12 1 13 2014-02-10 Myles C. Maxfield <mmaxfield@apple.com> 2 14 -
trunk/Source/WebKit/mac/WebCoreSupport/WebEditorClient.h
r163715 r163920 135 135 136 136 #if PLATFORM(IOS) 137 virtual void suppressSelectionNotifications() override;138 virtual void restoreSelectionNotifications() override;139 137 virtual void startDelayingAndCoalescingContentChangeNotifications() override; 140 138 virtual void stopDelayingAndCoalescingContentChangeNotifications() override; … … 173 171 RefPtr<WebCore::TextCheckingRequest> m_textCheckingRequest; 174 172 #if PLATFORM(IOS) 175 int m_selectionNotificationSuppressions;176 173 bool m_delayingContentChangeNotifications; 177 174 bool m_hasDelayedContentChangeNotification; -
trunk/Source/WebKit/mac/WebCoreSupport/WebEditorClient.mm
r163715 r163920 195 195 , m_haveUndoRedoOperations(false) 196 196 #if PLATFORM(IOS) 197 , m_selectionNotificationSuppressions(0)198 197 , m_delayingContentChangeNotifications(0) 199 198 , m_hasDelayedContentChangeNotification(0) … … 358 357 // Selection can be changed while deallocating down the WebView / Frame / Editor. Do not post in that case because it's already too late 359 358 // for the NSInvocation to retain the WebView. 360 if (![m_webView _isClosing] && m_selectionNotificationSuppressions == 0)359 if (![m_webView _isClosing]) 361 360 WebThreadPostNotification(WebViewDidChangeSelectionNotification, m_webView, nil); 362 361 #endif … … 798 797 799 798 #if PLATFORM(IOS) 800 801 void WebEditorClient::suppressSelectionNotifications()802 {803 m_selectionNotificationSuppressions++;804 }805 806 void WebEditorClient::restoreSelectionNotifications()807 {808 --m_selectionNotificationSuppressions;809 if (m_selectionNotificationSuppressions < 0)810 m_selectionNotificationSuppressions = 0;811 }812 799 813 800 void WebEditorClient::writeDataToPasteboard(NSDictionary* representation) -
trunk/Source/WebKit2/ChangeLog
r163919 r163920 1 2014-02-11 Ryosuke Niwa <rniwa@webkit.org> 2 3 Frame::rectForSelection shouldn't instantiate FrameSelection 4 https://bugs.webkit.org/show_bug.cgi?id=128587 5 6 Reviewed by Enrica Casucci. 7 8 * WebProcess/WebCoreSupport/WebEditorClient.h: 9 * WebProcess/WebCoreSupport/ios/WebEditorClientIOS.mm: 10 1 11 2014-02-11 Enrica Casucci <enrica@apple.com> 2 12 -
trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.h
r163712 r163920 154 154 #endif 155 155 #if PLATFORM(IOS) 156 virtual void suppressSelectionNotifications() override;157 virtual void restoreSelectionNotifications() override;158 156 virtual void startDelayingAndCoalescingContentChangeNotifications() override; 159 157 virtual void stopDelayingAndCoalescingContentChangeNotifications() override; -
trunk/Source/WebKit2/WebProcess/WebCoreSupport/ios/WebEditorClientIOS.mm
r159724 r163920 76 76 } 77 77 78 void WebEditorClient::suppressSelectionNotifications()79 {80 notImplemented();81 }82 83 void WebEditorClient::restoreSelectionNotifications()84 {85 notImplemented();86 }87 88 78 void WebEditorClient::startDelayingAndCoalescingContentChangeNotifications() 89 79 {
Note: See TracChangeset
for help on using the changeset viewer.