Commit d95d7abd authored by Emilio Cobos Álvarez's avatar Emilio Cobos Álvarez
Browse files

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
parent 3133373f
Loading
Loading
Loading
Loading
+8 −13
Original line number Diff line number Diff line
@@ -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;
}

+3 −0
Original line number Diff line number Diff line
@@ -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
+12 −5
Original line number Diff line number Diff line
@@ -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);
+17 −15
Original line number Diff line number Diff line
@@ -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,30 +194,31 @@ 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));
  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
nsXULCommandDispatcher::AddCommandUpdater(Element* aElement,
+9 −6
Original line number Diff line number Diff line
@@ -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;