Bug 1735076 - Use ProgrammaticFocusFlags from nsXULCommandDispatcher. r=smaug

Relevant calls are here:

  https://searchfox.org/mozilla-central/rev/21a9b72545da06681db97c4b3a2a6be761f4aae5/toolkit/content/widgets/button.js#42-68

This makes sure to set the FLAG_BYKEY properly if needed, instead of passing
down raw flags to nsFocusManager. Clean up a bit while at it.

Let me know if you want a test for this, but we have tests for programmatic
focus and :focus-visible already, so my gut feeling is that testing this
particular XUL-specific change is not super-worth-it...

Differential Revision: https://phabricator.services.mozilla.com/D133690
This commit is contained in:
Emilio Cobos Álvarez
2021-12-23 18:34:05 +00:00
parent d1811d01d1
commit 8b56890b85
5 changed files with 49 additions and 39 deletions

View File

@@ -462,22 +462,17 @@ nsFocusManager::GetFocusedElement(Element** aFocusedElement) {
return NS_OK;
}
uint32_t nsFocusManager::GetLastFocusMethod(nsPIDOMWindowOuter* aWindow) const {
nsPIDOMWindowOuter* window = aWindow ? aWindow : mFocusedWindow.get();
uint32_t method = window ? window->GetFocusMethod() : 0;
NS_ASSERTION((method & METHOD_MASK) == method, "invalid focus method");
return method;
}
NS_IMETHODIMP
nsFocusManager::GetLastFocusMethod(mozIDOMWindowProxy* aWindow,
uint32_t* aLastFocusMethod) {
// the focus method is stored on the inner window
nsCOMPtr<nsPIDOMWindowOuter> window;
if (aWindow) {
window = nsPIDOMWindowOuter::From(aWindow);
}
if (!window) {
window = mFocusedWindow;
}
*aLastFocusMethod = window ? window->GetFocusMethod() : 0;
NS_ASSERTION((*aLastFocusMethod & METHOD_MASK) == *aLastFocusMethod,
"invalid focus method");
*aLastFocusMethod = GetLastFocusMethod(nsPIDOMWindowOuter::From(aWindow));
return NS_OK;
}

View File

@@ -163,6 +163,9 @@ class nsFocusManager final : public nsIFocusManager,
*/
void UpdateCaretForCaretBrowsingMode();
/** @see nsIFocusManager.getLastFocusMethod() */
uint32_t GetLastFocusMethod(nsPIDOMWindowOuter*) const;
/**
* Returns the content node that would be focused if aWindow was in an
* active window. This will traverse down the frame hierarchy, starting at

View File

@@ -3755,11 +3755,18 @@ nsresult HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor) {
!aVisitor.mEvent->AsFocusEvent()->mFromRaise &&
SelectTextFieldOnFocus()) {
if (Document* document = GetComposedDoc()) {
uint32_t lastFocusMethod;
fm->GetLastFocusMethod(document->GetWindow(), &lastFocusMethod);
if (lastFocusMethod & (nsIFocusManager::FLAG_BYKEY |
nsIFocusManager::FLAG_BYMOVEFOCUS) &&
!(lastFocusMethod & nsIFocusManager::FLAG_BYJS)) {
uint32_t lastFocusMethod =
fm->GetLastFocusMethod(document->GetWindow());
const bool shouldSelectAllOnFocus = [&] {
if (lastFocusMethod & nsIFocusManager::FLAG_BYMOVEFOCUS) {
return true;
}
if (lastFocusMethod & nsIFocusManager::FLAG_BYJS) {
return false;
}
return bool(lastFocusMethod & nsIFocusManager::FLAG_BYKEY);
}();
if (shouldSelectAllOnFocus) {
RefPtr<nsPresContext> presContext =
GetPresContext(eForComposedDoc);
DispatchSelectEvent(presContext);

View File

@@ -27,6 +27,7 @@
#include "mozilla/BasicEvents.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ElementBinding.h"
using namespace mozilla;
using mozilla::dom::Document;
@@ -193,29 +194,30 @@ nsXULCommandDispatcher::AdvanceFocus() {
}
NS_IMETHODIMP
nsXULCommandDispatcher::RewindFocus() {
nsCOMPtr<nsPIDOMWindowOuter> win;
GetRootFocusedContentAndWindow(getter_AddRefs(win));
RefPtr<Element> result;
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm)
return fm->MoveFocus(win, nullptr, nsIFocusManager::MOVEFOCUS_BACKWARD, 0,
getter_AddRefs(result));
return NS_OK;
nsXULCommandDispatcher::AdvanceFocusIntoSubtree(Element* aElt) {
return MoveFocusIntoSubtree(aElt, /* aForward = */ true);
}
NS_IMETHODIMP
nsXULCommandDispatcher::AdvanceFocusIntoSubtree(Element* aElt) {
nsXULCommandDispatcher::RewindFocus() {
return MoveFocusIntoSubtree(nullptr, /* aForward = */ false);
}
nsresult nsXULCommandDispatcher::MoveFocusIntoSubtree(Element* aElt,
bool aForward) {
nsCOMPtr<nsPIDOMWindowOuter> win;
GetRootFocusedContentAndWindow(getter_AddRefs(win));
RefPtr<Element> result;
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm)
return fm->MoveFocus(win, aElt, nsIFocusManager::MOVEFOCUS_FORWARD, 0,
getter_AddRefs(result));
return NS_OK;
if (!fm) {
return NS_OK;
}
auto flags = nsFocusManager::ProgrammaticFocusFlags(dom::FocusOptions()) |
nsIFocusManager::FLAG_BYMOVEFOCUS;
auto type = aForward ? nsIFocusManager::MOVEFOCUS_FORWARD
: nsIFocusManager::MOVEFOCUS_BACKWARD;
return fm->MoveFocus(win, aElt, type, flags, getter_AddRefs(result));
}
NS_IMETHODIMP

View File

@@ -32,8 +32,11 @@ class Element;
class nsXULCommandDispatcher : public nsIDOMXULCommandDispatcher,
public nsSupportsWeakReference {
using Document = mozilla::dom::Document;
using Element = mozilla::dom::Element;
public:
explicit nsXULCommandDispatcher(mozilla::dom::Document* aDocument);
explicit nsXULCommandDispatcher(Document* aDocument);
// nsISupports
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -50,21 +53,21 @@ class nsXULCommandDispatcher : public nsIDOMXULCommandDispatcher,
already_AddRefed<nsPIWindowRoot> GetWindowRoot();
mozilla::dom::Element* GetRootFocusedContentAndWindow(
nsPIDOMWindowOuter** aWindow);
Element* GetRootFocusedContentAndWindow(nsPIDOMWindowOuter** aWindow);
nsresult MoveFocusIntoSubtree(Element*, bool aForward);
RefPtr<mozilla::dom::Document> mDocument;
RefPtr<Document> mDocument;
class Updater {
public:
Updater(mozilla::dom::Element* aElement, const nsAString& aEvents,
Updater(Element* aElement, const nsAString& aEvents,
const nsAString& aTargets)
: mElement(aElement),
mEvents(aEvents),
mTargets(aTargets),
mNext(nullptr) {}
RefPtr<mozilla::dom::Element> mElement;
RefPtr<Element> mElement;
nsString mEvents;
nsString mTargets;
Updater* mNext;