Changeset 32605 in webkit
- Timestamp:
- Apr 27, 2008 9:46:17 PM (16 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r32604 r32605 1 2008-04-27 Dan Bernstein <mitz@apple.com> 2 3 Reviewed by Darin Adler. 4 5 - test for https://bugs.webkit.org/show_bug.cgi?id=3729 6 <rdar://problem/4036353> REGRESSION: arrow keys move insertion bar backwards in RTL text 7 8 * editing/selection/move-left-right-expected.txt: Added. 9 * editing/selection/move-left-right.html: Added. 10 * platform/mac/editing/selection/move-left-right-expected.txt: Added. 11 1 12 2008-04-27 Sam Weinig <sam@webkit.org> 2 13 -
trunk/WebCore/ChangeLog
r32604 r32605 1 2008-04-27 Dan Bernstein <mitz@apple.com> 2 3 Reviewed by Darin Adler. 4 5 - fix https://bugs.webkit.org/show_bug.cgi?id=3729 6 <rdar://problem/4036353> REGRESSION: arrow keys move insertion bar backwards in RTL text 7 8 Test: editing/selection/move-left-right.html 9 10 * editing/SelectionController.cpp: 11 (WebCore::SelectionController::modifyMovingRight): Added. Currently 12 implemented for character granularity, all other being treated as 13 "forward". 14 (WebCore::SelectionController::modifyMovingForward): Renamed 15 modifyMovingRightForward() to this. 16 (WebCore::SelectionController::modifyMovingLeft): Added. Currently 17 implemented for character granularity, all other being treated as 18 "backward". 19 (WebCore::SelectionController::modifyMovingBackward): Renamed 20 modifyMovingLeftBackward() to this. 21 (WebCore::SelectionController::modify): Changed to call either the 22 visual (left/right) or logical (backward/forward) methods depending on 23 the 'dir' argument for moves. 24 * editing/SelectionController.h: 25 * editing/VisiblePosition.cpp: 26 (WebCore::VisiblePosition::leftVisuallyDistinctCandidate): Added. 27 (WebCore::VisiblePosition::left): Added. 28 (WebCore::VisiblePosition::rightVisuallyDistinctCandidate): Added. 29 (WebCore::VisiblePosition::right): Added. 30 * editing/VisiblePosition.h: 31 1 32 2008-04-27 Sam Weinig <sam@webkit.org> 2 33 -
trunk/WebCore/editing/SelectionController.cpp
r32508 r32605 286 286 } 287 287 288 VisiblePosition SelectionController::modifyMovingRightForward(TextGranularity granularity) 288 VisiblePosition SelectionController::modifyMovingRight(TextGranularity granularity) 289 { 290 VisiblePosition pos; 291 switch (granularity) { 292 case CharacterGranularity: 293 if (isRange()) 294 pos = VisiblePosition(m_sel.end(), m_sel.affinity()); 295 else 296 pos = VisiblePosition(m_sel.extent(), m_sel.affinity()).right(true); 297 break; 298 case WordGranularity: 299 case SentenceGranularity: 300 case LineGranularity: 301 case ParagraphGranularity: 302 case SentenceBoundary: 303 case LineBoundary: 304 case ParagraphBoundary: 305 case DocumentBoundary: 306 // FIXME: Implement all of the above. 307 pos = modifyMovingForward(granularity); 308 break; 309 } 310 return pos; 311 } 312 313 VisiblePosition SelectionController::modifyMovingForward(TextGranularity granularity) 289 314 { 290 315 VisiblePosition pos; … … 379 404 } 380 405 381 VisiblePosition SelectionController::modifyMovingLeftBackward(TextGranularity granularity) 406 VisiblePosition SelectionController::modifyMovingLeft(TextGranularity granularity) 407 { 408 VisiblePosition pos; 409 switch (granularity) { 410 case CharacterGranularity: 411 if (isRange()) 412 pos = VisiblePosition(m_sel.start(), m_sel.affinity()); 413 else 414 pos = VisiblePosition(m_sel.extent(), m_sel.affinity()).left(true); 415 break; 416 case WordGranularity: 417 case SentenceGranularity: 418 case LineGranularity: 419 case ParagraphGranularity: 420 case SentenceBoundary: 421 case LineBoundary: 422 case ParagraphBoundary: 423 case DocumentBoundary: 424 // FIXME: Implement all of the above. 425 pos = modifyMovingBackward(granularity); 426 break; 427 } 428 return pos; 429 } 430 431 VisiblePosition SelectionController::modifyMovingBackward(TextGranularity granularity) 382 432 { 383 433 VisiblePosition pos; … … 441 491 VisiblePosition pos; 442 492 switch (dir) { 443 // EDIT FIXME: These need to handle bidi444 493 case RIGHT: 494 if (alter == MOVE) 495 pos = modifyMovingRight(granularity); 496 else 497 pos = modifyExtendingRightForward(granularity); 498 break; 445 499 case FORWARD: 446 500 if (alter == EXTEND) 447 501 pos = modifyExtendingRightForward(granularity); 448 502 else 449 pos = modifyMoving RightForward(granularity);503 pos = modifyMovingForward(granularity); 450 504 break; 451 505 case LEFT: 506 if (alter == MOVE) 507 pos = modifyMovingLeft(granularity); 508 else 509 pos = modifyExtendingLeftBackward(granularity); 510 break; 452 511 case BACKWARD: 453 512 if (alter == EXTEND) 454 513 pos = modifyExtendingLeftBackward(granularity); 455 514 else 456 pos = modifyMoving LeftBackward(granularity);515 pos = modifyMovingBackward(granularity); 457 516 break; 458 517 } -
trunk/WebCore/editing/SelectionController.h
r29581 r32605 126 126 127 127 VisiblePosition modifyExtendingRightForward(TextGranularity); 128 VisiblePosition modifyMovingRightForward(TextGranularity); 128 VisiblePosition modifyMovingRight(TextGranularity); 129 VisiblePosition modifyMovingForward(TextGranularity); 129 130 VisiblePosition modifyExtendingLeftBackward(TextGranularity); 130 VisiblePosition modifyMovingLeftBackward(TextGranularity); 131 VisiblePosition modifyMovingLeft(TextGranularity); 132 VisiblePosition modifyMovingBackward(TextGranularity); 131 133 132 134 void layout(); -
trunk/WebCore/editing/VisiblePosition.cpp
r32508 r32605 103 103 } 104 104 105 Position VisiblePosition::leftVisuallyDistinctCandidate() const 106 { 107 Position p = m_deepPosition; 108 Position downstreamStart = p.downstream(); 109 110 TextDirection primaryDirection = LTR; 111 for (RenderObject* r = p.node()->renderer(); r; r = r->parent()) { 112 if (r->isBlockFlow()) { 113 primaryDirection = r->style()->direction(); 114 break; 115 } 116 } 117 118 while (true) { 119 InlineBox* box; 120 int offset; 121 p.getInlineBoxAndOffset(m_affinity, primaryDirection, box, offset); 122 if (!box) 123 return primaryDirection == LTR ? previousVisuallyDistinctCandidate(p) : nextVisuallyDistinctCandidate(p); 124 125 RenderObject* renderer = box->object(); 126 127 while (true) { 128 if ((renderer->isReplaced() || renderer->isBR()) && offset == box->caretRightmostOffset()) 129 return box->direction() == LTR ? previousVisuallyDistinctCandidate(p) : nextVisuallyDistinctCandidate(p); 130 131 offset = box->direction() == LTR ? renderer->previousOffset(offset) : renderer->nextOffset(offset); 132 133 int caretMinOffset = box->caretMinOffset(); 134 int caretMaxOffset = box->caretMaxOffset(); 135 136 if (offset > caretMinOffset && offset < caretMaxOffset) 137 break; 138 139 if (box->direction() == LTR ? offset < caretMinOffset : offset > caretMaxOffset) { 140 // Overshot to the left. 141 InlineBox* prevBox = box->prevLeafChild(); 142 if (!prevBox) 143 return primaryDirection == LTR ? previousVisuallyDistinctCandidate(p) : nextVisuallyDistinctCandidate(p);; 144 145 // Reposition at the other logical position corresponding to our edge's visual position and go for another round. 146 box = prevBox; 147 renderer = box->object(); 148 offset = prevBox->caretRightmostOffset(); 149 continue; 150 } 151 152 ASSERT(offset == box->caretLeftmostOffset()); 153 154 unsigned char level = box->bidiLevel(); 155 InlineBox* prevBox = box->prevLeafChild(); 156 157 if (box->direction() == primaryDirection) { 158 if (!prevBox || prevBox->bidiLevel() >= level) 159 break; 160 161 level = prevBox->bidiLevel(); 162 163 InlineBox* nextBox = box; 164 do { 165 nextBox = nextBox->nextLeafChild(); 166 } while (nextBox && nextBox->bidiLevel() > level); 167 168 if (nextBox && nextBox->bidiLevel() == level) 169 break; 170 171 while (InlineBox* prevBox = box->prevLeafChild()) { 172 if (prevBox->bidiLevel() < level) 173 break; 174 box = prevBox; 175 } 176 renderer = box->object(); 177 offset = box->caretRightmostOffset(); 178 if (box->direction() == primaryDirection) 179 break; 180 continue; 181 } 182 183 if (prevBox) { 184 box = prevBox; 185 renderer = box->object(); 186 offset = box->caretRightmostOffset(); 187 if (box->bidiLevel() > level) { 188 do { 189 prevBox = box->prevLeafChild(); 190 } while (prevBox && prevBox->bidiLevel() > level); 191 192 if (!prevBox || prevBox->bidiLevel() < level) 193 continue; 194 } 195 } else { 196 // Trailing edge of a secondary run. Set to the leading edge of the entire run. 197 while (true) { 198 while (InlineBox* nextBox = box->nextLeafChild()) { 199 if (nextBox->bidiLevel() < level) 200 break; 201 box = nextBox; 202 } 203 if (box->bidiLevel() == level) 204 break; 205 level = box->bidiLevel(); 206 while (InlineBox* prevBox = box->prevLeafChild()) { 207 if (prevBox->bidiLevel() < level) 208 break; 209 box = prevBox; 210 } 211 if (box->bidiLevel() == level) 212 break; 213 level = box->bidiLevel(); 214 } 215 renderer = box->object(); 216 offset = primaryDirection == LTR ? box->caretMinOffset() : box->caretMaxOffset(); 217 } 218 break; 219 } 220 221 p = Position(renderer->element(), offset); 222 223 if (p.isCandidate() && p.downstream() != downstreamStart || p.atStart() || p.atEnd()) 224 return p; 225 } 226 } 227 228 VisiblePosition VisiblePosition::left(bool stayInEditableContent) const 229 { 230 Position pos = leftVisuallyDistinctCandidate(); 231 if (pos.atStart() || pos.atEnd()) 232 return VisiblePosition(); 233 234 VisiblePosition left = VisiblePosition(pos, DOWNSTREAM); 235 ASSERT(left != *this); 236 237 if (!stayInEditableContent) 238 return left; 239 240 // FIXME: This may need to do something different from "before". 241 return honorEditableBoundaryAtOrBefore(left); 242 } 243 244 Position VisiblePosition::rightVisuallyDistinctCandidate() const 245 { 246 Position p = m_deepPosition; 247 Position downstreamStart = p.downstream(); 248 249 TextDirection primaryDirection = LTR; 250 for (RenderObject* r = p.node()->renderer(); r; r = r->parent()) { 251 if (r->isBlockFlow()) { 252 primaryDirection = r->style()->direction(); 253 break; 254 } 255 } 256 257 while (true) { 258 InlineBox* box; 259 int offset; 260 p.getInlineBoxAndOffset(m_affinity, primaryDirection, box, offset); 261 if (!box) 262 return primaryDirection == LTR ? nextVisuallyDistinctCandidate(p) : previousVisuallyDistinctCandidate(p); 263 264 RenderObject* renderer = box->object(); 265 266 while (true) { 267 if ((renderer->isReplaced() || renderer->isBR()) && offset == box->caretLeftmostOffset()) 268 return box->direction() == LTR ? nextVisuallyDistinctCandidate(p) : previousVisuallyDistinctCandidate(p); 269 270 offset = box->direction() == LTR ? renderer->nextOffset(offset) : renderer->previousOffset(offset); 271 272 int caretMinOffset = box->caretMinOffset(); 273 int caretMaxOffset = box->caretMaxOffset(); 274 275 if (offset > caretMinOffset && offset < caretMaxOffset) 276 break; 277 278 if (box->direction() == LTR ? offset > caretMaxOffset : offset < caretMinOffset) { 279 // Overshot to the right. 280 InlineBox* nextBox = box->nextLeafChild(); 281 if (!nextBox) 282 return primaryDirection == LTR ? nextVisuallyDistinctCandidate(p) : previousVisuallyDistinctCandidate(p);; 283 284 // Reposition at the other logical position corresponding to our edge's visual position and go for another round. 285 box = nextBox; 286 renderer = box->object(); 287 offset = nextBox->caretLeftmostOffset(); 288 continue; 289 } 290 291 ASSERT(offset == box->caretRightmostOffset()); 292 293 unsigned char level = box->bidiLevel(); 294 InlineBox* nextBox = box->nextLeafChild(); 295 296 if (box->direction() == primaryDirection) { 297 if (!nextBox || nextBox->bidiLevel() >= level) 298 break; 299 300 level = nextBox->bidiLevel(); 301 302 InlineBox* prevBox = box; 303 do { 304 prevBox = prevBox->prevLeafChild(); 305 } while (prevBox && prevBox->bidiLevel() > level); 306 307 if (prevBox && prevBox->bidiLevel() == level) // For example, abc FED 123 ^ CBA 308 break; 309 310 // For example, abc 123 ^ CBA 311 while (InlineBox* nextBox = box->nextLeafChild()) { 312 if (nextBox->bidiLevel() < level) 313 break; 314 box = nextBox; 315 } 316 renderer = box->object(); 317 offset = box->caretLeftmostOffset(); 318 if (box->direction() == primaryDirection) 319 break; 320 continue; 321 } 322 323 if (nextBox) { 324 box = nextBox; 325 renderer = box->object(); 326 offset = box->caretLeftmostOffset(); 327 if (box->bidiLevel() > level) { 328 do { 329 nextBox = box->nextLeafChild(); 330 } while (nextBox && nextBox->bidiLevel() > level); 331 332 if (!nextBox || nextBox->bidiLevel() < level) 333 continue; 334 } 335 } else { 336 // Trailing edge of a secondary run. Set to the leading edge of the entire run. 337 while (true) { 338 while (InlineBox* prevBox = box->prevLeafChild()) { 339 if (prevBox->bidiLevel() < level) 340 break; 341 box = prevBox; 342 } 343 if (box->bidiLevel() == level) 344 break; 345 level = box->bidiLevel(); 346 while (InlineBox* nextBox = box->nextLeafChild()) { 347 if (nextBox->bidiLevel() < level) 348 break; 349 box = nextBox; 350 } 351 if (box->bidiLevel() == level) 352 break; 353 level = box->bidiLevel(); 354 } 355 renderer = box->object(); 356 offset = primaryDirection == LTR ? box->caretMaxOffset() : box->caretMinOffset(); 357 } 358 break; 359 } 360 361 p = Position(renderer->element(), offset); 362 363 if (p.isCandidate() && p.downstream() != downstreamStart || p.atStart() || p.atEnd()) 364 return p; 365 } 366 } 367 368 VisiblePosition VisiblePosition::right(bool stayInEditableContent) const 369 { 370 Position pos = rightVisuallyDistinctCandidate(); 371 if (pos.atStart() || pos.atEnd()) 372 return VisiblePosition(); 373 374 VisiblePosition right = VisiblePosition(pos, DOWNSTREAM); 375 ASSERT(right != *this); 376 377 if (!stayInEditableContent) 378 return right; 379 380 // FIXME: This may need to do something different from "after". 381 return honorEditableBoundaryAtOrAfter(right); 382 } 383 105 384 VisiblePosition VisiblePosition::honorEditableBoundaryAtOrBefore(const VisiblePosition &pos) const 106 385 { -
trunk/WebCore/editing/VisiblePosition.h
r32508 r32605 71 71 VisiblePosition honorEditableBoundaryAtOrAfter(const VisiblePosition&) const; 72 72 73 VisiblePosition left(bool stayInEditableContent = false) const; 74 VisiblePosition right(bool stayInEditableContent = false) const; 75 73 76 UChar characterAfter() const; 74 77 UChar characterBefore() const { return previous().characterAfter(); } … … 98 101 void init(const Position&, EAffinity); 99 102 Position canonicalPosition(const Position&); 103 104 Position leftVisuallyDistinctCandidate() const; 105 Position rightVisuallyDistinctCandidate() const; 100 106 101 107 Position m_deepPosition;
Note: See TracChangeset
for help on using the changeset viewer.