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 |