1
0
mirror of https://github.com/roytam1/UXP.git synced 2026-05-26 05:46:58 +00:00

Issue #2548 - Part 5 - Implement the HTMLOrForeignElement mixin. https://bugzilla.mozilla.org/show_bug.cgi?id=1577660 Add 'preventScroll' option to HTMLElement's, SVGElement's and XULElement's 'focus' method. https://bugzilla.mozilla.org/show_bug.cgi?id=1374045

This commit is contained in:
Brian Smith
2026-03-20 03:19:58 -05:00
committed by roytam1
parent 502c704770
commit 3febe21f99
20 changed files with 78 additions and 43 deletions
+8 -2
View File
@@ -308,12 +308,18 @@ Element::TabIndex()
}
void
Element::Focus(mozilla::ErrorResult& aError)
Element::Focus(const FocusOptions& aOptions, ErrorResult& aError)
{
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(this);
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
// Also other browsers seem to have the hack to not re-focus (and flush) when
// the element is already focused.
// Until https://github.com/whatwg/html/issues/4512 is clarified, we'll
// maintain interoperatibility by not re-focusing, independent of aOptions.
// I.e., `focus({ preventScroll: true})` followed by `focus( { preventScroll:
// false })` won't re-focus.
if (fm && domElement) {
aError = fm->SetFocus(domElement, 0);
aError = fm->SetFocus(domElement, nsFocusManager::FocusOptionsToFocusManagerFlags(aOptions));
}
}
+1 -1
View File
@@ -216,7 +216,7 @@ public:
/**
* Make focus on this element.
*/
virtual void Focus(mozilla::ErrorResult& aError);
virtual void Focus(const FocusOptions& aOptions, ErrorResult& aError);
/**
* Show blur and clear focus.
+6
View File
@@ -48,6 +48,7 @@
#include "mozilla/ContentEvents.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ElementBinding.h"
#include "mozilla/dom/ShadowRoot.h"
#include "mozilla/dom/HTMLInputElement.h"
#include "mozilla/dom/HTMLSlotElement.h"
@@ -3005,6 +3006,11 @@ nsFocusManager::DetermineElementToMoveFocus(nsPIDOMWindowOuter* aWindow,
return NS_OK;
}
uint32_t nsFocusManager::FocusOptionsToFocusManagerFlags(
const mozilla::dom::FocusOptions& aOptions) {
return aOptions.mPreventScroll ? nsIFocusManager::FLAG_NOSCROLL : 0;
}
static bool
IsHostOrSlot(nsIContent* aContent)
{
+4
View File
@@ -26,6 +26,7 @@ class nsIMessageBroadcaster;
namespace mozilla {
namespace dom {
struct FocusOptions;
class TabParent;
}
}
@@ -110,6 +111,9 @@ public:
static nsIContent* GetFocusedDescendant(nsPIDOMWindowOuter* aWindow, bool aDeep,
nsPIDOMWindowOuter** aFocusedWindow);
static uint32_t FocusOptionsToFocusManagerFlags(
const mozilla::dom::FocusOptions& aOptions);
/**
* Returns the content node that focus will be redirected to if aContent was
* focused. This is used for the special case of certain XUL elements such
+3 -3
View File
@@ -3590,7 +3590,7 @@ HTMLInputElement::Blur(ErrorResult& aError)
}
void
HTMLInputElement::Focus(ErrorResult& aError)
HTMLInputElement::Focus(const FocusOptions& aOptions, ErrorResult& aError)
{
if (mType == NS_FORM_INPUT_NUMBER) {
// Focus our anonymous text control, if we have one.
@@ -3600,7 +3600,7 @@ HTMLInputElement::Focus(ErrorResult& aError)
RefPtr<HTMLInputElement> textControl =
numberControlFrame->GetAnonTextControl();
if (textControl) {
textControl->Focus(aError);
textControl->Focus(aOptions, aError);
return;
}
}
@@ -3616,7 +3616,7 @@ HTMLInputElement::Focus(ErrorResult& aError)
}
if (mType != NS_FORM_INPUT_FILE) {
nsGenericHTMLElement::Focus(aError);
nsGenericHTMLElement::Focus(aOptions, aError);
return;
}
+2 -1
View File
@@ -134,7 +134,8 @@ public:
virtual int32_t TabIndexDefault() override;
using nsGenericHTMLElement::Focus;
virtual void Blur(ErrorResult& aError) override;
virtual void Focus(ErrorResult& aError) override;
virtual void Focus(const FocusOptions& aOptions,
ErrorResult& aError) override;
// nsINode
#if !defined(ANDROID) && !defined(XP_MACOSX)
+3 -2
View File
@@ -93,14 +93,15 @@ HTMLLabelElement::GetForm() const
}
void
HTMLLabelElement::Focus(ErrorResult& aError)
HTMLLabelElement::Focus(const FocusOptions& aOptions,
ErrorResult& aError)
{
// retarget the focus method at the for content
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
nsCOMPtr<nsIDOMElement> elem = do_QueryObject(GetLabeledElement());
if (elem)
fm->SetFocus(elem, 0);
fm->SetFocus(elem, nsFocusManager::FocusOptionsToFocusManagerFlags(aOptions));
}
}
+2 -1
View File
@@ -56,7 +56,8 @@ public:
}
using nsGenericHTMLElement::Focus;
virtual void Focus(mozilla::ErrorResult& aError) override;
virtual void Focus(const FocusOptions& aOptions,
ErrorResult& aError) override;
virtual bool IsDisabled() const override { return false; }
+8 -5
View File
@@ -86,7 +86,8 @@ HTMLLegendElement::UnbindFromTree(bool aDeep, bool aNullParent)
}
void
HTMLLegendElement::Focus(ErrorResult& aError)
HTMLLegendElement::Focus(const FocusOptions& aOptions,
ErrorResult& aError)
{
nsIFrame* frame = GetPrimaryFrame();
if (!frame) {
@@ -95,7 +96,7 @@ HTMLLegendElement::Focus(ErrorResult& aError)
int32_t tabIndex;
if (frame->IsFocusable(&tabIndex, false)) {
nsGenericHTMLElement::Focus(aError);
nsGenericHTMLElement::Focus(aOptions, aError);
return;
}
@@ -108,7 +109,8 @@ HTMLLegendElement::Focus(ErrorResult& aError)
nsCOMPtr<nsIDOMElement> result;
aError = fm->MoveFocus(nullptr, this, nsIFocusManager::MOVEFOCUS_FORWARD,
nsIFocusManager::FLAG_NOPARENTFRAME,
nsIFocusManager::FLAG_NOPARENTFRAME |
nsFocusManager::FocusOptionsToFocusManagerFlags(aOptions),
getter_AddRefs(result));
}
@@ -116,9 +118,10 @@ bool
HTMLLegendElement::PerformAccesskey(bool aKeyCausesActivation,
bool aIsTrustedEvent)
{
// just use the same behaviour as the focus method
FocusOptions options;
ErrorResult rv;
Focus(rv);
Focus(options, rv);
return NS_SUCCEEDED(rv.StealNSResult());
}
+2 -1
View File
@@ -24,7 +24,8 @@ public:
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLLegendElement, legend)
using nsGenericHTMLElement::Focus;
virtual void Focus(ErrorResult& aError) override;
virtual void Focus(const FocusOptions& aOptions,
ErrorResult& aError) override;
virtual bool PerformAccesskey(bool aKeyCausesActivation,
bool aIsTrustedEvent) override;
+3 -2
View File
@@ -150,8 +150,9 @@ public:
// If something is focused in the same document, ignore autofocus.
if (!fm->GetFocusedContent() ||
fm->GetFocusedContent()->OwnerDoc() != document) {
mozilla::ErrorResult rv;
mElement->Focus(rv);
FocusOptions options;
ErrorResult rv;
mElement->Focus(options, rv);
return rv.StealNSResult();
}
+2 -1
View File
@@ -434,8 +434,9 @@ public:
return rv.StealNSResult();
}
NS_IMETHOD Focus() final override {
mozilla::dom::FocusOptions options;
mozilla::ErrorResult rv;
Focus(rv);
Focus(options, rv);
return rv.StealNSResult();
}
NS_IMETHOD GetDraggable(bool* aDraggable) final override {
+1 -2
View File
@@ -435,8 +435,7 @@ MathMLElement::ParseNumericValue(const nsString& aString,
number.Append(c);
}
if (/*StaticPrefs::mathml_legacy_number_syntax_disabled() &&*/ gotDot &&
str[i - 1] == '.') {
if (gotDot && str[i - 1] == '.') {
if (!(aFlags & PARSE_SUPPRESS_WARNINGS)) {
ReportLengthParseError(aString, aDocument);
}
+17
View File
@@ -169,6 +169,23 @@ interface mixin ElementCSSInlineStyle {
readonly attribute CSSStyleDeclaration style;
};
// https://html.spec.whatwg.org/#focus-management-apis
dictionary FocusOptions {
boolean preventScroll = false;
};
interface mixin HTMLOrForeignElement {
[SameObject] readonly attribute DOMStringMap dataset;
// See bug 1389421
// attribute DOMString nonce; // intentionally no [CEReactions]
// See bug 1575154
// [CEReactions] attribute boolean autofocus;
[CEReactions, SetterThrows, Pure] attribute long tabIndex;
[Throws] void focus(optional FocusOptions options);
[Throws] void blur();
};
// http://dev.w3.org/csswg/cssom-view/
enum ScrollLogicalPosition { "start", "center", "end", "nearest" };
dictionary ScrollIntoViewOptions : ScrollOptions {
+1 -8
View File
@@ -22,8 +22,6 @@ interface HTMLElement : Element {
// attribute boolean translate;
[CEReactions, SetterThrows, Pure]
attribute DOMString dir;
[Constant]
readonly attribute DOMStringMap dataset;
[CEReactions, GetterThrows, Pure]
attribute [TreatNullAs=EmptyString] DOMString innerText;
@@ -32,12 +30,6 @@ interface HTMLElement : Element {
[CEReactions, SetterThrows, Pure]
attribute boolean hidden;
void click();
[CEReactions, SetterThrows, Pure]
attribute long tabIndex;
[Throws]
void focus();
[Throws]
void blur();
[CEReactions, SetterThrows, Pure]
attribute DOMString accessKey;
[Pure]
@@ -92,6 +84,7 @@ interface mixin TouchEventHandlers {
};
HTMLElement includes GlobalEventHandlers;
HTMLElement includes HTMLOrForeignElement;
HTMLElement includes DocumentAndElementEventHandlers;
HTMLElement includes ElementCSSInlineStyle;
HTMLElement includes TouchEventHandlers;
+1 -1
View File
@@ -13,7 +13,7 @@
[Exposed=Window]
interface MathMLElement : Element { };
MathMLElement includes GlobalEventHandlers;
//MathMLElement includes HTMLOrForeignElement;
MathMLElement includes HTMLOrForeignElement;
MathMLElement includes DocumentAndElementEventHandlers;
MathMLElement includes ElementCSSInlineStyle;
MathMLElement includes TouchEventHandlers;
+1 -6
View File
@@ -15,18 +15,13 @@ interface SVGElement : Element {
[Constant]
readonly attribute SVGAnimatedString className;
[SameObject] readonly attribute DOMStringMap dataset;
readonly attribute SVGSVGElement? ownerSVGElement;
readonly attribute SVGElement? viewportElement;
[SetterThrows, Pure]
attribute long tabIndex;
[Throws] void focus();
[Throws] void blur();
};
SVGElement includes GlobalEventHandlers;
SVGElement includes HTMLOrForeignElement;
SVGElement includes DocumentAndElementEventHandlers;
SVGElement includes ElementCSSInlineStyle;
SVGElement includes TouchEventHandlers;
+1 -4
View File
@@ -96,10 +96,6 @@ interface XULElement : Element {
[Throws]
readonly attribute BoxObject? boxObject;
[Throws]
void focus();
[Throws]
void blur();
[Throws]
void click();
void doCommand();
@@ -134,6 +130,7 @@ interface mixin MozFrameLoaderOwner {
XULElement includes GlobalEventHandlers;
XULElement includes ElementCSSInlineStyle;
XULElement includes HTMLOrForeignElement;
XULElement includes TouchEventHandlers;
XULElement includes MozFrameLoaderOwner;
XULElement includes OnErrorEventHandlerForNodes;
+2 -1
View File
@@ -1720,7 +1720,8 @@ NS_IMETHODIMP
nsXULElement::Focus()
{
ErrorResult rv;
Focus(rv);
FocusOptions options;
Focus(options, rv);
return rv.StealNSResult();
}
+10 -2
View File
@@ -308,7 +308,11 @@ public:
NS_IMETHOD Run() override
{
if (mNumber->AsElement()->State().HasState(NS_EVENT_STATE_FOCUS)) {
HTMLInputElement::FromContent(mTextField)->Focus();
// This job shouldn't be triggered by a WebIDL interface, hence the
// default options can be used.
FocusOptions options;
ErrorResult rv;
HTMLInputElement::FromContent(mTextField)->Focus(options, rv);
}
return NS_OK;
@@ -595,7 +599,11 @@ nsNumberControlFrame::HandleFocusEvent(WidgetEvent* aEvent)
if (aEvent->mOriginalTarget != mTextField) {
// Move focus to our text field
RefPtr<HTMLInputElement> textField = HTMLInputElement::FromContent(mTextField);
textField->Focus();
// Use default FocusOptions, because this method isn't supposed to be called
// from a WebIDL interface.
FocusOptions options;
ErrorResult rv;
textField->Focus(options, rv);
}
}