Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(680)

Side by Side Diff: Source/core/editing/Caret.cpp

Issue 20681004: Make first-letter style to work with editing Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: 2013-09-20T18:27:32 Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698