OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 1201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1212 { | 1212 { |
1213 const bool selectionHasDirection = true; | 1213 const bool selectionHasDirection = true; |
1214 setSelection(VisibleSelection(m_selection.base(), pos, affinity, selectionHa
sDirection), CloseTyping | ClearTypingStyle | userTriggered); | 1214 setSelection(VisibleSelection(m_selection.base(), pos, affinity, selectionHa
sDirection), CloseTyping | ClearTypingStyle | userTriggered); |
1215 } | 1215 } |
1216 | 1216 |
1217 void CaretBase::clearCaretRect() | 1217 void CaretBase::clearCaretRect() |
1218 { | 1218 { |
1219 m_caretLocalRect = LayoutRect(); | 1219 m_caretLocalRect = LayoutRect(); |
1220 } | 1220 } |
1221 | 1221 |
| 1222 static inline bool caretRendersInsideNode(Node* node) |
| 1223 { |
| 1224 return node && !isTableElement(node) && !editingIgnoresContent(node); |
| 1225 } |
| 1226 |
| 1227 static RenderObject* caretRenderer(Node* node) |
| 1228 { |
| 1229 if (!node) |
| 1230 return 0; |
| 1231 |
| 1232 RenderObject* renderer = node->renderer(); |
| 1233 if (!renderer) |
| 1234 return 0; |
| 1235 |
| 1236 // if caretNode is a block and caret is inside it then caret should be paint
ed by that block |
| 1237 bool paintedByBlock = renderer->isBlockFlow() && caretRendersInsideNode(node
); |
| 1238 return paintedByBlock ? renderer : renderer->containingBlock(); |
| 1239 } |
| 1240 |
1222 bool CaretBase::updateCaretRect(Document* document, const VisiblePosition& caret
Position) | 1241 bool CaretBase::updateCaretRect(Document* document, const VisiblePosition& caret
Position) |
1223 { | 1242 { |
1224 document->updateStyleIfNeeded(); | 1243 document->updateStyleIfNeeded(); |
1225 m_caretLocalRect = LayoutRect(); | 1244 m_caretLocalRect = LayoutRect(); |
1226 | 1245 |
1227 m_caretRectNeedsUpdate = false; | 1246 m_caretRectNeedsUpdate = false; |
1228 | 1247 |
1229 if (caretPosition.isNull()) | 1248 if (caretPosition.isNull()) |
1230 return false; | 1249 return false; |
1231 | 1250 |
(...skipping 18 matching lines...) Expand all Loading... |
1250 localRect.move(renderer->offsetFromContainer(containerObject, localRect.
location())); | 1269 localRect.move(renderer->offsetFromContainer(containerObject, localRect.
location())); |
1251 renderer = containerObject; | 1270 renderer = containerObject; |
1252 } | 1271 } |
1253 | 1272 |
1254 if (!unrooted) | 1273 if (!unrooted) |
1255 m_caretLocalRect = localRect; | 1274 m_caretLocalRect = localRect; |
1256 | 1275 |
1257 return true; | 1276 return true; |
1258 } | 1277 } |
1259 | 1278 |
1260 static inline bool caretRendersInsideNode(Node* node) | |
1261 { | |
1262 return node && !isTableElement(node) && !editingIgnoresContent(node); | |
1263 } | |
1264 | |
1265 RenderObject* CaretBase::caretRenderer(Node* node) const | |
1266 { | |
1267 if (!node) | |
1268 return 0; | |
1269 | |
1270 RenderObject* renderer = node->renderer(); | |
1271 if (!renderer) | |
1272 return 0; | |
1273 | |
1274 // if caretNode is a block and caret is inside it then caret should be paint
ed by that block | |
1275 bool paintedByBlock = renderer->isBlockFlow() && caretRendersInsideNode(node
); | |
1276 return paintedByBlock ? renderer : renderer->containingBlock(); | |
1277 } | |
1278 | |
1279 RenderObject* FrameSelection::caretRenderer() const | 1279 RenderObject* FrameSelection::caretRenderer() const |
1280 { | 1280 { |
1281 return CaretBase::caretRenderer(m_selection.start().deprecatedNode()); | 1281 return WebCore::caretRenderer(m_selection.start().deprecatedNode()); |
1282 } | 1282 } |
1283 | 1283 |
1284 RenderObject* DragCaretController::caretRenderer() const | 1284 RenderObject* DragCaretController::caretRenderer() const |
1285 { | 1285 { |
1286 return CaretBase::caretRenderer(m_position.deepEquivalent().deprecatedNode()
); | 1286 return WebCore::caretRenderer(m_position.deepEquivalent().deprecatedNode()); |
1287 } | 1287 } |
1288 | 1288 |
1289 static bool isNonOrphanedCaret(const VisibleSelection& selection) | 1289 static bool isNonOrphanedCaret(const VisibleSelection& selection) |
1290 { | 1290 { |
1291 return selection.isCaret() && !selection.start().isOrphan() && !selection.en
d().isOrphan(); | 1291 return selection.isCaret() && !selection.start().isOrphan() && !selection.en
d().isOrphan(); |
1292 } | 1292 } |
1293 | 1293 |
1294 LayoutRect FrameSelection::localCaretRect() | 1294 LayoutRect FrameSelection::localCaretRect() |
1295 { | 1295 { |
1296 if (shouldUpdateCaretRect()) { | 1296 if (shouldUpdateCaretRect()) { |
(...skipping 17 matching lines...) Expand all Loading... |
1314 toRenderBox(caretPainter)->flipForWritingMode(localRect); | 1314 toRenderBox(caretPainter)->flipForWritingMode(localRect); |
1315 return caretPainter->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoun
dingBox(); | 1315 return caretPainter->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoun
dingBox(); |
1316 } | 1316 } |
1317 | 1317 |
1318 IntRect FrameSelection::absoluteCaretBounds() | 1318 IntRect FrameSelection::absoluteCaretBounds() |
1319 { | 1319 { |
1320 recomputeCaretRect(); | 1320 recomputeCaretRect(); |
1321 return m_absCaretBounds; | 1321 return m_absCaretBounds; |
1322 } | 1322 } |
1323 | 1323 |
1324 static LayoutRect repaintRectForCaret(LayoutRect caret) | 1324 static void repaintCaretForLocalRect(Node* node, const LayoutRect& rect) |
1325 { | 1325 { |
1326 if (caret.isEmpty()) | 1326 RenderObject* caretPainter = caretRenderer(node); |
1327 return LayoutRect(); | 1327 if (!caretPainter) |
1328 // Ensure that the dirty rect intersects the block that paints the caret eve
n in the case where | 1328 return; |
1329 // the caret itself is just outside the block. See <https://bugs.webkit.org/
show_bug.cgi?id=19086>. | |
1330 caret.inflateX(1); | |
1331 caret.inflateY(1); | |
1332 return caret; | |
1333 } | |
1334 | 1329 |
1335 IntRect CaretBase::caretRepaintRect(Node* node) const | 1330 caretPainter->repaintRectangle(rect); |
1336 { | |
1337 return absoluteBoundsForLocalRect(node, repaintRectForCaret(localCaretRectWi
thoutUpdate())); | |
1338 } | 1331 } |
1339 | 1332 |
1340 bool FrameSelection::recomputeCaretRect() | 1333 bool FrameSelection::recomputeCaretRect() |
1341 { | 1334 { |
1342 if (!shouldUpdateCaretRect()) | 1335 if (!shouldUpdateCaretRect()) |
1343 return false; | 1336 return false; |
1344 | 1337 |
1345 if (!m_frame) | 1338 if (!m_frame) |
1346 return false; | 1339 return false; |
1347 | 1340 |
1348 FrameView* v = m_frame->document()->view(); | 1341 FrameView* v = m_frame->document()->view(); |
1349 if (!v) | 1342 if (!v) |
1350 return false; | 1343 return false; |
1351 | 1344 |
1352 LayoutRect oldRect = localCaretRectWithoutUpdate(); | 1345 LayoutRect oldRect = localCaretRectWithoutUpdate(); |
1353 LayoutRect newRect = localCaretRect(); | 1346 LayoutRect newRect = localCaretRect(); |
1354 if (oldRect == newRect && !m_absCaretBoundsDirty) | 1347 if (oldRect == newRect && !m_absCaretBoundsDirty) |
1355 return false; | 1348 return false; |
1356 | 1349 |
1357 IntRect oldAbsCaretBounds = m_absCaretBounds; | 1350 IntRect oldAbsCaretBounds = m_absCaretBounds; |
1358 // FIXME: Rename m_caretRect to m_localCaretRect. | |
1359 m_absCaretBounds = absoluteBoundsForLocalRect(m_selection.start().deprecated
Node(), localCaretRectWithoutUpdate()); | 1351 m_absCaretBounds = absoluteBoundsForLocalRect(m_selection.start().deprecated
Node(), localCaretRectWithoutUpdate()); |
1360 m_absCaretBoundsDirty = false; | 1352 m_absCaretBoundsDirty = false; |
1361 | 1353 |
1362 if (oldAbsCaretBounds == m_absCaretBounds) | 1354 if (oldAbsCaretBounds == m_absCaretBounds) |
1363 return false; | 1355 return false; |
1364 | 1356 |
1365 #if ENABLE(TEXT_CARET) | 1357 #if ENABLE(TEXT_CARET) |
1366 IntRect oldAbsoluteCaretRepaintBounds = m_absoluteCaretRepaintBounds; | |
1367 #endif | |
1368 | |
1369 // We believe that we need to inflate the local rect before transforming it
to obtain the repaint bounds. | |
1370 m_absoluteCaretRepaintBounds = caretRepaintRect(m_selection.start().deprecat
edNode()); | |
1371 | |
1372 #if ENABLE(TEXT_CARET) | |
1373 if (RenderView* view = m_frame->document()->renderView()) { | 1358 if (RenderView* view = m_frame->document()->renderView()) { |
1374 // FIXME: make caret repainting container-aware. | 1359 Node* node = m_selection.start().deprecatedNode(); |
1375 view->repaintRectangleInViewAndCompositedLayers(oldAbsoluteCaretRepaintB
ounds, false); | 1360 if (m_previousCaretNode) |
| 1361 repaintCaretForLocalRect(m_previousCaretNode.get(), oldRect); |
| 1362 m_previousCaretNode = node; |
1376 if (shouldRepaintCaret(view, isContentEditable())) | 1363 if (shouldRepaintCaret(view, isContentEditable())) |
1377 view->repaintRectangleInViewAndCompositedLayers(m_absoluteCaretRepai
ntBounds, false); | 1364 repaintCaretForLocalRect(node, newRect); |
1378 } | 1365 } |
1379 #endif | 1366 #endif |
1380 return true; | 1367 return true; |
1381 } | 1368 } |
1382 | 1369 |
1383 bool CaretBase::shouldRepaintCaret(const RenderView* view, bool isContentEditabl
e) const | 1370 bool CaretBase::shouldRepaintCaret(const RenderView* view, bool isContentEditabl
e) const |
1384 { | 1371 { |
1385 ASSERT(view); | 1372 ASSERT(view); |
1386 Frame* frame = view->frameView() ? view->frameView()->frame() : 0; // The fr
ame where the selection started. | 1373 Frame* frame = view->frameView() ? view->frameView()->frame() : 0; // The fr
ame where the selection started. |
1387 bool caretBrowsing = frame && frame->settings() && frame->settings()->caretB
rowsingEnabled(); | 1374 bool caretBrowsing = frame && frame->settings() && frame->settings()->caretB
rowsingEnabled(); |
(...skipping 21 matching lines...) Expand all Loading... |
1409 // changes which may have been done. | 1396 // changes which may have been done. |
1410 // And, we need to leave this layout here so the caret moves right | 1397 // And, we need to leave this layout here so the caret moves right |
1411 // away after clicking. | 1398 // away after clicking. |
1412 m_caretRectNeedsUpdate = true; | 1399 m_caretRectNeedsUpdate = true; |
1413 | 1400 |
1414 if (caretRectChanged) | 1401 if (caretRectChanged) |
1415 return; | 1402 return; |
1416 | 1403 |
1417 if (RenderView* view = node->document()->renderView()) { | 1404 if (RenderView* view = node->document()->renderView()) { |
1418 if (shouldRepaintCaret(view, node->isContentEditable(Node::UserSelectAll
IsAlwaysNonEditable))) | 1405 if (shouldRepaintCaret(view, node->isContentEditable(Node::UserSelectAll
IsAlwaysNonEditable))) |
1419 view->repaintRectangleInViewAndCompositedLayers(caretRepaintRect(nod
e), false); | 1406 repaintCaretForLocalRect(node, localCaretRectWithoutUpdate()); |
1420 } | 1407 } |
1421 } | 1408 } |
1422 | 1409 |
1423 void FrameSelection::paintCaret(GraphicsContext* context, const LayoutPoint& pai
ntOffset, const LayoutRect& clipRect) | 1410 void FrameSelection::paintCaret(GraphicsContext* context, const LayoutPoint& pai
ntOffset, const LayoutRect& clipRect) |
1424 { | 1411 { |
1425 if (m_selection.isCaret() && m_caretPaint) | 1412 if (m_selection.isCaret() && m_caretPaint) |
1426 CaretBase::paintCaret(m_selection.start().deprecatedNode(), context, pai
ntOffset, clipRect); | 1413 CaretBase::paintCaret(m_selection.start().deprecatedNode(), context, pai
ntOffset, clipRect); |
1427 } | 1414 } |
1428 | 1415 |
1429 void CaretBase::paintCaret(Node* node, GraphicsContext* context, const LayoutPoi
nt& paintOffset, const LayoutRect& clipRect) const | 1416 void CaretBase::paintCaret(Node* node, GraphicsContext* context, const LayoutPoi
nt& paintOffset, const LayoutRect& clipRect) const |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1676 } | 1663 } |
1677 | 1664 |
1678 void FrameSelection::focusedOrActiveStateChanged() | 1665 void FrameSelection::focusedOrActiveStateChanged() |
1679 { | 1666 { |
1680 bool activeAndFocused = isFocusedAndActive(); | 1667 bool activeAndFocused = isFocusedAndActive(); |
1681 | 1668 |
1682 // Because RenderObject::selectionBackgroundColor() and | 1669 // Because RenderObject::selectionBackgroundColor() and |
1683 // RenderObject::selectionForegroundColor() check if the frame is active, | 1670 // RenderObject::selectionForegroundColor() check if the frame is active, |
1684 // we have to update places those colors were painted. | 1671 // we have to update places those colors were painted. |
1685 if (RenderView* view = m_frame->document()->renderView()) | 1672 if (RenderView* view = m_frame->document()->renderView()) |
1686 view->repaintRectangleInViewAndCompositedLayers(enclosingIntRect(bounds(
))); | 1673 view->repaintSelection(); |
1687 | 1674 |
1688 // Caret appears in the active frame. | 1675 // Caret appears in the active frame. |
1689 if (activeAndFocused) | 1676 if (activeAndFocused) |
1690 setSelectionFromNone(); | 1677 setSelectionFromNone(); |
1691 setCaretVisibility(activeAndFocused ? Visible : Hidden); | 1678 setCaretVisibility(activeAndFocused ? Visible : Hidden); |
1692 | 1679 |
1693 // Update for caps lock state | 1680 // Update for caps lock state |
1694 m_frame->eventHandler()->capsLockStateMayHaveChanged(); | 1681 m_frame->eventHandler()->capsLockStateMayHaveChanged(); |
1695 | 1682 |
1696 // Because StyleResolver::checkOneSelector() and | 1683 // Because StyleResolver::checkOneSelector() and |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2077 sel.showTreeForThis(); | 2064 sel.showTreeForThis(); |
2078 } | 2065 } |
2079 | 2066 |
2080 void showTree(const WebCore::FrameSelection* sel) | 2067 void showTree(const WebCore::FrameSelection* sel) |
2081 { | 2068 { |
2082 if (sel) | 2069 if (sel) |
2083 sel->showTreeForThis(); | 2070 sel->showTreeForThis(); |
2084 } | 2071 } |
2085 | 2072 |
2086 #endif | 2073 #endif |
OLD | NEW |