Chromium Code Reviews| 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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 56 return adoptPtr(new DragCaretController); | 56 return adoptPtr(new DragCaretController); |
| 57 } | 57 } |
| 58 | 58 |
| 59 bool DragCaretController::isContentRichlyEditable() const | 59 bool DragCaretController::isContentRichlyEditable() const |
| 60 { | 60 { |
| 61 return isRichlyEditablePosition(m_position.deepEquivalent()); | 61 return isRichlyEditablePosition(m_position.deepEquivalent()); |
| 62 } | 62 } |
| 63 | 63 |
| 64 void DragCaretController::setCaretPosition(const VisiblePosition& position) | 64 void DragCaretController::setCaretPosition(const VisiblePosition& position) |
| 65 { | 65 { |
| 66 if (Node* node = m_position.deepEquivalent().deprecatedNode()) | 66 if (m_position.isNotNull()) |
| 67 invalidateCaretRect(node); | 67 invalidateCaretRect(m_position.deepEquivalent()); |
| 68 m_position = position; | 68 m_position = position; |
| 69 setCaretRectNeedsUpdate(); | 69 setCaretRectNeedsUpdate(); |
| 70 Document* document = 0; | 70 if (m_position.isNotNull()) |
| 71 if (Node* node = m_position.deepEquivalent().deprecatedNode()) { | 71 invalidateCaretRect(m_position.deepEquivalent()); |
| 72 invalidateCaretRect(node); | |
| 73 document = &node->document(); | |
| 74 } | |
| 75 if (m_position.isNull() || m_position.isOrphan()) | 72 if (m_position.isNull() || m_position.isOrphan()) |
| 76 clearCaretRect(); | 73 clearCaretRect(); |
| 77 else | 74 else |
| 78 updateCaretRect(document, m_position); | 75 updateCaretRect(m_position.deepEquivalent().document(), m_position); |
| 79 } | 76 } |
| 80 | 77 |
| 81 static bool removingNodeRemovesPosition(Node* node, const Position& position) | 78 static bool removingNodeRemovesPosition(Node* node, const Position& position) |
| 82 { | 79 { |
| 83 if (!position.anchorNode()) | 80 if (!position.anchorNode()) |
| 84 return false; | 81 return false; |
| 85 | 82 |
| 86 if (position.anchorNode() == node) | 83 if (position.anchorNode() == node) |
| 87 return true; | 84 return true; |
| 88 | 85 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 116 void CaretBase::clearCaretRect() | 113 void CaretBase::clearCaretRect() |
| 117 { | 114 { |
| 118 m_caretLocalRect = LayoutRect(); | 115 m_caretLocalRect = LayoutRect(); |
| 119 } | 116 } |
| 120 | 117 |
| 121 static inline bool caretRendersInsideNode(Node* node) | 118 static inline bool caretRendersInsideNode(Node* node) |
| 122 { | 119 { |
| 123 return node && !isTableElement(node) && !editingIgnoresContent(node); | 120 return node && !isTableElement(node) && !editingIgnoresContent(node); |
| 124 } | 121 } |
| 125 | 122 |
| 126 RenderObject* CaretBase::caretRenderer(Node* node) | 123 RenderObject* CaretBase::caretRenderer(RenderObject* renderer) |
|
ojan
2013/09/23 23:01:45
This function looks to me like it's only used in t
| |
| 127 { | 124 { |
| 128 if (!node) | |
| 129 return 0; | |
| 130 | |
| 131 RenderObject* renderer = node->renderer(); | |
| 132 if (!renderer) | 125 if (!renderer) |
| 133 return 0; | 126 return 0; |
| 134 | 127 |
| 135 // if caretNode is a block and caret is inside it then caret should be paint ed by that block | 128 // if caretNode is a block and caret is inside it then caret should be paint ed by that block |
| 136 bool paintedByBlock = renderer->isRenderBlock() && caretRendersInsideNode(no de); | 129 bool paintedByBlock = renderer->isRenderBlock() && caretRendersInsideNode(re nderer->node()); |
| 137 return paintedByBlock ? renderer : renderer->containingBlock(); | 130 return paintedByBlock ? renderer : renderer->containingBlock(); |
| 138 } | 131 } |
| 139 | 132 |
| 133 RenderObject* CaretBase::caretRenderer(const Position& position) | |
| 134 { | |
| 135 return caretRenderer(position.rendererOfAnchorNode()); | |
| 136 } | |
| 137 | |
| 140 bool CaretBase::updateCaretRect(Document* document, const VisiblePosition& caret Position) | 138 bool CaretBase::updateCaretRect(Document* document, const VisiblePosition& caret Position) |
| 141 { | 139 { |
| 142 document->updateStyleIfNeeded(); | 140 document->updateStyleIfNeeded(); |
| 143 m_caretLocalRect = LayoutRect(); | 141 m_caretLocalRect = LayoutRect(); |
| 144 | 142 |
| 145 m_caretRectNeedsUpdate = false; | 143 m_caretRectNeedsUpdate = false; |
| 146 | 144 |
| 147 if (caretPosition.isNull()) | 145 if (caretPosition.isNull()) |
| 148 return false; | 146 return false; |
| 149 | 147 |
| 150 ASSERT(caretPosition.deepEquivalent().deprecatedNode()->renderer()); | 148 ASSERT(caretPosition.deepEquivalent().deprecatedNode()->renderer()); |
| 151 | 149 |
| 152 // First compute a rect local to the renderer at the selection start. | 150 // First compute a rect local to the renderer at the selection start. |
| 153 RenderObject* renderer; | 151 RenderObject* renderer; |
| 154 LayoutRect localRect = caretPosition.localCaretRect(renderer); | 152 LayoutRect localRect = caretPosition.localCaretRect(renderer); |
| 155 | 153 |
| 156 // Get the renderer that will be responsible for painting the caret | 154 // Get the renderer that will be responsible for painting the caret |
| 157 // (which is either the renderer we just found, or one of its containers). | 155 // (which is either the renderer we just found, or one of its containers). |
| 158 RenderObject* caretPainter = caretRenderer(caretPosition.deepEquivalent().de precatedNode()); | 156 RenderObject* caretPainter = caretRenderer(caretPosition.deepEquivalent()); |
| 159 | 157 |
| 160 // Compute an offset between the renderer and the caretPainter. | 158 // Compute an offset between the renderer and the caretPainter. |
| 161 bool unrooted = false; | 159 bool unrooted = false; |
| 162 while (renderer != caretPainter) { | 160 while (renderer != caretPainter) { |
| 163 RenderObject* containerObject = renderer->container(); | 161 RenderObject* containerObject = renderer->container(); |
| 164 if (!containerObject) { | 162 if (!containerObject) { |
| 165 unrooted = true; | 163 unrooted = true; |
| 166 break; | 164 break; |
| 167 } | 165 } |
| 168 localRect.move(renderer->offsetFromContainer(containerObject, localRect. location())); | 166 localRect.move(renderer->offsetFromContainer(containerObject, localRect. location())); |
| 169 renderer = containerObject; | 167 renderer = containerObject; |
| 170 } | 168 } |
| 171 | 169 |
| 172 if (!unrooted) | 170 if (!unrooted) |
| 173 m_caretLocalRect = localRect; | 171 m_caretLocalRect = localRect; |
| 174 | 172 |
| 175 return true; | 173 return true; |
| 176 } | 174 } |
| 177 | 175 |
| 178 RenderObject* DragCaretController::caretRenderer() const | 176 RenderObject* DragCaretController::caretRenderer() const |
| 179 { | 177 { |
| 180 return CaretBase::caretRenderer(m_position.deepEquivalent().deprecatedNode() ); | 178 return CaretBase::caretRenderer(m_position.deepEquivalent()); |
| 181 } | 179 } |
| 182 | 180 |
| 183 IntRect CaretBase::absoluteBoundsForLocalRect(Node* node, const LayoutRect& rect ) const | 181 IntRect CaretBase::absoluteBoundsForLocalRect(const Position& position, const La youtRect& rect) const |
| 184 { | 182 { |
| 185 RenderObject* caretPainter = caretRenderer(node); | 183 RenderObject* caretPainter = caretRenderer(position); |
| 186 if (!caretPainter) | 184 if (!caretPainter) |
| 187 return IntRect(); | 185 return IntRect(); |
| 188 | 186 |
| 189 LayoutRect localRect(rect); | 187 LayoutRect localRect(rect); |
| 190 if (caretPainter->isBox()) | 188 if (caretPainter->isBox()) |
| 191 toRenderBox(caretPainter)->flipForWritingMode(localRect); | 189 toRenderBox(caretPainter)->flipForWritingMode(localRect); |
| 192 return caretPainter->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoun dingBox(); | 190 return caretPainter->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoun dingBox(); |
| 193 } | 191 } |
| 194 | 192 |
| 195 void CaretBase::repaintCaretForLocalRect(Node* node, const LayoutRect& rect) | 193 void CaretBase::repaintCaretForLocalRect(const Position& position, const LayoutR ect& rect) |
| 196 { | 194 { |
| 197 RenderObject* caretPainter = caretRenderer(node); | 195 RenderObject* caretPainter = caretRenderer(position); |
| 198 if (!caretPainter) | 196 if (!caretPainter) |
| 199 return; | 197 return; |
| 200 | 198 |
| 201 // FIXME: Need to over-paint 1 pixel to workaround some rounding problems. | 199 // FIXME: Need to over-paint 1 pixel to workaround some rounding problems. |
| 202 // https://bugs.webkit.org/show_bug.cgi?id=108283 | 200 // https://bugs.webkit.org/show_bug.cgi?id=108283 |
| 203 LayoutRect inflatedRect = rect; | 201 LayoutRect inflatedRect = rect; |
| 204 inflatedRect.inflate(1); | 202 inflatedRect.inflate(1); |
| 205 | 203 |
| 206 caretPainter->repaintRectangle(inflatedRect); | 204 caretPainter->repaintRectangle(inflatedRect); |
| 207 } | 205 } |
| 208 | 206 |
| 209 bool CaretBase::shouldRepaintCaret(const RenderView* view, bool isContentEditabl e) const | 207 bool CaretBase::shouldRepaintCaret(const RenderView* view, bool isContentEditabl e) const |
| 210 { | 208 { |
| 211 ASSERT(view); | 209 ASSERT(view); |
| 212 bool caretBrowsing = false; | 210 bool caretBrowsing = false; |
| 213 if (FrameView* frameView = view->frameView()) { | 211 if (FrameView* frameView = view->frameView()) { |
| 214 Frame& frame = frameView->frame(); // The frame where the selection star ted | 212 Frame& frame = frameView->frame(); // The frame where the selection star ted |
| 215 caretBrowsing = frame.settings() && frame.settings()->caretBrowsingEnabl ed(); | 213 caretBrowsing = frame.settings() && frame.settings()->caretBrowsingEnabl ed(); |
| 216 } | 214 } |
| 217 return (caretBrowsing || isContentEditable); | 215 return (caretBrowsing || isContentEditable); |
| 218 } | 216 } |
| 219 | 217 |
| 220 void CaretBase::invalidateCaretRect(Node* node, bool caretRectChanged) | 218 void CaretBase::invalidateCaretRect(const Position& position, bool caretRectChan ged) |
| 221 { | 219 { |
| 222 // EDIT FIXME: This is an unfortunate hack. | 220 // EDIT FIXME: This is an unfortunate hack. |
| 223 // Basically, we can't trust this layout position since we | 221 // Basically, we can't trust this layout position since we |
| 224 // can't guarantee that the check to see if we are in unrendered | 222 // can't guarantee that the check to see if we are in unrendered |
| 225 // content will work at this point. We may have to wait for | 223 // content will work at this point. We may have to wait for |
| 226 // a layout and re-render of the document to happen. So, resetting this | 224 // a layout and re-render of the document to happen. So, resetting this |
| 227 // flag will cause another caret layout to happen the first time | 225 // flag will cause another caret layout to happen the first time |
| 228 // that we try to paint the caret after this call. That one will work since | 226 // that we try to paint the caret after this call. That one will work since |
| 229 // it happens after the document has accounted for any editing | 227 // it happens after the document has accounted for any editing |
| 230 // changes which may have been done. | 228 // changes which may have been done. |
| 231 // And, we need to leave this layout here so the caret moves right | 229 // And, we need to leave this layout here so the caret moves right |
| 232 // away after clicking. | 230 // away after clicking. |
| 233 m_caretRectNeedsUpdate = true; | 231 m_caretRectNeedsUpdate = true; |
| 234 | 232 |
| 235 if (caretRectChanged) | 233 if (caretRectChanged) |
| 236 return; | 234 return; |
| 237 | 235 |
| 238 if (RenderView* view = node->document().renderView()) { | 236 if (RenderView* view = position.document()->renderView()) { |
| 239 if (shouldRepaintCaret(view, node->isContentEditable(Node::UserSelectAll IsAlwaysNonEditable))) | 237 if (shouldRepaintCaret(view, position.anchorNode()->isContentEditable(No de::UserSelectAllIsAlwaysNonEditable))) |
| 240 repaintCaretForLocalRect(node, localCaretRectWithoutUpdate()); | 238 repaintCaretForLocalRect(position, localCaretRectWithoutUpdate()); |
| 241 } | 239 } |
| 242 } | 240 } |
| 243 | 241 |
| 244 void CaretBase::paintCaret(Node* node, GraphicsContext* context, const LayoutPoi nt& paintOffset, const LayoutRect& clipRect) const | 242 void CaretBase::paintCaret(const Position& position, GraphicsContext* context, c onst LayoutPoint& paintOffset, const LayoutRect& clipRect) const |
| 245 { | 243 { |
| 246 if (m_caretVisibility == Hidden) | 244 if (m_caretVisibility == Hidden) |
| 247 return; | 245 return; |
| 248 | 246 |
| 249 LayoutRect drawingRect = localCaretRectWithoutUpdate(); | 247 LayoutRect drawingRect = localCaretRectWithoutUpdate(); |
| 250 RenderObject* renderer = caretRenderer(node); | 248 RenderObject* renderer = caretRenderer(position); |
| 251 if (renderer && renderer->isBox()) | 249 if (renderer && renderer->isBox()) |
| 252 toRenderBox(renderer)->flipForWritingMode(drawingRect); | 250 toRenderBox(renderer)->flipForWritingMode(drawingRect); |
| 253 drawingRect.moveBy(roundedIntPoint(paintOffset)); | 251 drawingRect.moveBy(roundedIntPoint(paintOffset)); |
| 254 LayoutRect caret = intersection(drawingRect, clipRect); | 252 LayoutRect caret = intersection(drawingRect, clipRect); |
| 255 if (caret.isEmpty()) | 253 if (caret.isEmpty()) |
| 256 return; | 254 return; |
| 257 | 255 |
| 258 Color caretColor = Color::black; | 256 Color caretColor = Color::black; |
| 259 | 257 |
| 260 Element* element; | 258 Element* element = position.element(); |
| 261 if (node->isElementNode()) | |
| 262 element = toElement(node); | |
| 263 else | |
| 264 element = node->parentElement(); | |
| 265 | |
| 266 if (element && element->renderer()) | 259 if (element && element->renderer()) |
| 267 caretColor = element->renderer()->resolveColor(CSSPropertyColor); | 260 caretColor = element->renderer()->resolveColor(CSSPropertyColor); |
| 268 | 261 |
| 269 context->fillRect(caret, caretColor); | 262 context->fillRect(caret, caretColor); |
| 270 } | 263 } |
| 271 | 264 |
| 272 void DragCaretController::paintDragCaret(Frame* frame, GraphicsContext* p, const LayoutPoint& paintOffset, const LayoutRect& clipRect) const | 265 void DragCaretController::paintDragCaret(Frame* frame, GraphicsContext* p, const LayoutPoint& paintOffset, const LayoutRect& clipRect) const |
| 273 { | 266 { |
| 274 if (m_position.deepEquivalent().deprecatedNode()->document().frame() == fram e) | 267 if (m_position.deepEquivalent().deprecatedNode()->document().frame() == fram e) |
| 275 paintCaret(m_position.deepEquivalent().deprecatedNode(), p, paintOffset, clipRect); | 268 paintCaret(m_position.deepEquivalent(), p, paintOffset, clipRect); |
| 276 } | 269 } |
| 277 | 270 |
| 278 } | 271 } |
| OLD | NEW |