Bug 1195672 - Make focus changing by long tap behaves like by single tap. f=mtseng, r=roc

We want the focus changing behavior by long tap as close as to the one
by single tap.

The only functional change is that we always clear old focus and
re-focus the window if a focusable frame cannot be found. This behavior
is the same as the single tap implemented in
EventStateManager::PostHandleEvent().

Besides, ChangeFocus now returns the new focusable frame instead of bool
which provides more information.
This commit is contained in:
Ting-Yu Lin 2015-08-19 15:54:10 +08:00
parent f6d8e741db
commit a52d8e0b25
2 changed files with 26 additions and 31 deletions

View File

@ -502,46 +502,38 @@ AccessibleCaretManager::GetCaretMode() const
return CaretMode::Selection;
}
bool
nsIFrame*
AccessibleCaretManager::ChangeFocus(nsIFrame* aFrame) const
{
nsIFrame* currFrame = aFrame;
nsIContent* newFocusContent = nullptr;
while (currFrame) {
int32_t tabIndexUnused = 0;
if (currFrame->IsFocusable(&tabIndexUnused, true)) {
newFocusContent = currFrame->GetContent();
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(newFocusContent));
if (domElement)
break;
// This implementation is similar to EventStateManager::PostHandleEvent().
// Look for the nearest enclosing focusable frame.
nsIFrame* focusableFrame = aFrame;
while (focusableFrame) {
if (focusableFrame->IsFocusable(nullptr, true)) {
break;
}
currFrame = currFrame->GetParent();
focusableFrame = focusableFrame->GetParent();
}
// If target frame is focusable, we should move focus to it. If target frame
// isn't focusable, and our previous focused content is editable, we should
// clear focus.
// If a focusable frame is found, move focus to it. Otherwise, clear the old
// focus then re-focus the window.
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (newFocusContent && currFrame) {
nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(newFocusContent));
fm->SetFocus(domElement, 0);
MOZ_ASSERT(fm);
if (focusableFrame) {
nsIContent* focusableContent = focusableFrame->GetContent();
MOZ_ASSERT(focusableContent, "Focusable frame must have content!");
nsCOMPtr<nsIDOMElement> focusableElement = do_QueryInterface(focusableContent);
fm->SetFocus(focusableElement, nsIFocusManager::FLAG_BYMOUSE);
} else {
nsIContent* focusedContent = GetFocusedContent();
if (focusedContent) {
// Clear focus if content was editable element, or contentEditable.
nsGenericHTMLElement* focusedGeneric =
nsGenericHTMLElement::FromContent(focusedContent);
if (focusedContent->GetTextEditorRootContent() ||
(focusedGeneric && focusedGeneric->IsContentEditable())) {
nsIDOMWindow* win = mPresShell->GetDocument()->GetWindow();
if (win) {
fm->ClearFocus(win);
}
}
nsIDOMWindow* win = mPresShell->GetDocument()->GetWindow();
if (win) {
fm->ClearFocus(win);
fm->SetFocusedWindow(win);
}
}
return (newFocusContent && currFrame);
return focusableFrame;
}
nsresult

View File

@ -115,7 +115,10 @@ protected:
void UpdateCaretsForSelectionMode();
void UpdateCaretsForTilt();
bool ChangeFocus(nsIFrame* aFrame) const;
// Change focus to the nearest enclosing focusable frame of aFrame.
// @return focusable frame if there is any; nullptr otherwise.
nsIFrame* ChangeFocus(nsIFrame* aFrame) const;
nsresult SelectWord(nsIFrame* aFrame, const nsPoint& aPoint) const;
void SetSelectionDragState(bool aState) const;
void SetSelectionDirection(nsDirection aDir) const;