|
Lines 305-311
bool FocusController::advanceFocusDirectionally(FocusDirection direction, Keyboa
a/WebCore/page/FocusController.cpp_sec1
|
| 305 |
frame = frame->tree()->top(); |
305 |
frame = frame->tree()->top(); |
| 306 |
|
306 |
|
| 307 |
FocusCandidate focusCandidate; |
307 |
FocusCandidate focusCandidate; |
| 308 |
findFocusableNodeInDirection(frame->document(), focusedNode, direction, event, focusCandidate); |
308 |
findFocusableNodeInDirection(frame->document(), focusedNode, direction, event, focusCandidate, FocusCandidate()); |
| 309 |
|
309 |
|
| 310 |
Node* node = focusCandidate.node; |
310 |
Node* node = focusCandidate.node; |
| 311 |
if (!node || !node->isElementNode()) { |
311 |
if (!node || !node->isElementNode()) { |
|
Lines 342-387
bool FocusController::advanceFocusDirectionally(FocusDirection direction, Keyboa
a/WebCore/page/FocusController.cpp_sec2
|
| 342 |
return true; |
342 |
return true; |
| 343 |
} |
343 |
} |
| 344 |
|
344 |
|
| 345 |
static void updateFocusCandidateIfCloser(Node* focusedNode, Node* candidate, long long distance, FocusCandidate& closestFocusCandidate) |
345 |
// FIXME: Make this method more modular, and simpler to understand and maintain. |
|
|
346 |
static void updateFocusCandidateIfCloser(Node* focusedNode, FocusCandidate candidate, FocusCandidate& closest) |
| 346 |
{ |
347 |
{ |
| 347 |
// Bail out if |distance| is bigger than the current closest candidate. |
348 |
bool sameDocument = candidate.document() == closest.document(); |
| 348 |
if (distance >= closestFocusCandidate.distance) |
349 |
if (sameDocument) { |
|
|
350 |
if (closest.alignment > candidate.alignment |
| 351 |
|| (closest.parentAlignment && candidate.alignment > closest.parentAlignment)) |
| 352 |
return; |
| 353 |
} else if (closest.alignment > candidate.alignment |
| 354 |
&& (closest.parentAlignment && candidate.alignment > closest.parentAlignment)) |
| 349 |
return; |
355 |
return; |
| 350 |
|
356 |
|
| 351 |
// If |focusedNode| and |candidate| are in the same document AND |
357 |
if (candidate.alignment != None |
| 352 |
// current |closestFocusCandidadte| is not in an {i}frame that is |
358 |
|| (!closest.isNull() && closest.parentAlignment >= candidate.alignment |
| 353 |
// preferable to get focused. |
359 |
&& closest.document() == candidate.document())) { |
| 354 |
if (focusedNode->document() == candidate->document() |
360 |
|
| 355 |
&& distance < closestFocusCandidate.parentDistance) { |
361 |
// If we are now in an higher precedent case, lets reset the current |closest|'s |
| 356 |
closestFocusCandidate.node = candidate; |
362 |
// |distance| so we force it to be bigger than any result we will get from |
| 357 |
closestFocusCandidate.distance = distance; |
363 |
// |spatialDistance()| (see below). |
| 358 |
closestFocusCandidate.parentDistance = maxDistance(); |
364 |
if (closest.alignment < candidate.alignment |
| 359 |
} else if (focusedNode->document() != candidate->document()) { |
365 |
&& closest.parentAlignment < candidate.alignment) |
| 360 |
// If the |focusedNode| is in an inner document and the |candidate| is |
366 |
closest.distance = maxDistance(); |
| 361 |
// in a different document, we only consider to change focus if there is |
367 |
|
| 362 |
// not another already good focusable candidate in the same document as |
368 |
closest.alignment = candidate.alignment; |
| 363 |
// |focusedNode|. |
369 |
} |
| 364 |
if (!((isInRootDocument(candidate) && !isInRootDocument(focusedNode)) |
370 |
|
| 365 |
&& focusedNode->document() == closestFocusCandidate.document())) { |
371 |
// Bail out if candidate's distance is bigger than the closest candidate's distance. |
| 366 |
closestFocusCandidate.node = candidate; |
372 |
if (candidate.distance >= closest.distance) |
| 367 |
closestFocusCandidate.distance = distance; |
373 |
return; |
| 368 |
} |
374 |
|
|
|
375 |
// If |focusedNode| and |candidate| are in the same document and current |
| 376 |
// |closest| is not in an {i}frame that is preferable to get focused ... |
| 377 |
if (focusedNode->document() == candidate.document() |
| 378 |
&& candidate.distance < closest.parentDistance) |
| 379 |
closest = candidate; |
| 380 |
else if (focusedNode->document() != candidate.document()) { |
| 381 |
// If the |focusedNode| is in an inner document and |candidate| is in a |
| 382 |
// different document, we only consider to change focus if there is not |
| 383 |
// another already good focusable candidate in the same document as |focusedNode|. |
| 384 |
if (!((isInRootDocument(candidate.node) && !isInRootDocument(focusedNode)) |
| 385 |
&& focusedNode->document() == closest.document())) |
| 386 |
closest = candidate; |
| 369 |
} |
387 |
} |
| 370 |
} |
388 |
} |
| 371 |
|
389 |
|
| 372 |
void FocusController::findFocusableNodeInDirection(Document* document, Node* focusedNode, FocusDirection direction, KeyboardEvent* event, FocusCandidate& closestFocusCandidate) |
390 |
void FocusController::findFocusableNodeInDirection(Document* document, Node* focusedNode, FocusDirection direction, KeyboardEvent* event, FocusCandidate& closestFocusCandidate, FocusCandidate candidateParent) |
| 373 |
{ |
391 |
{ |
| 374 |
ASSERT(document); |
392 |
ASSERT(document); |
| 375 |
|
393 |
|
| 376 |
// Walk all the child nodes and update focusCandidate if we find a nearer node. |
394 |
// Walk all the child nodes and update |closestFocusCandidate| if we find a nearer node. |
| 377 |
for (Node* candidate = document->firstChild(); candidate; candidate = candidate->traverseNextNode()) { |
395 |
for (Node* candidate = document->firstChild(); candidate; candidate = candidate->traverseNextNode()) { |
| 378 |
// Inner documents case. |
396 |
// Inner documents case. |
|
|
397 |
|
| 379 |
if (candidate->isFrameOwnerElement()) |
398 |
if (candidate->isFrameOwnerElement()) |
| 380 |
deepFindFocusableNodeInDirection(focusedNode, candidate, direction, event, closestFocusCandidate); |
399 |
deepFindFocusableNodeInDirection(focusedNode, candidate, direction, event, closestFocusCandidate); |
| 381 |
else if (candidate != focusedNode && candidate->isKeyboardFocusable(event)) { |
400 |
else if (candidate != focusedNode && candidate->isKeyboardFocusable(event)) { |
| 382 |
long long distance = distanceInDirection(focusedNode, candidate, |
401 |
FocusCandidate currentFocusCandidate(candidate); |
| 383 |
direction, closestFocusCandidate); |
402 |
|
| 384 |
updateFocusCandidateIfCloser(focusedNode, candidate, distance, closestFocusCandidate); |
403 |
// Get distance and alignment from current candidate. |
|
|
404 |
distanceDataForNode(direction, focusedNode, currentFocusCandidate); |
| 405 |
|
| 406 |
// If |candidateParent| is not Null, it means that we are in a recursive call |
| 407 |
// from deepFineFocusableNodeInDirection (i.e. processing an element in an iframe), |
| 408 |
// and holds the distance and alignment data of the iframe element itself. |
| 409 |
if (!candidateParent.isNull()) { |
| 410 |
currentFocusCandidate.parentAlignment = candidateParent.alignment; |
| 411 |
currentFocusCandidate.parentDistance = candidateParent.distance; |
| 412 |
} |
| 413 |
|
| 414 |
updateFocusCandidateIfCloser(focusedNode, currentFocusCandidate, closestFocusCandidate); |
| 385 |
} |
415 |
} |
| 386 |
} |
416 |
} |
| 387 |
} |
417 |
} |
|
Lines 397-420
void FocusController::deepFindFocusableNodeInDirection(Node* focusedNode, Node*
a/WebCore/page/FocusController.cpp_sec3
|
| 397 |
return; |
427 |
return; |
| 398 |
|
428 |
|
| 399 |
if (innerDocument == focusedNode->document()) |
429 |
if (innerDocument == focusedNode->document()) |
| 400 |
findFocusableNodeInDirection(innerDocument, focusedNode, direction, event, closestFocusCandidate); |
430 |
findFocusableNodeInDirection(innerDocument, focusedNode, direction, event, closestFocusCandidate, FocusCandidate()); |
| 401 |
else { |
431 |
else { |
| 402 |
// Check if the current {i}frame element itself is a good candidate |
432 |
// Check if the current {i}frame element itself is a good candidate |
| 403 |
// to move focus to. If it is, then we traverse its inner nodes. |
433 |
// to move focus to. If it is, then we traverse its inner nodes. |
| 404 |
// Lets pass a copy of the best candidate, to not get fooled by a |
434 |
FocusCandidate candidateParent = FocusCandidate(candidate); |
| 405 |
// frame without focusable elements. |
435 |
distanceDataForNode(direction, focusedNode, candidateParent); |
| 406 |
FocusCandidate focusCandidateCopy = closestFocusCandidate; |
436 |
|
| 407 |
long long distance = distanceInDirection(focusedNode, candidate, direction, focusCandidateCopy); |
437 |
// FIXME: What about aligment? |
| 408 |
if (distance < focusCandidateCopy.distance) { |
438 |
if (candidateParent.distance < closestFocusCandidate.distance) |
| 409 |
focusCandidateCopy.parentAlignment = focusCandidateCopy.alignment; |
439 |
findFocusableNodeInDirection(innerDocument, focusedNode, direction, event, closestFocusCandidate, candidateParent); |
| 410 |
focusCandidateCopy.parentDistance = distance; |
|
|
| 411 |
|
| 412 |
findFocusableNodeInDirection(innerDocument, focusedNode, direction, event, focusCandidateCopy); |
| 413 |
|
| 414 |
// If we really have an inner closer focus candidate node, take it. |
| 415 |
if (closestFocusCandidate.node != focusCandidateCopy.node) |
| 416 |
closestFocusCandidate = focusCandidateCopy; |
| 417 |
} |
| 418 |
} |
440 |
} |
| 419 |
} |
441 |
} |
| 420 |
|
442 |
|