зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1689816 - Implement <tabpanels> and <deck> without XUL layout. r=Gijs,Jamie,morgan,preferences-reviewers,mconley,TYLin
Gijs for front-end bits, layout for the new CSS properties and the removal of nsDeckFrame / nsStackLayout, Jamie and Morgan for the a11y changes. As discussed in the bug, the main tricky part here is handling a11y correctly. For <deck>, that's trivial (just use `visibility: hidden` to hide the panels visually, while removing the unselected panels from the a11y tree). For <tabpanels> however we need to do something special. We do want to hide stuff visually, but we want to preserve the contents in the a11y tree. For that, the easiest fix is introducing a new privileged CSS property (-moz-subtree-hidden-only-visually), which takes care of not painting the frame, but marks stuff offscreen in the accessibility tree. This is not intended to be a property used widely. Other than that, the changes are relatively straight-forward, though some of the accessible/mac changes I could get a sanity-check on. Differential Revision: https://phabricator.services.mozilla.com/D157875
This commit is contained in:
Родитель
2bb8defd02
Коммит
4e978b56b5
|
@ -75,7 +75,6 @@
|
|||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPrefs_accessibility.h"
|
||||
#include "mozilla/SVGGeometryFrame.h"
|
||||
#include "nsDeckFrame.h"
|
||||
|
||||
#include "XULAlertAccessible.h"
|
||||
#include "XULComboboxAccessible.h"
|
||||
|
@ -443,62 +442,19 @@ LocalAccessible* nsAccessibilityService::GetRootDocumentAccessible(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void nsAccessibilityService::DeckPanelSwitched(PresShell* aPresShell,
|
||||
nsIContent* aDeckNode,
|
||||
nsIFrame* aPrevBoxFrame,
|
||||
nsIFrame* aCurrentBoxFrame) {
|
||||
void nsAccessibilityService::NotifyOfTabPanelVisibilityChange(
|
||||
PresShell* aPresShell, Element* aPanel, bool aNowVisible) {
|
||||
MOZ_ASSERT(aPanel->GetParent()->IsXULElement(nsGkAtoms::tabpanels));
|
||||
|
||||
DocAccessible* document = GetDocAccessible(aPresShell);
|
||||
if (!document) {
|
||||
return;
|
||||
}
|
||||
// A deck with a LocalAccessible is a tabpanels element.
|
||||
const bool isTabPanels = document->HasAccessible(aDeckNode);
|
||||
MOZ_ASSERT(!isTabPanels || aDeckNode->IsXULElement(nsGkAtoms::tabpanels),
|
||||
"A deck with a LocalAccessible should be a tabpanels element");
|
||||
|
||||
if (aPrevBoxFrame) {
|
||||
nsIContent* panelNode = aPrevBoxFrame->GetContent();
|
||||
#ifdef A11Y_LOG
|
||||
if (logging::IsEnabled(logging::eTree)) {
|
||||
logging::MsgBegin("TREE", "deck panel unselected");
|
||||
logging::Node("container", panelNode);
|
||||
logging::Node("content", aDeckNode);
|
||||
logging::MsgEnd();
|
||||
}
|
||||
#endif
|
||||
if (isTabPanels) {
|
||||
// Tabpanels are accessible even when not selected.
|
||||
if (LocalAccessible* acc = document->GetAccessible(panelNode)) {
|
||||
RefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(acc, states::OFFSCREEN, true);
|
||||
document->FireDelayedEvent(event);
|
||||
}
|
||||
} else {
|
||||
document->ContentRemoved(panelNode);
|
||||
}
|
||||
}
|
||||
|
||||
if (aCurrentBoxFrame) {
|
||||
nsIContent* panelNode = aCurrentBoxFrame->GetContent();
|
||||
#ifdef A11Y_LOG
|
||||
if (logging::IsEnabled(logging::eTree)) {
|
||||
logging::MsgBegin("TREE", "deck panel selected");
|
||||
logging::Node("container", panelNode);
|
||||
logging::Node("content", aDeckNode);
|
||||
logging::MsgEnd();
|
||||
}
|
||||
#endif
|
||||
if (isTabPanels) {
|
||||
// Tabpanels are accessible even when not selected, so we don't have to
|
||||
// insert a LocalAccessible.
|
||||
if (LocalAccessible* acc = document->GetAccessible(panelNode)) {
|
||||
RefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(acc, states::OFFSCREEN, false);
|
||||
document->FireDelayedEvent(event);
|
||||
}
|
||||
} else {
|
||||
document->ContentInserted(panelNode, panelNode->GetNextSibling());
|
||||
}
|
||||
if (LocalAccessible* acc = document->GetAccessible(aPanel)) {
|
||||
RefPtr<AccEvent> event =
|
||||
new AccStateChangeEvent(acc, states::OFFSCREEN, aNowVisible);
|
||||
document->FireDelayedEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1128,16 +1084,6 @@ LocalAccessible* nsAccessibilityService::CreateAccessible(
|
|||
|
||||
// XUL accessibles.
|
||||
if (!newAcc && content->IsXULElement()) {
|
||||
// No accessible for not selected deck panel and its children.
|
||||
if (!aContext->IsXULTabpanels()) {
|
||||
nsDeckFrame* deckFrame = do_QueryFrame(frame->GetParent());
|
||||
if (deckFrame && deckFrame->GetSelectedBox() != frame) {
|
||||
if (aIsSubtreeHidden) *aIsSubtreeHidden = true;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (content->IsXULElement(nsGkAtoms::panel)) {
|
||||
// We filter here instead of in the XUL map because
|
||||
// if we filter there and return null, we still end up
|
||||
|
|
|
@ -153,13 +153,6 @@ class nsAccessibilityService final : public mozilla::a11y::DocManager,
|
|||
void GetStringRelationType(uint32_t aRelationType, nsAString& aString);
|
||||
|
||||
// nsAccesibilityService
|
||||
/**
|
||||
* Notification used to update the accessible tree when deck panel is
|
||||
* switched.
|
||||
*/
|
||||
void DeckPanelSwitched(mozilla::PresShell* aPresShell, nsIContent* aDeckNode,
|
||||
nsIFrame* aPrevBoxFrame, nsIFrame* aCurrentBoxFrame);
|
||||
|
||||
/**
|
||||
* Notification used to update the accessible tree when new content is
|
||||
* inserted.
|
||||
|
@ -240,6 +233,10 @@ class nsAccessibilityService final : public mozilla::a11y::DocManager,
|
|||
void NotifyOfComputedStyleChange(mozilla::PresShell* aPresShell,
|
||||
nsIContent* aContent);
|
||||
|
||||
void NotifyOfTabPanelVisibilityChange(mozilla::PresShell* aPresShell,
|
||||
mozilla::dom::Element* aPanel,
|
||||
bool aVisible);
|
||||
|
||||
void NotifyOfResolutionChange(mozilla::PresShell* aPresShell,
|
||||
float aResolution);
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "nsAccCache.h"
|
||||
#include "nsAccessiblePivot.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsDeckFrame.h"
|
||||
#include "nsEventShell.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsTextEquivUtils.h"
|
||||
|
@ -1052,21 +1051,6 @@ LocalAccessible* DocAccessible::GetAccessibleOrContainer(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Check if node is in an unselected deck panel
|
||||
if (aNoContainerIfPruned && currNode->IsXULElement()) {
|
||||
if (nsIFrame* frame = currNode->AsContent()->GetPrimaryFrame()) {
|
||||
nsDeckFrame* deckFrame = do_QueryFrame(frame->GetParent());
|
||||
if (deckFrame && deckFrame->GetSelectedBox() != frame) {
|
||||
// If deck is not a <tabpanels>, return null
|
||||
nsIContent* parentFrameContent = deckFrame->GetContent();
|
||||
if (!parentFrameContent ||
|
||||
!parentFrameContent->IsXULElement(nsGkAtoms::tabpanels)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if node is in zero-sized map
|
||||
if (aNoContainerIfPruned && currNode->IsHTMLElement(nsGkAtoms::map)) {
|
||||
if (nsIFrame* frame = currNode->AsContent()->GetPrimaryFrame()) {
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
#include "nsIContent.h"
|
||||
#include "nsIFormControl.h"
|
||||
|
||||
#include "nsDeckFrame.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIFrame.h"
|
||||
|
@ -70,6 +69,7 @@
|
|||
#include "nsArrayUtils.h"
|
||||
#include "nsWhitespaceTokenizer.h"
|
||||
#include "nsAttrName.h"
|
||||
#include "nsContainerFrame.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/BasicEvents.h"
|
||||
|
@ -324,22 +324,16 @@ uint64_t LocalAccessible::VisibilityState() const {
|
|||
return states::INVISIBLE;
|
||||
}
|
||||
|
||||
if (nsLayoutUtils::IsPopup(curFrame)) return 0;
|
||||
|
||||
// Offscreen state for background tab content and invisible for not selected
|
||||
// deck panel.
|
||||
nsIFrame* parentFrame = curFrame->GetParent();
|
||||
nsDeckFrame* deckFrame = do_QueryFrame(parentFrame);
|
||||
if (deckFrame && deckFrame->GetSelectedBox() != curFrame) {
|
||||
if (deckFrame->GetContent()->IsXULElement(nsGkAtoms::tabpanels)) {
|
||||
return states::OFFSCREEN;
|
||||
}
|
||||
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Children of not selected deck panel are not accessible.");
|
||||
return states::INVISIBLE;
|
||||
if (nsLayoutUtils::IsPopup(curFrame)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (curFrame->StyleUIReset()->mMozSubtreeHiddenOnlyVisually) {
|
||||
// Offscreen state for background tab content.
|
||||
return states::OFFSCREEN;
|
||||
}
|
||||
|
||||
nsIFrame* parentFrame = curFrame->GetParent();
|
||||
// If contained by scrollable frame then check that at least 12 pixels
|
||||
// around the object is visible, otherwise the object is offscreen.
|
||||
nsIScrollableFrame* scrollableFrame = do_QueryFrame(parentFrame);
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "XULTabAccessible.h"
|
||||
#include "HTMLFormControlAccessible.h"
|
||||
|
||||
#include "nsDeckFrame.h"
|
||||
#include "nsObjCExceptions.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
|
@ -126,26 +125,17 @@ enum CheckboxValue {
|
|||
@implementation mozPaneAccessible
|
||||
|
||||
- (NSArray*)moxChildren {
|
||||
if (!mGeckoAccessible->AsLocal()) return nil;
|
||||
|
||||
nsDeckFrame* deckFrame =
|
||||
do_QueryFrame(mGeckoAccessible->AsLocal()->GetFrame());
|
||||
nsIFrame* selectedFrame = deckFrame ? deckFrame->GetSelectedBox() : nullptr;
|
||||
|
||||
LocalAccessible* selectedAcc = nullptr;
|
||||
if (selectedFrame) {
|
||||
nsINode* node = selectedFrame->GetContent();
|
||||
selectedAcc = mGeckoAccessible->AsLocal()->Document()->GetAccessible(node);
|
||||
// By default, all tab panels are exposed in the a11y tree
|
||||
// even if the tab they represent isn't the active tab. To
|
||||
// prevent VoiceOver from navigating background tab content,
|
||||
// only expose the tab panel that is currently on screen.
|
||||
for (mozAccessible* child in [super moxChildren]) {
|
||||
if (!([child state] & states::OFFSCREEN)) {
|
||||
return [NSArray arrayWithObject:GetObjectOrRepresentedView(child)];
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedAcc) {
|
||||
mozAccessible* curNative = GetNativeFromGeckoAccessible(selectedAcc);
|
||||
if (curNative)
|
||||
return
|
||||
[NSArray arrayWithObjects:GetObjectOrRepresentedView(curNative), nil];
|
||||
}
|
||||
|
||||
return nil;
|
||||
MOZ_ASSERT_UNREACHABLE("We have no on screen tab content?");
|
||||
return @[];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
// CSS display
|
||||
testCSSAttrs("display_mozbox");
|
||||
testCSSAttrs("display_mozinlinebox");
|
||||
testCSSAttrs("display_mozdeck");
|
||||
testCSSAttrs("display_mozpopup");
|
||||
|
||||
SimpleTest.finish();
|
||||
|
@ -50,7 +49,6 @@
|
|||
|
||||
<vbox id="display_mozbox" style="display: -moz-box;" role="img"/>
|
||||
<vbox id="display_mozinlinebox" style="display: -moz-inline-box;" role="img"/>
|
||||
<vbox id="display_mozdeck" style="display: -moz-deck;" role="img"/>
|
||||
<vbox id="display_mozpopup" style="display: -moz-popup;" role="img"/>
|
||||
|
||||
</hbox>
|
||||
|
|
|
@ -2171,23 +2171,23 @@ var gBrowserInit = {
|
|||
return;
|
||||
}
|
||||
|
||||
if (gBrowser.selectedBrowser.isRemoteBrowser) {
|
||||
// If the initial browser is remote, in order to optimize for first paint,
|
||||
// we'll defer switching focus to that browser until it has painted.
|
||||
this._firstContentWindowPaintDeferred.promise.then(() => {
|
||||
// If focus didn't move while we were waiting for first paint, we're okay
|
||||
// to move to the browser.
|
||||
if (
|
||||
document.commandDispatcher.focusedElement == initiallyFocusedElement
|
||||
) {
|
||||
gBrowser.selectedBrowser.focus();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// If the initial browser is not remote, we can focus the browser
|
||||
// immediately with no paint performance impact.
|
||||
gBrowser.selectedBrowser.focus();
|
||||
}
|
||||
// If the initial browser is remote, in order to optimize for first paint,
|
||||
// we'll defer switching focus to that browser until it has painted.
|
||||
// Otherwise use a regular promise to guarantee that mutationobserver
|
||||
// microtasks that could affect focusability have run.
|
||||
let promise = gBrowser.selectedBrowser.isRemoteBrowser
|
||||
? this._firstContentWindowPaintDeferred.promise
|
||||
: Promise.resolve();
|
||||
|
||||
promise.then(() => {
|
||||
// If focus didn't move while we were waiting, we're okay to move to
|
||||
// the browser.
|
||||
if (
|
||||
document.commandDispatcher.focusedElement == initiallyFocusedElement
|
||||
) {
|
||||
gBrowser.selectedBrowser.focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Delay removing the attribute using requestAnimationFrame to avoid
|
||||
|
|
|
@ -47,7 +47,7 @@ add_task(async function() {
|
|||
Assert.equal(
|
||||
win.document.activeElement,
|
||||
expectedActiveElement,
|
||||
uri + ": the active element is expected"
|
||||
`${uri}: the active element is expected: ${win.document.activeElement?.nodeName}`
|
||||
);
|
||||
Assert.equal(win.gURLBar.value, "", uri + ": urlbar is empty");
|
||||
Assert.ok(win.gURLBar.placeholder, uri + ": placeholder text is present");
|
||||
|
|
|
@ -254,11 +254,7 @@ add_task(async function() {
|
|||
|
||||
// The widget is still fetching tabs, as we've neutered everything that
|
||||
// provides them
|
||||
is(
|
||||
deck.selectedIndex,
|
||||
"" + DECKINDEX_FETCHING,
|
||||
"first deck entry is visible"
|
||||
);
|
||||
is(deck.selectedIndex, DECKINDEX_FETCHING, "first deck entry is visible");
|
||||
|
||||
// Tell the widget there are tabs available, but with zero clients.
|
||||
mockedInternal.getTabClients = () => {
|
||||
|
@ -269,7 +265,7 @@ add_task(async function() {
|
|||
// The UI should be showing the "no clients" pane.
|
||||
is(
|
||||
deck.selectedIndex,
|
||||
"" + DECKINDEX_NOCLIENTS,
|
||||
DECKINDEX_NOCLIENTS,
|
||||
"no-clients deck entry is visible"
|
||||
);
|
||||
|
||||
|
@ -320,11 +316,7 @@ add_task(async function() {
|
|||
await updateTabsPanel();
|
||||
|
||||
// The UI should be showing tabs!
|
||||
is(
|
||||
deck.selectedIndex,
|
||||
"" + DECKINDEX_TABS,
|
||||
"no-clients deck entry is visible"
|
||||
);
|
||||
is(deck.selectedIndex, DECKINDEX_TABS, "no-clients deck entry is visible");
|
||||
let tabList = document.getElementById("PanelUI-remotetabs-tabslist");
|
||||
let node = tabList.firstElementChild;
|
||||
// First entry should be the client with the most-recent tab.
|
||||
|
@ -467,7 +459,7 @@ add_task(async function() {
|
|||
let subpanel = document.getElementById("PanelUI-remotetabs-main");
|
||||
ok(!subpanel.hidden, "main pane is visible");
|
||||
let deck = document.getElementById("PanelUI-remotetabs-deck");
|
||||
is(deck.selectedIndex, "" + DECKINDEX_TABS, "we should be showing tabs");
|
||||
is(deck.selectedIndex, DECKINDEX_TABS, "we should be showing tabs");
|
||||
|
||||
function checkTabsPage(tabsShownCount, showMoreLabel) {
|
||||
let tabList = document.getElementById("PanelUI-remotetabs-tabslist");
|
||||
|
|
|
@ -25,7 +25,7 @@ add_task(async function() {
|
|||
);
|
||||
is(
|
||||
weavePrefsDeck.selectedIndex,
|
||||
"0",
|
||||
0,
|
||||
"Should select the #noFxaAccount child node"
|
||||
);
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ add_task(async function test_infobar() {
|
|||
let notif = showTranslationUI("fr");
|
||||
is(
|
||||
notif.state,
|
||||
"" + Translation.STATE_OFFER,
|
||||
Translation.STATE_OFFER,
|
||||
"the infobar is offering translation"
|
||||
);
|
||||
is(
|
||||
|
@ -117,7 +117,7 @@ add_task(async function test_infobar() {
|
|||
notif._getAnonElt("translate").click();
|
||||
is(
|
||||
notif.state,
|
||||
"" + Translation.STATE_TRANSLATING,
|
||||
Translation.STATE_TRANSLATING,
|
||||
"the infobar is in the translating state"
|
||||
);
|
||||
ok(
|
||||
|
@ -134,14 +134,14 @@ add_task(async function test_infobar() {
|
|||
|
||||
info("Make the translation fail and check we are in the error state.");
|
||||
notif.translation.failTranslation();
|
||||
is(notif.state, "" + Translation.STATE_ERROR, "infobar in the error state");
|
||||
is(notif.state, Translation.STATE_ERROR, "infobar in the error state");
|
||||
checkURLBarIcon();
|
||||
|
||||
info("Click the try again button");
|
||||
notif._getAnonElt("tryAgain").click();
|
||||
is(
|
||||
notif.state,
|
||||
"" + Translation.STATE_TRANSLATING,
|
||||
Translation.STATE_TRANSLATING,
|
||||
"infobar in the translating state"
|
||||
);
|
||||
ok(
|
||||
|
@ -162,7 +162,7 @@ add_task(async function test_infobar() {
|
|||
notif.translation.finishTranslation();
|
||||
is(
|
||||
notif.state,
|
||||
"" + Translation.STATE_TRANSLATED,
|
||||
Translation.STATE_TRANSLATED,
|
||||
"infobar in the translated state"
|
||||
);
|
||||
checkURLBarIcon(true);
|
||||
|
@ -207,7 +207,7 @@ add_task(async function test_infobar() {
|
|||
from.doCommand();
|
||||
is(
|
||||
notif.state,
|
||||
"" + Translation.STATE_TRANSLATING,
|
||||
Translation.STATE_TRANSLATING,
|
||||
"infobar in the translating state"
|
||||
);
|
||||
ok(
|
||||
|
@ -232,7 +232,7 @@ add_task(async function test_infobar() {
|
|||
to.doCommand();
|
||||
is(
|
||||
notif.state,
|
||||
"" + Translation.STATE_TRANSLATING,
|
||||
Translation.STATE_TRANSLATING,
|
||||
"infobar in the translating state"
|
||||
);
|
||||
ok(
|
||||
|
@ -254,7 +254,7 @@ add_task(async function test_infobar() {
|
|||
notif = showTranslationUI("fr");
|
||||
is(
|
||||
notif.state,
|
||||
"" + Translation.STATE_OFFER,
|
||||
Translation.STATE_OFFER,
|
||||
"the infobar is offering translation"
|
||||
);
|
||||
is(
|
||||
|
@ -267,7 +267,7 @@ add_task(async function test_infobar() {
|
|||
notif._getAnonElt("translate").click();
|
||||
is(
|
||||
notif.state,
|
||||
"" + Translation.STATE_TRANSLATING,
|
||||
Translation.STATE_TRANSLATING,
|
||||
"the infobar is in the translating state"
|
||||
);
|
||||
ok(
|
||||
|
@ -332,7 +332,7 @@ add_task(async function test_infobar_using_page() {
|
|||
let notif = notificationBox.getNotificationWithValue("translation");
|
||||
is(
|
||||
notif.state,
|
||||
"" + Translation.STATE_OFFER,
|
||||
Translation.STATE_OFFER,
|
||||
"the infobar is offering translation"
|
||||
);
|
||||
is(
|
||||
|
|
|
@ -468,7 +468,7 @@ class AsyncTabSwitcher {
|
|||
let index = Array.prototype.indexOf.call(tabpanels.children, showPanel);
|
||||
if (index != -1) {
|
||||
this.log(`Switch to tab ${index} - ${this.tinfo(showTab)}`);
|
||||
tabpanels.setAttribute("selectedIndex", index);
|
||||
tabpanels.updateSelectedIndex(index);
|
||||
if (showTab === this.requestedTab) {
|
||||
if (requestedTabState == this.STATE_LOADED) {
|
||||
// The new tab will be made visible in the next paint, record the expected
|
||||
|
|
|
@ -397,9 +397,11 @@ moz-input-box > menupopup .context-menu-add-engine > .menu-iconic-left {
|
|||
}
|
||||
|
||||
#tabbrowser-tabs {
|
||||
/* overriding tabbox.css */
|
||||
-moz-box-align: stretch;
|
||||
margin-bottom: 0;
|
||||
position: static;
|
||||
z-index: auto;
|
||||
}
|
||||
|
||||
/* Bookmark drag and drop styles */
|
||||
|
|
|
@ -113,6 +113,7 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
|
|||
"object-fit",
|
||||
"-moz-orient",
|
||||
"-moz-osx-font-smoothing",
|
||||
"-moz-subtree-hidden-only-visually",
|
||||
"outline-style",
|
||||
"overflow-anchor",
|
||||
"overflow-block",
|
||||
|
|
|
@ -10,18 +10,14 @@
|
|||
#include "Layers.h"
|
||||
#include "mozilla/dom/BrowserChild.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/gfx/gfxVars.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
#include "mozilla/layers/APZCCallbackHelper.h"
|
||||
#include "mozilla/layers/APZPublicUtils.h"
|
||||
#include "mozilla/layers/CompositorBridgeChild.h"
|
||||
#include "mozilla/layers/LayersMessageUtils.h"
|
||||
#include "mozilla/layers/PAPZ.h"
|
||||
#include "mozilla/layers/RepaintRequest.h"
|
||||
#include "mozilla/PresShell.h"
|
||||
#include "mozilla/StaticPrefs_layers.h"
|
||||
#include "mozilla/StaticPrefs_layout.h"
|
||||
#include "nsDeckFrame.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsPlaceholderFrame.h"
|
||||
|
@ -33,13 +29,9 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
using gfx::gfxVars;
|
||||
using gfx::IntSize;
|
||||
|
||||
using layers::APZCCallbackHelper;
|
||||
using layers::FrameMetrics;
|
||||
using layers::LayerManager;
|
||||
using layers::RepaintRequest;
|
||||
using layers::ScrollableLayerGuid;
|
||||
|
||||
typedef ScrollableLayerGuid::ViewID ViewID;
|
||||
|
@ -805,12 +797,11 @@ bool DisplayPortUtils::CalculateAndSetDisplayPortMargins(
|
|||
aRepaintMode);
|
||||
}
|
||||
|
||||
bool DisplayPortUtils::MaybeCreateDisplayPort(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aScrollFrame,
|
||||
RepaintMode aRepaintMode) {
|
||||
bool DisplayPortUtils::MaybeCreateDisplayPort(
|
||||
nsDisplayListBuilder* aBuilder, nsIFrame* aScrollFrame,
|
||||
nsIScrollableFrame* aScrollFrameAsScrollable, RepaintMode aRepaintMode) {
|
||||
nsIContent* content = aScrollFrame->GetContent();
|
||||
nsIScrollableFrame* scrollableFrame = do_QueryFrame(aScrollFrame);
|
||||
if (!content || !scrollableFrame) {
|
||||
if (!content) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -823,7 +814,7 @@ bool DisplayPortUtils::MaybeCreateDisplayPort(nsDisplayListBuilder* aBuilder,
|
|||
if (aBuilder->IsPaintingToWindow() &&
|
||||
nsLayoutUtils::AsyncPanZoomEnabled(aScrollFrame) &&
|
||||
!aBuilder->HaveScrollableDisplayPort() &&
|
||||
scrollableFrame->WantAsyncScroll()) {
|
||||
aScrollFrameAsScrollable->WantAsyncScroll()) {
|
||||
// If we don't already have a displayport, calculate and set one.
|
||||
if (!haveDisplayPort) {
|
||||
// We only use the viewId for logging purposes, but create it
|
||||
|
@ -835,7 +826,7 @@ bool DisplayPortUtils::MaybeCreateDisplayPort(nsDisplayListBuilder* aBuilder,
|
|||
sDisplayportLog, LogLevel::Debug,
|
||||
("Setting DP on first-encountered scrollId=%" PRIu64 "\n", viewId));
|
||||
|
||||
CalculateAndSetDisplayPortMargins(scrollableFrame, aRepaintMode);
|
||||
CalculateAndSetDisplayPortMargins(aScrollFrameAsScrollable, aRepaintMode);
|
||||
#ifdef DEBUG
|
||||
haveDisplayPort = HasNonMinimalDisplayPort(content);
|
||||
MOZ_ASSERT(haveDisplayPort,
|
||||
|
@ -884,10 +875,8 @@ bool DisplayPortUtils::MaybeCreateDisplayPortInFirstScrollFrameEncountered(
|
|||
aFrame->GetContent()->GetID() == nsGkAtoms::tabbrowser_arrowscrollbox) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIScrollableFrame* sf = do_QueryFrame(aFrame);
|
||||
if (sf) {
|
||||
if (MaybeCreateDisplayPort(aBuilder, aFrame, RepaintMode::Repaint)) {
|
||||
if (nsIScrollableFrame* sf = do_QueryFrame(aFrame)) {
|
||||
if (MaybeCreateDisplayPort(aBuilder, aFrame, sf, RepaintMode::Repaint)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -901,28 +890,21 @@ bool DisplayPortUtils::MaybeCreateDisplayPortInFirstScrollFrameEncountered(
|
|||
if (aFrame->IsSubDocumentFrame()) {
|
||||
PresShell* presShell = static_cast<nsSubDocumentFrame*>(aFrame)
|
||||
->GetSubdocumentPresShellForPainting(0);
|
||||
nsIFrame* root = presShell ? presShell->GetRootFrame() : nullptr;
|
||||
if (root) {
|
||||
if (nsIFrame* root = presShell ? presShell->GetRootFrame() : nullptr) {
|
||||
if (MaybeCreateDisplayPortInFirstScrollFrameEncountered(root, aBuilder)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aFrame->IsDeckFrame()) {
|
||||
// only descend the visible card of a decks
|
||||
nsIFrame* child = static_cast<nsDeckFrame*>(aFrame)->GetSelectedBox();
|
||||
if (child) {
|
||||
return MaybeCreateDisplayPortInFirstScrollFrameEncountered(child,
|
||||
aBuilder);
|
||||
}
|
||||
if (aFrame->StyleUIReset()->mMozSubtreeHiddenOnlyVisually) {
|
||||
// Only descend the visible card of deck / tabpanels
|
||||
return false;
|
||||
}
|
||||
|
||||
for (nsIFrame* child : aFrame->PrincipalChildList()) {
|
||||
if (MaybeCreateDisplayPortInFirstScrollFrameEncountered(child, aBuilder)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -278,9 +278,9 @@ class DisplayPortUtils {
|
|||
* Returns true if there is a displayport on an async scrollable scrollframe
|
||||
* after this call, either because one was just added or it already existed.
|
||||
*/
|
||||
static bool MaybeCreateDisplayPort(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aScrollFrame,
|
||||
RepaintMode aRepaintMode);
|
||||
static bool MaybeCreateDisplayPort(
|
||||
nsDisplayListBuilder* aBuilder, nsIFrame* aScrollFrame,
|
||||
nsIScrollableFrame* aScrollFrameAsScrollable, RepaintMode aRepaintMode);
|
||||
|
||||
/**
|
||||
* Sets a zero margin display port on all proper ancestors of aFrame that
|
||||
|
|
|
@ -3961,38 +3961,24 @@ void PresShell::ClearMouseCaptureOnView(nsView* aView) {
|
|||
}
|
||||
|
||||
void PresShell::ClearMouseCapture() {
|
||||
nsIContent* capturingContent = GetCapturingContent();
|
||||
if (!capturingContent) {
|
||||
AllowMouseCapture(false);
|
||||
return;
|
||||
}
|
||||
|
||||
ReleaseCapturingContent();
|
||||
AllowMouseCapture(false);
|
||||
}
|
||||
|
||||
void PresShell::ClearMouseCapture(nsIFrame* aFrame) {
|
||||
MOZ_ASSERT(
|
||||
aFrame && aFrame->GetParent() &&
|
||||
aFrame->GetParent()->Type() == LayoutFrameType::Deck,
|
||||
"This function should only be called with a child frame of <deck>");
|
||||
MOZ_ASSERT(aFrame);
|
||||
|
||||
nsIContent* capturingContent = GetCapturingContent();
|
||||
if (!capturingContent) {
|
||||
AllowMouseCapture(false);
|
||||
return;
|
||||
}
|
||||
|
||||
nsIFrame* capturingFrame = capturingContent->GetPrimaryFrame();
|
||||
if (!capturingFrame) {
|
||||
ReleaseCapturingContent();
|
||||
AllowMouseCapture(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nsLayoutUtils::IsAncestorFrameCrossDocInProcess(aFrame, capturingFrame)) {
|
||||
ReleaseCapturingContent();
|
||||
AllowMouseCapture(false);
|
||||
const bool shouldClear =
|
||||
!capturingFrame ||
|
||||
nsLayoutUtils::IsAncestorFrameCrossDocInProcess(aFrame, capturingFrame);
|
||||
if (shouldClear) {
|
||||
ClearMouseCapture();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -205,13 +205,22 @@ class PresShell final : public nsStubDocumentObserver,
|
|||
|
||||
static void ClearMouseCaptureOnView(nsView* aView);
|
||||
|
||||
// If a frame in the subtree rooted at aFrame is capturing the mouse then
|
||||
// clears that capture.
|
||||
static void ClearMouseCapture(nsIFrame* aFrame);
|
||||
|
||||
// Clear the capture content if it exists in this process.
|
||||
static void ClearMouseCapture();
|
||||
|
||||
// If a frame in the subtree rooted at aFrame is capturing the mouse then
|
||||
// clears that capture.
|
||||
//
|
||||
// NOTE(emilio): This is needed only so that mouse events captured by a remote
|
||||
// frame don't remain being captured by the frame while hidden, see
|
||||
// dom/events/test/browser_mouse_enterleave_switch_tab.js, which is the only
|
||||
// test that meaningfully exercises this code path.
|
||||
//
|
||||
// We could consider maybe removing this, since the capturing content gets
|
||||
// reset on mouse/pointerdown? Or maybe exposing an API so that the front-end
|
||||
// does this.
|
||||
static void ClearMouseCapture(nsIFrame* aFrame);
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
/**
|
||||
* Return the document accessible for this PresShell if there is one.
|
||||
|
|
|
@ -2624,7 +2624,7 @@ MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(ServoPostTraversalFlags)
|
|||
// flags for kids.
|
||||
static ServoPostTraversalFlags SendA11yNotifications(
|
||||
nsPresContext* aPresContext, Element* aElement,
|
||||
ComputedStyle* aOldComputedStyle, ComputedStyle* aNewComputedStyle,
|
||||
const ComputedStyle& aOldStyle, const ComputedStyle& aNewStyle,
|
||||
ServoPostTraversalFlags aFlags) {
|
||||
using Flags = ServoPostTraversalFlags;
|
||||
MOZ_ASSERT(!(aFlags & Flags::SkipA11yNotifications) ||
|
||||
|
@ -2638,13 +2638,24 @@ static ServoPostTraversalFlags SendA11yNotifications(
|
|||
// enabled. Just skip everything.
|
||||
return Flags::Empty;
|
||||
}
|
||||
|
||||
if (aNewStyle.StyleUIReset()->mMozSubtreeHiddenOnlyVisually !=
|
||||
aOldStyle.StyleUIReset()->mMozSubtreeHiddenOnlyVisually) {
|
||||
if (aElement->GetParent() &&
|
||||
aElement->GetParent()->IsXULElement(nsGkAtoms::tabpanels)) {
|
||||
accService->NotifyOfTabPanelVisibilityChange(
|
||||
aPresContext->PresShell(), aElement,
|
||||
aNewStyle.StyleUIReset()->mMozSubtreeHiddenOnlyVisually);
|
||||
}
|
||||
}
|
||||
|
||||
if (aFlags & Flags::SkipA11yNotifications) {
|
||||
// Propogate the skipping flag to descendants.
|
||||
// Propagate the skipping flag to descendants.
|
||||
return Flags::SkipA11yNotifications;
|
||||
}
|
||||
|
||||
bool needsNotify = false;
|
||||
bool isVisible = aNewComputedStyle->StyleVisibility()->IsVisible();
|
||||
bool isVisible = aNewStyle.StyleVisibility()->IsVisible();
|
||||
if (aFlags & Flags::SendA11yNotificationsIfShown) {
|
||||
if (!isVisible) {
|
||||
// Propagate the sending-if-shown flag to descendants.
|
||||
|
@ -2657,7 +2668,7 @@ static ServoPostTraversalFlags SendA11yNotifications(
|
|||
} else {
|
||||
// If we shouldn't skip in any case, we need to check whether our
|
||||
// own visibility has changed.
|
||||
bool wasVisible = aOldComputedStyle->StyleVisibility()->IsVisible();
|
||||
bool wasVisible = aOldStyle.StyleVisibility()->IsVisible();
|
||||
needsNotify = wasVisible != isVisible;
|
||||
}
|
||||
|
||||
|
@ -2887,9 +2898,9 @@ bool RestyleManager::ProcessPostTraversal(Element* aElement,
|
|||
AddLayerChangesForAnimation(styleFrame, primaryFrame, aElement, changeHint,
|
||||
aRestyleState.ChangeList());
|
||||
|
||||
childrenFlags |=
|
||||
SendA11yNotifications(mPresContext, aElement, oldOrDisplayContentsStyle,
|
||||
upToDateStyle, aFlags);
|
||||
childrenFlags |= SendA11yNotifications(mPresContext, aElement,
|
||||
*oldOrDisplayContentsStyle,
|
||||
*upToDateStyle, aFlags);
|
||||
}
|
||||
|
||||
const bool traverseElementChildren =
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
<html><body>
|
||||
<object style="display:-moz-deck;">
|
||||
<noscript>
|
||||
</noscript>
|
||||
</object>
|
||||
</body></html>
|
||||
|
||||
|
||||
|
||||
|
|
@ -58,16 +58,13 @@ window.location.reload();
|
|||
<s style=" display: -moz-box; position: absolute; direction: ltr;">
|
||||
<q style=" display: table; direction: ltr;">
|
||||
<bdo style=" display: block;">mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m
|
||||
<q style=" display: -moz-deck; position: absolute; direction: rtl;">mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m
|
||||
</q>
|
||||
</bdo>
|
||||
</q>
|
||||
</s>
|
||||
<map style=" display: inline-table; position: fixed; direction: ltr;">
|
||||
<q style=" display: table; direction: ltr;">
|
||||
<bdo style=" display: block;">
|
||||
<q style=" display: -moz-deck; position: absolute; direction: rtl;">mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m
|
||||
</q>mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m
|
||||
mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m
|
||||
<q style=" display: inline; direction: ltr;">mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m
|
||||
</q>
|
||||
</bdo>
|
||||
|
@ -366,7 +363,6 @@ window.location.reload();
|
|||
</q>
|
||||
</q>
|
||||
</q>
|
||||
<listing style=" display: -moz-deck; direction: ltr;">
|
||||
<p style=" display: block; position: fixed; direction: ltr;">
|
||||
<q style=" display: table-header-group; ">
|
||||
<q style=" display: table-cell; ">
|
||||
|
@ -405,7 +401,6 @@ window.location.reload();
|
|||
</q>
|
||||
</q>
|
||||
</p>
|
||||
</listing>
|
||||
<q style=" display: table-header-group; ">
|
||||
<q style=" display: table-cell; ">
|
||||
<q style=" display: table; direction: ltr;">
|
||||
|
@ -656,7 +651,7 @@ window.location.reload();
|
|||
</map>
|
||||
<ol style="display: inline-block;direction: ltr;">
|
||||
<p style="display: inherit;position: fixed;direction: ltr;">
|
||||
<body style="display: -moz-deck;position: absolute;direction: ltr;">mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m
|
||||
<body style="display: position: absolute;direction: ltr;">mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m
|
||||
</ol>mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m
|
||||
</html>mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m
|
||||
</map>mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body><div style="display: -moz-deck;"><div style="overflow: auto; border: 4294967296px solid blue;">M</div></div></body>
|
||||
</html>
|
|
@ -105,7 +105,6 @@ load 343540-1.html
|
|||
load 344057-1.xhtml
|
||||
load 344064-1.html
|
||||
load 344300-1.html
|
||||
load 344300-2.html
|
||||
load chrome://reftest/content/crashtests/layout/base/crashtests/344340-1.xhtml
|
||||
load 347898-1.html
|
||||
load 348126-1.html
|
||||
|
@ -316,7 +315,6 @@ load 543648-1.html
|
|||
load 560447-1.html
|
||||
load 564063-1.html
|
||||
load 569018-1.html
|
||||
load chrome://reftest/content/crashtests/layout/base/crashtests/570038-1.html
|
||||
load chrome://reftest/content/crashtests/layout/base/crashtests/572003.xhtml
|
||||
load 572582-1.xhtml
|
||||
load 576649-1.html
|
||||
|
|
|
@ -215,8 +215,6 @@ nsContainerFrame* NS_NewRootBoxFrame(PresShell* aPresShell,
|
|||
nsContainerFrame* NS_NewDocElementBoxFrame(PresShell* aPresShell,
|
||||
ComputedStyle* aStyle);
|
||||
|
||||
nsIFrame* NS_NewDeckFrame(PresShell* aPresShell, ComputedStyle* aStyle);
|
||||
|
||||
nsIFrame* NS_NewLeafBoxFrame(PresShell* aPresShell, ComputedStyle* aStyle);
|
||||
|
||||
nsIFrame* NS_NewRangeFrame(PresShell* aPresShell, ComputedStyle* aStyle);
|
||||
|
@ -4549,11 +4547,6 @@ nsCSSFrameConstructor::FindDisplayData(const nsStyleDisplay& aDisplay,
|
|||
FCDATA_DESIRED_PARENT_TYPE_TO_BITS(eTypeRuby));
|
||||
return &data;
|
||||
}
|
||||
case StyleDisplayInside::MozDeck: {
|
||||
static constexpr FrameConstructionData data =
|
||||
SIMPLE_XUL_FCDATA(NS_NewDeckFrame);
|
||||
return &data;
|
||||
}
|
||||
case StyleDisplayInside::MozPopup: {
|
||||
static constexpr FrameConstructionData data(
|
||||
NS_NewMenuPopupFrame, FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_IS_POPUP |
|
||||
|
|
|
@ -117,7 +117,6 @@
|
|||
#include "nsCSSPseudoElements.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsTHashMap.h"
|
||||
#include "nsDeckFrame.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsFlexContainerFrame.h"
|
||||
#include "nsFontInflationData.h"
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include "nsRepeatService.h"
|
||||
#include "nsFloatManager.h"
|
||||
#include "nsSprocketLayout.h"
|
||||
#include "nsStackLayout.h"
|
||||
#include "nsTextControlFrame.h"
|
||||
#include "txMozillaXSLTProcessor.h"
|
||||
#include "nsTreeSanitizer.h"
|
||||
|
@ -329,7 +328,6 @@ void nsLayoutStatics::Shutdown() {
|
|||
nsColorNames::ReleaseTable();
|
||||
nsCSSProps::ReleaseTable();
|
||||
nsRepeatService::Shutdown();
|
||||
nsStackLayout::Shutdown();
|
||||
|
||||
nsXULContentUtils::Finish();
|
||||
nsXULPrototypeCache::ReleaseGlobals();
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<body style="direction: rtl;">
|
||||
|
||||
<form style="display: -moz-deck; width: 1em;">
|
||||
<fieldset>
|
||||
<legend>Your name</legend>
|
||||
<input type="text" name="name" size="20"/>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Your E-mail address</legend>
|
||||
<input type="text" name="email" size="25"/>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -20,7 +20,6 @@ load 370703-1.html
|
|||
load 370940-1.html
|
||||
load 370967.html
|
||||
load 378369.html
|
||||
load 378413-1.xhtml
|
||||
load 380116-1.xhtml
|
||||
load 382610-1.html
|
||||
load 383887-1.html
|
||||
|
|
|
@ -22,7 +22,6 @@ FRAME_CLASSES = [
|
|||
Frame("nsComboboxDisplayFrame", "ComboboxDisplay", NOT_LEAF),
|
||||
Frame("nsContinuingTextFrame", "Text", LEAF),
|
||||
Frame("nsDateTimeControlFrame", "DateTimeControl", NOT_LEAF),
|
||||
Frame("nsDeckFrame", "Deck", NOT_LEAF),
|
||||
Frame("nsDocElementBoxFrame", "DocElementBox", NOT_LEAF),
|
||||
Frame("nsFieldSetFrame", "FieldSet", NOT_LEAF),
|
||||
Frame("nsFileControlFrame", "Block", LEAF),
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<table style="display: -moz-deck;"><tbody><tr><td>
|
||||
<span style="position: relative;"><marquee><marquee><span style="position: absolute;">X</span></marquee></marquee></span>
|
||||
</td></tr></tbody></table>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,17 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
|
||||
<div style="display:-moz-deck">
|
||||
<div>
|
||||
<span style="float: right; width: 0;">x</span>
|
||||
</div>
|
||||
<div style="position: relative;">
|
||||
<span style="float: right;">
|
||||
<span style="position: absolute;">y</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,16 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
|
||||
div { display: flex; }
|
||||
div:after { display: -moz-deck; content: counter(b); }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div></div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -87,7 +87,6 @@ load 370174-2.html
|
|||
load 370174-3.html
|
||||
load 370699-1.html
|
||||
load 370794-1.html
|
||||
load 370866-1.xhtml
|
||||
load 370884-1.xhtml
|
||||
load 371348-1.xhtml
|
||||
load 371561-1.html
|
||||
|
@ -104,7 +103,6 @@ load 379217-2.xhtml
|
|||
load 379917-1.xhtml
|
||||
load 380012-1.html
|
||||
load 381152-1.html
|
||||
load 381786-1.html
|
||||
load 382129-1.xhtml
|
||||
load 382131-1.html
|
||||
load 382199-1.html
|
||||
|
@ -536,7 +534,6 @@ asserts(8-46) load 850931.html # nested multicols, inner multicol has column-wid
|
|||
load 851396-1.html
|
||||
load 854263-1.html
|
||||
load 862185.html
|
||||
load 862947-1.html
|
||||
load 863935.html
|
||||
load 866547-1.html
|
||||
needs-focus pref(accessibility.browsewithcaret,true) load 868906.html
|
||||
|
|
|
@ -100,7 +100,6 @@
|
|||
#include "nsBlockFrame.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsChangeHint.h"
|
||||
#include "nsDeckFrame.h"
|
||||
#include "nsSubDocumentFrame.h"
|
||||
#include "RetainedDisplayListBuilder.h"
|
||||
|
||||
|
@ -375,17 +374,19 @@ bool nsIFrame::IsVisibleConsideringAncestors(uint32_t aFlags) const {
|
|||
const nsIFrame* frame = this;
|
||||
while (frame) {
|
||||
nsView* view = frame->GetView();
|
||||
if (view && view->GetVisibility() == nsViewVisibility_kHide) return false;
|
||||
|
||||
if (this != frame && frame->HidesContent()) return false;
|
||||
|
||||
nsIFrame* parent = frame->GetParent();
|
||||
nsDeckFrame* deck = do_QueryFrame(parent);
|
||||
if (deck) {
|
||||
if (deck->GetSelectedBox() != frame) return false;
|
||||
if (view && view->GetVisibility() == nsViewVisibility_kHide) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
if (frame->StyleUIReset()->mMozSubtreeHiddenOnlyVisually) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this != frame && frame->HidesContent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nsIFrame* parent = frame->GetParent()) {
|
||||
frame = parent;
|
||||
} else {
|
||||
parent = nsLayoutUtils::GetCrossDocParentFrameInProcess(frame);
|
||||
|
@ -1286,6 +1287,10 @@ void nsIFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
|
|||
scrollableFrame->PostPendingResnap();
|
||||
}
|
||||
}
|
||||
if (StyleUIReset()->mMozSubtreeHiddenOnlyVisually &&
|
||||
!aOldComputedStyle->StyleUIReset()->mMozSubtreeHiddenOnlyVisually) {
|
||||
PresShell::ClearMouseCapture(this);
|
||||
}
|
||||
} else { // !aOldComputedStyle
|
||||
handleStickyChange = disp->mPosition == StylePositionProperty::Sticky;
|
||||
}
|
||||
|
@ -3983,22 +3988,21 @@ static bool ShouldSkipFrame(nsDisplayListBuilder* aBuilder,
|
|||
if (aBuilder->IsBackgroundOnly()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aBuilder->IsForGenerateGlyphMask() &&
|
||||
(!aFrame->IsTextFrame() && aFrame->IsLeaf())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// The placeholder frame should have the same content as the OOF frame.
|
||||
if (aBuilder->GetSelectedFramesOnly() &&
|
||||
(aFrame->IsLeaf() && !aFrame->IsSelected())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static const nsFrameState skipFlags =
|
||||
(NS_FRAME_TOO_DEEP_IN_FRAME_TREE | NS_FRAME_IS_NONDISPLAY);
|
||||
|
||||
return aFrame->HasAnyStateBits(skipFlags);
|
||||
if (aFrame->HasAnyStateBits(skipFlags)) {
|
||||
return true;
|
||||
}
|
||||
return aFrame->StyleUIReset()->mMozSubtreeHiddenOnlyVisually;
|
||||
}
|
||||
|
||||
void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div style="display: -moz-deck;" id="s">x</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,8 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body onload="document.getElementById('s').firstChild.data = 'x';">
|
||||
<div style="display: -moz-deck;" id="s"> </div>
|
||||
</body>
|
||||
</html>
|
|
@ -926,7 +926,6 @@ fuzzy-if(winWidget,0-123,0-1900) fuzzy-if(swgl,0-1,0-39) == 409659-1d.html 40965
|
|||
== 410621-1.html 410621-1-ref.html
|
||||
== 411059-1.html 411059-1-ref.html
|
||||
fuzzy-if(winWidget,46-129,652-770) == 411334-1.xml 411334-1-ref.xml
|
||||
== 411367-3.html 411367-3-ref.html
|
||||
== 411585-1.html 411585-1-ref.html
|
||||
== 411585-2.html 411585-2-ref.html
|
||||
fails == 411585-3.html 411585-3-ref.html # bug 426909
|
||||
|
|
|
@ -113,7 +113,7 @@ fuzzy(0-4,0-2) == underline-select-1.html underline-select-1-ref.html
|
|||
== vertical-mode-decorations-1.html vertical-mode-decorations-1-ref.html
|
||||
fuzzy-if(Android,0-238,0-36) == vertical-mode-decorations-2.html vertical-mode-decorations-2-ref.html
|
||||
!= 1415214.html 1415214-notref.html
|
||||
HTTP(..) == skip-ink-multiline-position.html skip-ink-multiline-position-ref.html
|
||||
fails-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) HTTP(..) == skip-ink-multiline-position.html skip-ink-multiline-position-ref.html # not reliable on Win7 (bug 1770273)
|
||||
== skip-ink-vertical-align.html skip-ink-vertical-align-ref.html
|
||||
!= skip-ink-vertical-align-2.html skip-ink-vertical-align-2-notref.html
|
||||
fuzzy(0-94,0-4) == skip-ink-cjk-1.html skip-ink-cjk-1-ref.html
|
||||
|
|
|
@ -607,6 +607,7 @@ cbindgen-types = [
|
|||
{ gecko = "StyleFontStyle", servo = "crate::values::computed::font::FontStyle" },
|
||||
{ gecko = "StyleFontWeight", servo = "crate::values::computed::font::FontWeight" },
|
||||
{ gecko = "StyleFontStretch", servo = "crate::values::computed::font::FontStretch" },
|
||||
{ gecko = "StyleBoolInteger", servo = "crate::values::computed::BoolInteger" },
|
||||
]
|
||||
|
||||
mapped-generic-types = [
|
||||
|
|
|
@ -91,8 +91,6 @@ enum class StyleDisplay : uint16_t {
|
|||
StyleDisplayFrom(StyleDisplayOutside::Block, StyleDisplayInside::MozBox),
|
||||
MozInlineBox =
|
||||
StyleDisplayFrom(StyleDisplayOutside::Inline, StyleDisplayInside::MozBox),
|
||||
MozDeck =
|
||||
StyleDisplayFrom(StyleDisplayOutside::XUL, StyleDisplayInside::MozDeck),
|
||||
MozPopup =
|
||||
StyleDisplayFrom(StyleDisplayOutside::XUL, StyleDisplayInside::MozPopup),
|
||||
};
|
||||
|
|
|
@ -3213,7 +3213,8 @@ nsChangeHint nsStyleUI::CalcDifference(const nsStyleUI& aNewData) const {
|
|||
nsStyleUIReset::nsStyleUIReset(const Document& aDocument)
|
||||
: mUserSelect(StyleUserSelect::Auto),
|
||||
mScrollbarWidth(StyleScrollbarWidth::Auto),
|
||||
mMozForceBrokenImageIcon(0),
|
||||
mMozForceBrokenImageIcon(false),
|
||||
mMozSubtreeHiddenOnlyVisually(false),
|
||||
mIMEMode(StyleImeMode::Auto),
|
||||
mWindowDragging(StyleWindowDragging::Default),
|
||||
mWindowShadow(StyleWindowShadow::Default),
|
||||
|
@ -3250,6 +3251,7 @@ nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource)
|
|||
: mUserSelect(aSource.mUserSelect),
|
||||
mScrollbarWidth(aSource.mScrollbarWidth),
|
||||
mMozForceBrokenImageIcon(aSource.mMozForceBrokenImageIcon),
|
||||
mMozSubtreeHiddenOnlyVisually(aSource.mMozSubtreeHiddenOnlyVisually),
|
||||
mIMEMode(aSource.mIMEMode),
|
||||
mWindowDragging(aSource.mWindowDragging),
|
||||
mWindowShadow(aSource.mWindowShadow),
|
||||
|
@ -3287,6 +3289,9 @@ nsChangeHint nsStyleUIReset::CalcDifference(
|
|||
if (mMozForceBrokenImageIcon != aNewData.mMozForceBrokenImageIcon) {
|
||||
hint |= nsChangeHint_ReconstructFrame;
|
||||
}
|
||||
if (mMozSubtreeHiddenOnlyVisually != aNewData.mMozSubtreeHiddenOnlyVisually) {
|
||||
hint |= nsChangeHint_RepaintFrame;
|
||||
}
|
||||
if (mScrollbarWidth != aNewData.mScrollbarWidth) {
|
||||
// For scrollbar-width change, we need some special handling similar
|
||||
// to overflow properties. Specifically, we may need to reconstruct
|
||||
|
|
|
@ -1863,7 +1863,8 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUIReset {
|
|||
return mAnimations[aIndex % mAnimationTimelineCount].GetTimeline();
|
||||
}
|
||||
|
||||
uint8_t mMozForceBrokenImageIcon; // (0 if not forcing, otherwise forcing)
|
||||
mozilla::StyleBoolInteger mMozForceBrokenImageIcon;
|
||||
mozilla::StyleBoolInteger mMozSubtreeHiddenOnlyVisually;
|
||||
mozilla::StyleImeMode mIMEMode;
|
||||
mozilla::StyleWindowDragging mWindowDragging;
|
||||
mozilla::StyleWindowShadow mWindowShadow;
|
||||
|
|
|
@ -104,6 +104,7 @@ const char* gInaccessibleProperties[] = {
|
|||
"-moz-min-font-size-ratio", // parsed by UA sheets only
|
||||
"-moz-box-layout", // chrome-only internal properties
|
||||
"-moz-font-smoothing-background-color", // chrome-only internal properties
|
||||
"-moz-subtree-hidden-only-visually", // chrome-only internal properties
|
||||
"-moz-window-input-region-margin", // chrome-only internal properties
|
||||
"-moz-window-opacity", // chrome-only internal properties
|
||||
"-moz-window-transform", // chrome-only internal properties
|
||||
|
|
|
@ -134,8 +134,6 @@ skip-if = true # Bug 701060
|
|||
[test_bug418986-2.html]
|
||||
[test_bug437915.html]
|
||||
[test_bug450191.html]
|
||||
[test_bug453896_deck.html]
|
||||
support-files = bug453896_iframe.html
|
||||
[test_bug470769.html]
|
||||
[test_bug499655.html]
|
||||
[test_bug499655.xhtml]
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=453896
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 453896</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body onload="run()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=453896">Mozilla Bug 453896</a>
|
||||
<div id="display">
|
||||
|
||||
<div style="display:-moz-deck; height: 300px; width: 300px;">
|
||||
<iframe src="about:blank"></iframe>
|
||||
<iframe id="subdoc" src="bug453896_iframe.html"></iframe>
|
||||
<iframe src="about:blank"></iframe>
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
/** Test for Bug 453896 **/
|
||||
|
||||
function run()
|
||||
{
|
||||
var iframe = document.getElementById("subdoc");
|
||||
var subdoc = iframe.contentDocument;
|
||||
var subwin = iframe.contentWindow;
|
||||
|
||||
subwin.run(window);
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -19,7 +19,6 @@ const NON_CONTENT_ACCESSIBLE_VALUES = {
|
|||
"-moz-autofill-background",
|
||||
],
|
||||
"display": [
|
||||
"-moz-deck",
|
||||
"-moz-popup",
|
||||
"-moz-box",
|
||||
"-moz-inline-box",
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
<html>
|
||||
<head><title>Testcase bug 290743 - This display:-moz-deck testcase freezes Mozilla</title></head>
|
||||
<body style="display:-moz-deck;">
|
||||
<input type="radio"><input type="radio">
|
||||
</body>
|
||||
</html>
|
|
@ -1,12 +0,0 @@
|
|||
<html><head>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div style="display: -moz-deck"><div style="display: -moz-popup"></div></div>
|
||||
|
||||
<div style="position: relative">Y</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,5 +0,0 @@
|
|||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<tabpanels>
|
||||
<treechildren style="display: -moz-deck;"/>
|
||||
</tabpanels>
|
||||
</window>
|
|
@ -1,31 +0,0 @@
|
|||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<menulist id="b" style="display: -moz-box;">
|
||||
<panel id="c" style=" position: absolute;">
|
||||
<popup onunderflow="document.getElementById('c').removeAttribute('style')"/>
|
||||
</panel>
|
||||
<menupopup id="a" style="display: -moz-box;">
|
||||
<menulist/>
|
||||
</menupopup>
|
||||
<panel style="display: -moz-deck;" onoverflow="document.getElementById('b').removeAttribute('style')">
|
||||
<popup style="display: -moz-deck;"/>
|
||||
</panel>
|
||||
</menulist>
|
||||
|
||||
<script id="script" xmlns="http://www.w3.org/1999/xhtml"><![CDATA[
|
||||
function doe() {
|
||||
document.getElementById('c').removeAttribute('style');
|
||||
document.documentElement.clientHeight;
|
||||
document.getElementById('b').removeAttribute('style');
|
||||
document.getElementById('a').setAttribute('selected', 'true');
|
||||
document.getElementById('a').setAttribute('style', 'position: fixed;');
|
||||
document.documentElement.clientHeight;
|
||||
document.getElementById('a').removeAttribute('style');
|
||||
}
|
||||
|
||||
function doe2() {
|
||||
window.location.reload();
|
||||
}
|
||||
setTimeout(doe2, 200);
|
||||
setTimeout(doe,100);
|
||||
]]></script>
|
||||
</window>
|
|
@ -5,12 +5,10 @@ load chrome://reftest/content/crashtests/layout/xul/crashtests/151826-1.xhtml
|
|||
load chrome://reftest/content/crashtests/layout/xul/crashtests/168724-1.xhtml
|
||||
load chrome://reftest/content/crashtests/layout/xul/crashtests/189814-1.xhtml
|
||||
skip-if(Android) load chrome://reftest/content/crashtests/layout/xul/crashtests/289410-1.xhtml
|
||||
load 290743.html
|
||||
load chrome://reftest/content/crashtests/layout/xul/crashtests/291702-1.xhtml
|
||||
load chrome://reftest/content/crashtests/layout/xul/crashtests/291702-2.xhtml
|
||||
load chrome://reftest/content/crashtests/layout/xul/crashtests/291702-3.xhtml
|
||||
load chrome://reftest/content/crashtests/layout/xul/crashtests/294371-1.xhtml
|
||||
load 311457-1.html
|
||||
load chrome://reftest/content/crashtests/layout/xul/crashtests/322786-1.xhtml
|
||||
skip-if(Android) load chrome://reftest/content/crashtests/layout/xul/crashtests/325377.xhtml
|
||||
skip-if(Android) load chrome://reftest/content/crashtests/layout/xul/crashtests/326879-1.xhtml
|
||||
|
@ -24,7 +22,6 @@ load chrome://reftest/content/crashtests/layout/xul/crashtests/366112-1.xhtml
|
|||
skip-if(Android) load chrome://reftest/content/crashtests/layout/xul/crashtests/366203-1.xhtml
|
||||
load 367185-1.xhtml
|
||||
load 369942-1.xhtml
|
||||
skip-if(Android) load chrome://reftest/content/crashtests/layout/xul/crashtests/374102-1.xhtml
|
||||
load 376137-1.html
|
||||
load 376137-2.html
|
||||
load 377592-1.svg
|
||||
|
@ -39,7 +36,6 @@ load 384871-1.html
|
|||
load chrome://reftest/content/crashtests/layout/xul/crashtests/386642.xhtml
|
||||
load chrome://reftest/content/crashtests/layout/xul/crashtests/387080-1.xhtml
|
||||
load 391974-1.html
|
||||
skip-if(Android) load chrome://reftest/content/crashtests/layout/xul/crashtests/399013.xhtml
|
||||
load 402912-1.xhtml
|
||||
load 404192.xhtml
|
||||
load chrome://reftest/content/crashtests/layout/xul/crashtests/408904-1.xhtml
|
||||
|
|
|
@ -23,7 +23,6 @@ UNIFIED_SOURCES += [
|
|||
"nsBoxFrame.cpp",
|
||||
"nsBoxLayout.cpp",
|
||||
"nsBoxLayoutState.cpp",
|
||||
"nsDeckFrame.cpp",
|
||||
"nsDocElementBoxFrame.cpp",
|
||||
"nsImageBoxFrame.cpp",
|
||||
"nsLeafBoxFrame.cpp",
|
||||
|
@ -39,7 +38,6 @@ UNIFIED_SOURCES += [
|
|||
"nsSliderFrame.cpp",
|
||||
"nsSplitterFrame.cpp",
|
||||
"nsSprocketLayout.cpp",
|
||||
"nsStackLayout.cpp",
|
||||
"nsTextBoxFrame.cpp",
|
||||
"nsXULPopupManager.cpp",
|
||||
"nsXULTooltipListener.cpp",
|
||||
|
|
|
@ -308,8 +308,7 @@ nsresult nsIFrame::SyncXULLayout(nsBoxLayoutState& aBoxLayoutState) {
|
|||
nsresult nsIFrame::XULRedraw(nsBoxLayoutState& aState) {
|
||||
if (aState.PaintingDisabled()) return NS_OK;
|
||||
|
||||
// nsStackLayout, at least, expects us to repaint descendants even
|
||||
// if a damage rect is provided
|
||||
// Unclear whether we could get away with just InvalidateFrame().
|
||||
InvalidateFrameSubtree();
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -1,283 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
//
|
||||
// Eric Vaughan
|
||||
// Netscape Communications
|
||||
//
|
||||
// See documentation in associated header file
|
||||
//
|
||||
|
||||
#include "nsDeckFrame.h"
|
||||
#include "mozilla/ComputedStyle.h"
|
||||
#include "mozilla/PresShell.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsViewManager.h"
|
||||
#include "nsBoxLayoutState.h"
|
||||
#include "nsStackLayout.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsXULPopupManager.h"
|
||||
#include "nsImageBoxFrame.h"
|
||||
#include "nsImageFrame.h"
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
# include "nsAccessibilityService.h"
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
nsIFrame* NS_NewDeckFrame(PresShell* aPresShell, ComputedStyle* aStyle) {
|
||||
return new (aPresShell) nsDeckFrame(aStyle, aPresShell->GetPresContext());
|
||||
}
|
||||
|
||||
NS_IMPL_FRAMEARENA_HELPERS(nsDeckFrame)
|
||||
|
||||
NS_QUERYFRAME_HEAD(nsDeckFrame)
|
||||
NS_QUERYFRAME_ENTRY(nsDeckFrame)
|
||||
NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
|
||||
|
||||
nsDeckFrame::nsDeckFrame(ComputedStyle* aStyle, nsPresContext* aPresContext)
|
||||
: nsBoxFrame(aStyle, aPresContext, kClassID) {
|
||||
nsCOMPtr<nsBoxLayout> layout;
|
||||
NS_NewStackLayout(layout);
|
||||
SetXULLayoutManager(layout);
|
||||
}
|
||||
|
||||
nsresult nsDeckFrame::AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
|
||||
int32_t aModType) {
|
||||
nsresult rv =
|
||||
nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
|
||||
|
||||
// if the index changed hide the old element and make the new element visible
|
||||
if (aAttribute == nsGkAtoms::selectedIndex) {
|
||||
IndexChanged();
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void nsDeckFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
|
||||
nsIFrame* aPrevInFlow) {
|
||||
nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
|
||||
|
||||
mIndex = GetSelectedIndex();
|
||||
}
|
||||
|
||||
void nsDeckFrame::ShowBox(nsIFrame* aBox) { Animate(aBox, true); }
|
||||
|
||||
void nsDeckFrame::HideBox(nsIFrame* aBox) {
|
||||
PresShell::ClearMouseCapture(aBox);
|
||||
Animate(aBox, false);
|
||||
}
|
||||
|
||||
void nsDeckFrame::IndexChanged() {
|
||||
// did the index change?
|
||||
int32_t index = GetSelectedIndex();
|
||||
|
||||
if (index == mIndex) return;
|
||||
|
||||
// redraw
|
||||
InvalidateFrame();
|
||||
|
||||
// hide the currently showing box
|
||||
nsIFrame* currentBox = GetSelectedBox();
|
||||
if (currentBox) // only hide if it exists
|
||||
HideBox(currentBox);
|
||||
|
||||
mSelectedBoxCache = nullptr;
|
||||
|
||||
mIndex = index;
|
||||
|
||||
ShowBox(GetSelectedBox());
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
nsAccessibilityService* accService = GetAccService();
|
||||
if (accService) {
|
||||
accService->DeckPanelSwitched(PresContext()->GetPresShell(), mContent,
|
||||
currentBox, GetSelectedBox());
|
||||
}
|
||||
#endif
|
||||
|
||||
// Force any popups that might be anchored on elements within hidden
|
||||
// box to update.
|
||||
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
||||
if (pm && currentBox) {
|
||||
pm->UpdatePopupPositions(currentBox->PresContext()->RefreshDriver());
|
||||
}
|
||||
}
|
||||
|
||||
int32_t nsDeckFrame::GetSelectedIndex() {
|
||||
// default index is 0
|
||||
int32_t index = 0;
|
||||
|
||||
// get the index attribute
|
||||
nsAutoString value;
|
||||
if (mContent->AsElement()->GetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::selectedIndex, value)) {
|
||||
nsresult error;
|
||||
|
||||
// convert it to an integer
|
||||
index = value.ToInteger(&error);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
nsIFrame* nsDeckFrame::GetSelectedBox() {
|
||||
if (!mSelectedBoxCache && mIndex >= 0) {
|
||||
mSelectedBoxCache = (mIndex >= 0) ? mFrames.FrameAt(mIndex) : nullptr;
|
||||
}
|
||||
return mSelectedBoxCache;
|
||||
}
|
||||
|
||||
void nsDeckFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aLists) {
|
||||
// if a tab is hidden all its children are too.
|
||||
if (StyleVisibility()->mVisible == StyleVisibility::Hidden) {
|
||||
return;
|
||||
}
|
||||
nsBoxFrame::BuildDisplayList(aBuilder, aLists);
|
||||
}
|
||||
|
||||
void nsDeckFrame::RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) {
|
||||
nsIFrame* currentFrame = GetSelectedBox();
|
||||
if (aOldFrame == currentFrame) {
|
||||
mSelectedBoxCache = nullptr;
|
||||
}
|
||||
|
||||
if (currentFrame && aOldFrame && currentFrame != aOldFrame) {
|
||||
// If the frame we're removing is at an index that's less
|
||||
// than mIndex, that means we're going to be shifting indexes
|
||||
// by 1.
|
||||
//
|
||||
// We attempt to keep the same child displayed by automatically
|
||||
// updating our internal notion of the current index.
|
||||
int32_t removedIndex = mFrames.IndexOf(aOldFrame);
|
||||
MOZ_ASSERT(removedIndex >= 0,
|
||||
"A deck child was removed that was not in mFrames.");
|
||||
if (removedIndex < mIndex) {
|
||||
// This shouldn't invalidate our cache, but be really paranoid, it's not
|
||||
// that important to keep our cache here.
|
||||
mSelectedBoxCache = nullptr;
|
||||
|
||||
mIndex--;
|
||||
// This is going to cause us to handle the index change in IndexedChanged,
|
||||
// but since the new index will match mIndex, it's essentially a noop.
|
||||
nsContentUtils::AddScriptRunner(new nsSetAttrRunnable(
|
||||
mContent->AsElement(), nsGkAtoms::selectedIndex, mIndex));
|
||||
}
|
||||
}
|
||||
nsBoxFrame::RemoveFrame(aListID, aOldFrame);
|
||||
}
|
||||
|
||||
void nsDeckFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aLists) {
|
||||
// only paint the selected box
|
||||
nsIFrame* box = GetSelectedBox();
|
||||
if (!box) return;
|
||||
|
||||
// Putting the child in the background list. This is a little weird but
|
||||
// it matches what we were doing before.
|
||||
nsDisplayListSet set(aLists, aLists.BlockBorderBackgrounds());
|
||||
BuildDisplayListForChild(aBuilder, box, set);
|
||||
}
|
||||
|
||||
void nsDeckFrame::Animate(nsIFrame* aParentBox, bool start) {
|
||||
if (!aParentBox) return;
|
||||
|
||||
nsImageBoxFrame* imgBoxFrame = do_QueryFrame(aParentBox);
|
||||
nsImageFrame* imgFrame = do_QueryFrame(aParentBox);
|
||||
|
||||
if (imgBoxFrame) {
|
||||
if (start)
|
||||
imgBoxFrame->RestartAnimation();
|
||||
else
|
||||
imgBoxFrame->StopAnimation();
|
||||
}
|
||||
|
||||
if (imgFrame) {
|
||||
if (start)
|
||||
imgFrame->RestartAnimation();
|
||||
else
|
||||
imgFrame->StopAnimation();
|
||||
}
|
||||
|
||||
for (const auto& childList : aParentBox->ChildLists()) {
|
||||
for (nsIFrame* child : childList.mList) {
|
||||
Animate(child, start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDeckFrame::DoXULLayout(nsBoxLayoutState& aState) {
|
||||
// Make sure we tweak the state so it does not resize our children.
|
||||
// We will do that.
|
||||
ReflowChildFlags oldFlags = aState.LayoutFlags();
|
||||
aState.SetLayoutFlags(ReflowChildFlags::NoSizeView);
|
||||
|
||||
// do a normal layout
|
||||
nsresult rv = nsBoxFrame::DoXULLayout(aState);
|
||||
|
||||
// <deck> and <tabpanels> other than our browser's tab shouldn't have any
|
||||
// <browser> or <iframe> to avoid running into troubles with Fission.
|
||||
MOZ_ASSERT(
|
||||
(mContent->IsXULElement(nsGkAtoms::tabpanels) &&
|
||||
mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::id,
|
||||
#ifdef MOZ_THUNDERBIRD
|
||||
u"tabpanelcontainer"_ns,
|
||||
#else
|
||||
u"tabbrowser-tabpanels"_ns,
|
||||
#endif
|
||||
eCaseMatters)) ||
|
||||
!HasPossiblyRemoteContents());
|
||||
|
||||
// run though each child. Hide all but the selected one
|
||||
nsIFrame* box = nsIFrame::GetChildXULBox(this);
|
||||
|
||||
nscoord count = 0;
|
||||
while (box) {
|
||||
// make collapsed children not show up
|
||||
if (count != mIndex) {
|
||||
HideBox(box);
|
||||
} else {
|
||||
ShowBox(box);
|
||||
}
|
||||
box = GetNextXULBox(box);
|
||||
count++;
|
||||
}
|
||||
|
||||
aState.SetLayoutFlags(oldFlags);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool nsDeckFrame::HasPossiblyRemoteContents() const {
|
||||
auto hasRemoteOrMayChangeRemoteNessAttribute =
|
||||
[](dom::Element& aElement) -> bool {
|
||||
return (aElement.AttrValueIs(kNameSpaceID_None, nsGkAtoms::remote,
|
||||
nsGkAtoms::_true, eCaseMatters) ||
|
||||
aElement.HasAttribute(u"maychangeremoteness"_ns));
|
||||
};
|
||||
|
||||
for (nsIContent* node = mContent; node; node = node->GetNextNode(mContent)) {
|
||||
if ((node->IsXULElement(nsGkAtoms::browser) ||
|
||||
node->IsHTMLElement(nsGkAtoms::iframe)) &&
|
||||
hasRemoteOrMayChangeRemoteNessAttribute(*(node->AsElement()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
|
||||
Eric D Vaughan
|
||||
A frame that can have multiple children. Only one child may be displayed at
|
||||
one time. So the can be flipped though like a deck of cards.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef nsDeckFrame_h___
|
||||
#define nsDeckFrame_h___
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsBoxFrame.h"
|
||||
|
||||
namespace mozilla {
|
||||
class PresShell;
|
||||
} // namespace mozilla
|
||||
|
||||
class nsDeckFrame final : public nsBoxFrame {
|
||||
public:
|
||||
NS_DECL_QUERYFRAME
|
||||
NS_DECL_FRAMEARENA_HELPERS(nsDeckFrame)
|
||||
|
||||
friend nsIFrame* NS_NewDeckFrame(mozilla::PresShell* aPresShell,
|
||||
ComputedStyle* aStyle);
|
||||
|
||||
virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
|
||||
int32_t aModType) override;
|
||||
|
||||
NS_IMETHOD DoXULLayout(nsBoxLayoutState& aState) override;
|
||||
|
||||
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayListSet& aLists) override;
|
||||
|
||||
virtual void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override;
|
||||
|
||||
virtual void BuildDisplayListForChildren(
|
||||
nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) override;
|
||||
|
||||
virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
|
||||
nsIFrame* aPrevInFlow) override;
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
virtual nsresult GetFrameName(nsAString& aResult) const override {
|
||||
return MakeFrameName(u"Deck"_ns, aResult);
|
||||
}
|
||||
#endif
|
||||
|
||||
explicit nsDeckFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
|
||||
|
||||
nsIFrame* GetSelectedBox();
|
||||
|
||||
// Returns whether this frame has any <browser> or <iframe> elements.
|
||||
// Note that this function traverses down all descendants so this function
|
||||
// should be used only in debug builds.
|
||||
bool HasPossiblyRemoteContents() const;
|
||||
|
||||
protected:
|
||||
void IndexChanged();
|
||||
int32_t GetSelectedIndex();
|
||||
void HideBox(nsIFrame* aBox);
|
||||
void ShowBox(nsIFrame* aBox);
|
||||
|
||||
private:
|
||||
int32_t mIndex = 0;
|
||||
nsIFrame* mSelectedBoxCache = nullptr;
|
||||
|
||||
void Animate(nsIFrame*, bool);
|
||||
|
||||
}; // class nsDeckFrame
|
||||
|
||||
#endif
|
|
@ -15,7 +15,6 @@
|
|||
#include "nsStyleConsts.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsBoxFrame.h"
|
||||
#include "nsStackLayout.h"
|
||||
#include "nsIAnonymousContentCreator.h"
|
||||
#include "nsNodeInfoManager.h"
|
||||
#include "nsContentCreatorFunctions.h"
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "nsGkAtoms.h"
|
||||
#include "nsBoxFrame.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsStackLayout.h"
|
||||
#include "nsIPopupContainer.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsFrameManager.h"
|
||||
|
|
|
@ -1,209 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
//
|
||||
// Eric Vaughan
|
||||
// Netscape Communications
|
||||
//
|
||||
// See documentation in associated header file
|
||||
//
|
||||
|
||||
#include "nsStackLayout.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsBoxLayoutState.h"
|
||||
#include "nsBoxFrame.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
nsBoxLayout* nsStackLayout::gInstance = nullptr;
|
||||
|
||||
nsresult NS_NewStackLayout(nsCOMPtr<nsBoxLayout>& aNewLayout) {
|
||||
if (!nsStackLayout::gInstance) {
|
||||
nsStackLayout::gInstance = new nsStackLayout();
|
||||
NS_IF_ADDREF(nsStackLayout::gInstance);
|
||||
}
|
||||
// we have not instance variables so just return our static one.
|
||||
aNewLayout = nsStackLayout::gInstance;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void nsStackLayout::Shutdown() { NS_IF_RELEASE(gInstance); }
|
||||
|
||||
nsStackLayout::nsStackLayout() = default;
|
||||
|
||||
/*
|
||||
* Sizing: we are as wide as the widest child
|
||||
* we are tall as the tallest child.
|
||||
*/
|
||||
|
||||
nsSize nsStackLayout::GetXULPrefSize(nsIFrame* aBox, nsBoxLayoutState& aState) {
|
||||
nsSize prefSize(0, 0);
|
||||
|
||||
nsIFrame* child = nsIFrame::GetChildXULBox(aBox);
|
||||
while (child) {
|
||||
nsSize pref = child->GetXULPrefSize(aState);
|
||||
|
||||
AddXULMargin(child, pref);
|
||||
|
||||
if (pref.width > prefSize.width) {
|
||||
prefSize.width = pref.width;
|
||||
}
|
||||
if (pref.height > prefSize.height) {
|
||||
prefSize.height = pref.height;
|
||||
}
|
||||
|
||||
child = nsIFrame::GetNextXULBox(child);
|
||||
}
|
||||
|
||||
AddXULBorderAndPadding(aBox, prefSize);
|
||||
|
||||
return prefSize;
|
||||
}
|
||||
|
||||
nsSize nsStackLayout::GetXULMinSize(nsIFrame* aBox, nsBoxLayoutState& aState) {
|
||||
nsSize minSize(0, 0);
|
||||
|
||||
nsIFrame* child = nsIFrame::GetChildXULBox(aBox);
|
||||
while (child) {
|
||||
nsSize min = child->GetXULMinSize(aState);
|
||||
|
||||
AddXULMargin(child, min);
|
||||
|
||||
if (min.width > minSize.width) {
|
||||
minSize.width = min.width;
|
||||
}
|
||||
if (min.height > minSize.height) {
|
||||
minSize.height = min.height;
|
||||
}
|
||||
|
||||
child = nsIFrame::GetNextXULBox(child);
|
||||
}
|
||||
|
||||
AddXULBorderAndPadding(aBox, minSize);
|
||||
|
||||
return minSize;
|
||||
}
|
||||
|
||||
nsSize nsStackLayout::GetXULMaxSize(nsIFrame* aBox, nsBoxLayoutState& aState) {
|
||||
nsSize maxSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
|
||||
|
||||
nsIFrame* child = nsIFrame::GetChildXULBox(aBox);
|
||||
while (child) {
|
||||
nsSize min = child->GetXULMinSize(aState);
|
||||
nsSize max = child->GetXULMaxSize(aState);
|
||||
|
||||
max = nsIFrame::XULBoundsCheckMinMax(min, max);
|
||||
|
||||
AddXULMargin(child, max);
|
||||
|
||||
if (max.width < maxSize.width) {
|
||||
maxSize.width = max.width;
|
||||
}
|
||||
if (max.height < maxSize.height) {
|
||||
maxSize.height = max.height;
|
||||
}
|
||||
|
||||
child = nsIFrame::GetNextXULBox(child);
|
||||
}
|
||||
|
||||
AddXULBorderAndPadding(aBox, maxSize);
|
||||
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
nscoord nsStackLayout::GetAscent(nsIFrame* aBox, nsBoxLayoutState& aState) {
|
||||
nscoord vAscent = 0;
|
||||
|
||||
nsIFrame* child = nsIFrame::GetChildXULBox(aBox);
|
||||
while (child) {
|
||||
nscoord ascent = child->GetXULBoxAscent(aState);
|
||||
nsMargin margin;
|
||||
child->GetXULMargin(margin);
|
||||
ascent += margin.top;
|
||||
if (ascent > vAscent) vAscent = ascent;
|
||||
|
||||
child = nsIFrame::GetNextXULBox(child);
|
||||
}
|
||||
|
||||
return vAscent;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsStackLayout::XULLayout(nsIFrame* aBox, nsBoxLayoutState& aState) {
|
||||
nsRect clientRect;
|
||||
aBox->GetXULClientRect(clientRect);
|
||||
|
||||
bool grow;
|
||||
|
||||
do {
|
||||
nsIFrame* child = nsIFrame::GetChildXULBox(aBox);
|
||||
grow = false;
|
||||
|
||||
while (child) {
|
||||
nsMargin margin;
|
||||
child->GetXULMargin(margin);
|
||||
nsRect childRect(clientRect);
|
||||
childRect.Deflate(margin);
|
||||
|
||||
if (childRect.width < 0) childRect.width = 0;
|
||||
|
||||
if (childRect.height < 0) childRect.height = 0;
|
||||
|
||||
nsRect oldRect(child->GetRect());
|
||||
bool sizeChanged = !oldRect.IsEqualEdges(childRect);
|
||||
|
||||
// only lay out dirty children or children whose sizes have changed
|
||||
if (sizeChanged || child->IsSubtreeDirty()) {
|
||||
// add in the child's margin
|
||||
nsMargin margin;
|
||||
child->GetXULMargin(margin);
|
||||
|
||||
// Now place the child.
|
||||
child->SetXULBounds(aState, childRect);
|
||||
|
||||
// Flow the child.
|
||||
child->XULLayout(aState);
|
||||
|
||||
// Get the child's new rect.
|
||||
childRect = child->GetRect();
|
||||
childRect.Inflate(margin);
|
||||
|
||||
// Did the child push back on us and get bigger?
|
||||
if (childRect.width > clientRect.width) {
|
||||
clientRect.width = childRect.width;
|
||||
grow = true;
|
||||
}
|
||||
|
||||
if (childRect.height > clientRect.height) {
|
||||
clientRect.height = childRect.height;
|
||||
grow = true;
|
||||
}
|
||||
}
|
||||
|
||||
child = nsIFrame::GetNextXULBox(child);
|
||||
}
|
||||
} while (grow);
|
||||
|
||||
// if some HTML inside us got bigger we need to force ourselves to
|
||||
// get bigger
|
||||
nsRect bounds(aBox->GetRect());
|
||||
nsMargin bp;
|
||||
aBox->GetXULBorderAndPadding(bp);
|
||||
clientRect.Inflate(bp);
|
||||
|
||||
if (clientRect.width > bounds.width || clientRect.height > bounds.height) {
|
||||
if (clientRect.width > bounds.width) bounds.width = clientRect.width;
|
||||
if (clientRect.height > bounds.height) bounds.height = clientRect.height;
|
||||
|
||||
aBox->SetXULBounds(aState, bounds);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
|
||||
Eric D Vaughan
|
||||
A frame that can have multiple children. Only one child may be displayed at
|
||||
one time. So the can be flipped though like a deck of cards.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef nsStackLayout_h___
|
||||
#define nsStackLayout_h___
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsBoxLayout.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCoord.h"
|
||||
|
||||
nsresult NS_NewStackLayout(nsCOMPtr<nsBoxLayout>& aNewLayout);
|
||||
|
||||
class nsStackLayout : public nsBoxLayout {
|
||||
public:
|
||||
friend nsresult NS_NewStackLayout(nsCOMPtr<nsBoxLayout>& aNewLayout);
|
||||
static void Shutdown();
|
||||
|
||||
nsStackLayout();
|
||||
|
||||
NS_IMETHOD XULLayout(nsIFrame* aBox, nsBoxLayoutState& aState) override;
|
||||
|
||||
virtual nsSize GetXULPrefSize(nsIFrame* aBox,
|
||||
nsBoxLayoutState& aBoxLayoutState) override;
|
||||
virtual nsSize GetXULMinSize(nsIFrame* aBox,
|
||||
nsBoxLayoutState& aBoxLayoutState) override;
|
||||
virtual nsSize GetXULMaxSize(nsIFrame* aBox,
|
||||
nsBoxLayoutState& aBoxLayoutState) override;
|
||||
virtual nscoord GetAscent(nsIFrame* aBox,
|
||||
nsBoxLayoutState& aBoxLayoutState) override;
|
||||
|
||||
private:
|
||||
static nsBoxLayout* gInstance;
|
||||
|
||||
}; // class nsStackLayout
|
||||
|
||||
#endif
|
|
@ -487,7 +487,7 @@ class Longhand(Property):
|
|||
"LineBreak",
|
||||
"LineClamp",
|
||||
"MasonryAutoFlow",
|
||||
"MozForceBrokenImageIcon",
|
||||
"BoolInteger",
|
||||
"text::MozControlCharacterVisibility",
|
||||
"MathDepth",
|
||||
"MozScriptMinSize",
|
||||
|
|
|
@ -108,11 +108,23 @@ ${helpers.predefined_type(
|
|||
enabled_in="chrome",
|
||||
)}
|
||||
|
||||
// Hack to allow chrome to hide stuff only visually (without hiding it from
|
||||
// a11y).
|
||||
${helpers.predefined_type(
|
||||
"-moz-subtree-hidden-only-visually",
|
||||
"BoolInteger",
|
||||
"computed::BoolInteger::zero()",
|
||||
engines="gecko",
|
||||
animation_value_type="discrete",
|
||||
spec="None (Nonstandard internal property)",
|
||||
enabled_in="chrome",
|
||||
)}
|
||||
|
||||
// TODO(emilio): Probably also should be hidden from content.
|
||||
${helpers.predefined_type(
|
||||
"-moz-force-broken-image-icon",
|
||||
"MozForceBrokenImageIcon",
|
||||
"computed::MozForceBrokenImageIcon::false_value()",
|
||||
"BoolInteger",
|
||||
"computed::BoolInteger::zero()",
|
||||
engines="gecko",
|
||||
animation_value_type="discrete",
|
||||
spec="None (Nonstandard Firefox-only property)",
|
||||
|
|
|
@ -97,7 +97,7 @@ pub use self::transform::{Rotate, Scale, Transform, TransformOperation};
|
|||
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
|
||||
#[cfg(feature = "gecko")]
|
||||
pub use self::ui::CursorImage;
|
||||
pub use self::ui::{Cursor, MozForceBrokenImageIcon, UserSelect};
|
||||
pub use self::ui::{Cursor, BoolInteger, UserSelect};
|
||||
pub use super::specified::TextTransform;
|
||||
pub use super::specified::ViewportVariant;
|
||||
pub use super::specified::{BorderStyle, TextDecorationLine};
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::values::computed::Number;
|
|||
use crate::values::generics::ui as generics;
|
||||
|
||||
pub use crate::values::specified::ui::CursorKind;
|
||||
pub use crate::values::specified::ui::{MozForceBrokenImageIcon, UserSelect};
|
||||
pub use crate::values::specified::ui::{BoolInteger, UserSelect};
|
||||
|
||||
/// A computed value for the `cursor` property.
|
||||
pub type Cursor = generics::GenericCursor<CursorImage>;
|
||||
|
|
|
@ -101,8 +101,6 @@ pub enum DisplayInside {
|
|||
#[cfg(feature = "gecko")]
|
||||
MozBox,
|
||||
#[cfg(feature = "gecko")]
|
||||
MozDeck,
|
||||
#[cfg(feature = "gecko")]
|
||||
MozPopup,
|
||||
}
|
||||
|
||||
|
@ -216,8 +214,6 @@ impl Display {
|
|||
#[cfg(feature = "gecko")]
|
||||
pub const MozInlineBox: Self = Self::new(DisplayOutside::Inline, DisplayInside::MozBox);
|
||||
#[cfg(feature = "gecko")]
|
||||
pub const MozDeck: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozDeck);
|
||||
#[cfg(feature = "gecko")]
|
||||
pub const MozPopup: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozPopup);
|
||||
|
||||
/// Make a raw display value from <display-outside> and <display-inside> values.
|
||||
|
@ -598,8 +594,6 @@ impl Parse for Display {
|
|||
#[cfg(feature = "gecko")]
|
||||
"-moz-inline-box" if moz_display_values_enabled(context) => Display::MozInlineBox,
|
||||
#[cfg(feature = "gecko")]
|
||||
"-moz-deck" if moz_display_values_enabled(context) => Display::MozDeck,
|
||||
#[cfg(feature = "gecko")]
|
||||
"-moz-popup" if moz_display_values_enabled(context) => Display::MozPopup,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ pub use self::transform::{Rotate, Scale, Transform};
|
|||
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
|
||||
#[cfg(feature = "gecko")]
|
||||
pub use self::ui::CursorImage;
|
||||
pub use self::ui::{Cursor, MozForceBrokenImageIcon, UserSelect};
|
||||
pub use self::ui::{Cursor, BoolInteger, UserSelect};
|
||||
pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent;
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
|
|
|
@ -88,31 +88,32 @@ impl SpecifiedValueInfo for CursorImage {
|
|||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
pub struct MozForceBrokenImageIcon(pub bool);
|
||||
#[repr(transparent)]
|
||||
pub struct BoolInteger(pub bool);
|
||||
|
||||
impl MozForceBrokenImageIcon {
|
||||
/// Return initial value of -moz-force-broken-image-icon which is false.
|
||||
impl BoolInteger {
|
||||
/// Returns 0
|
||||
#[inline]
|
||||
pub fn false_value() -> MozForceBrokenImageIcon {
|
||||
MozForceBrokenImageIcon(false)
|
||||
pub fn zero() -> Self {
|
||||
Self(false)
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for MozForceBrokenImageIcon {
|
||||
impl Parse for BoolInteger {
|
||||
fn parse<'i, 't>(
|
||||
_context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<MozForceBrokenImageIcon, ParseError<'i>> {
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
// We intentionally don't support calc values here.
|
||||
match input.expect_integer()? {
|
||||
0 => Ok(MozForceBrokenImageIcon(false)),
|
||||
1 => Ok(MozForceBrokenImageIcon(true)),
|
||||
0 => Ok(Self(false)),
|
||||
1 => Ok(Self(true)),
|
||||
_ => Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for MozForceBrokenImageIcon {
|
||||
impl ToCss for BoolInteger {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: Write,
|
||||
|
@ -121,22 +122,6 @@ impl ToCss for MozForceBrokenImageIcon {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<u8> for MozForceBrokenImageIcon {
|
||||
fn from(bits: u8) -> MozForceBrokenImageIcon {
|
||||
MozForceBrokenImageIcon(bits == 1)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MozForceBrokenImageIcon> for u8 {
|
||||
fn from(v: MozForceBrokenImageIcon) -> u8 {
|
||||
if v.0 {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A specified value for `scrollbar-color` property
|
||||
pub type ScrollbarColor = generics::ScrollbarColor<Color>;
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@ include = [
|
|||
"BreakBetween",
|
||||
"BreakWithin",
|
||||
"BorderStyle",
|
||||
"BoolInteger",
|
||||
"OutlineStyle",
|
||||
"CaptionSide",
|
||||
"FontSizeAdjust",
|
||||
|
|
|
@ -113,7 +113,7 @@
|
|||
ok(deck instanceof MozXULElement, "instance of MozXULElement");
|
||||
ok(XULElement.isInstance(deck), "instance of XULElement");
|
||||
is(deck.id, "foo", "attribute set");
|
||||
is(deck.selectedIndex, "0", "Custom Element is property attached");
|
||||
is(deck.selectedIndex, 0, "Custom Element is property attached");
|
||||
deck.remove();
|
||||
|
||||
info("Checking that whitespace text is removed but non-whitespace text isn't");
|
||||
|
|
|
@ -5,14 +5,13 @@
|
|||
XUL Widget Test for deck
|
||||
-->
|
||||
<window title="Deck Test"
|
||||
onload="setTimeout(run_tests, 0);"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<deck id="deck1" style="padding-top: 5px; padding-bottom: 12px;">
|
||||
<button id="d1b1" label="Button One"/>
|
||||
<button id="d1b2" label="Button Two is larger" height="80" style="margin: 1px;"/>
|
||||
<button id="d1b2" label="Button Two is larger" style="height: 80px; margin: 1px;"/>
|
||||
</deck>
|
||||
<deck id="deck2" selectedIndex="1">
|
||||
<button id="d2b1" label="Button One"/>
|
||||
|
@ -44,19 +43,15 @@
|
|||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript"><![CDATA[
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function run_tests() {
|
||||
add_task(async function run_tests() {
|
||||
test_deck();
|
||||
test_deck_child_removal();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
await test_deck_child_removal();
|
||||
});
|
||||
|
||||
function test_deck()
|
||||
{
|
||||
var deck = $("deck1");
|
||||
ok(deck.selectedIndex === '0', "deck one selectedIndex");
|
||||
is(deck.selectedIndex, 0, "deck one selectedIndex");
|
||||
// this size is the button height, 80, plus the button padding of 1px on each side,
|
||||
// plus the deck's 5px top padding and the 12px bottom padding.
|
||||
var rect = deck.getBoundingClientRect();
|
||||
|
@ -66,47 +61,52 @@ function test_deck()
|
|||
// change the selected page of the deck and ensure that the mouse click goes
|
||||
// to the button on that page
|
||||
deck.selectedIndex = 1;
|
||||
ok(deck.selectedIndex === '1', "deck one selectedIndex after change");
|
||||
is(deck.selectedIndex, 1, "deck one selectedIndex after change");
|
||||
synthesizeMouseExpectEvent(deck, 9, 9, { }, $("d1b2"), "click", "mouse on deck one after change");
|
||||
|
||||
deck = $("deck2");
|
||||
ok(deck.selectedIndex === '1', "deck two selectedIndex");
|
||||
is(deck.selectedIndex, 1, "deck two selectedIndex");
|
||||
synthesizeMouseExpectEvent(deck, 9, 9, { }, $("d2b2"), "click", "mouse on deck two");
|
||||
}
|
||||
|
||||
function test_deck_child_removal()
|
||||
async function test_deck_child_removal()
|
||||
{
|
||||
// Start with a simple case where we have two child nodes in a deck, with
|
||||
// the second child (index 1) selected. Removing the first node should
|
||||
// automatically set the selectedIndex at 0.
|
||||
let deck = $("deck3");
|
||||
let child = $("d3b1");
|
||||
is(deck.selectedIndex, "1", "Should have the deck element at index 1 selected");
|
||||
is(deck.selectedIndex, 1, "Should have the deck element at index 1 selected");
|
||||
|
||||
// Remove the child at the 0th index. The deck should automatically
|
||||
// set the selectedIndex to "0".
|
||||
child.remove();
|
||||
is(deck.selectedIndex, "0", "Should have the deck element at index 0 selected");
|
||||
|
||||
await Promise.resolve();
|
||||
|
||||
is(deck.selectedIndex, 0, "Should have the deck element at index 0 selected");
|
||||
|
||||
// Now scale it up by using a deck with 7 child nodes, and remove the
|
||||
// first three, making sure that the selectedIndex is decremented
|
||||
// each time.
|
||||
deck = $("deck4");
|
||||
let expectedIndex = 5;
|
||||
is(deck.selectedIndex, String(expectedIndex),
|
||||
is(deck.selectedIndex, expectedIndex,
|
||||
"Should have the deck element at index " + expectedIndex + " selected");
|
||||
|
||||
for (let i = 0; i < 3; ++i) {
|
||||
deck.firstChild.remove();
|
||||
expectedIndex--;
|
||||
is(deck.selectedIndex, String(expectedIndex),
|
||||
await Promise.resolve();
|
||||
is(deck.selectedIndex, expectedIndex,
|
||||
"Should have the deck element at index " + expectedIndex + " selected");
|
||||
}
|
||||
|
||||
// Check that removing the currently selected node doesn't change
|
||||
// behaviour.
|
||||
deck.childNodes[expectedIndex].remove();
|
||||
is(deck.selectedIndex, String(expectedIndex),
|
||||
await Promise.resolve();
|
||||
is(deck.selectedIndex, expectedIndex,
|
||||
"The selectedIndex should not change when removing the node " +
|
||||
"at the selected index.");
|
||||
|
||||
|
@ -114,14 +114,16 @@ function test_deck_child_removal()
|
|||
// nodes at indexes greater than the selected node.
|
||||
deck = $("deck5");
|
||||
expectedIndex = 2;
|
||||
is(deck.selectedIndex, String(expectedIndex),
|
||||
await Promise.resolve();
|
||||
is(deck.selectedIndex, expectedIndex,
|
||||
"Should have the deck element at index " + expectedIndex + " selected");
|
||||
|
||||
// And then remove all of the nodes, starting from last to first, making
|
||||
// sure that the selectedIndex does not change.
|
||||
while (deck.lastChild) {
|
||||
deck.lastChild.remove();
|
||||
is(deck.selectedIndex, String(expectedIndex),
|
||||
await Promise.resolve();
|
||||
is(deck.selectedIndex, expectedIndex,
|
||||
"Should have the deck element at index " + expectedIndex + " selected");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,40 +7,6 @@
|
|||
// This is loaded into chrome windows with the subscript loader. Wrap in
|
||||
// a block to prevent accidentally leaking globals onto `window`.
|
||||
{
|
||||
class MozDeck extends MozXULElement {
|
||||
set selectedIndex(val) {
|
||||
if (this.selectedIndex == val) {
|
||||
return;
|
||||
}
|
||||
this.setAttribute("selectedIndex", val);
|
||||
var event = document.createEvent("Events");
|
||||
event.initEvent("select", true, true);
|
||||
this.dispatchEvent(event);
|
||||
}
|
||||
|
||||
get selectedIndex() {
|
||||
return this.getAttribute("selectedIndex") || "0";
|
||||
}
|
||||
|
||||
set selectedPanel(val) {
|
||||
var selectedIndex = -1;
|
||||
for (
|
||||
var panel = val;
|
||||
panel != null;
|
||||
panel = panel.previousElementSibling
|
||||
) {
|
||||
++selectedIndex;
|
||||
}
|
||||
this.selectedIndex = selectedIndex;
|
||||
}
|
||||
|
||||
get selectedPanel() {
|
||||
return this.children[this.selectedIndex];
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("deck", MozDeck);
|
||||
|
||||
class MozDropmarker extends MozXULElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
|
|
@ -158,14 +158,107 @@
|
|||
|
||||
customElements.define("tabbox", MozTabbox);
|
||||
|
||||
class MozTabpanels extends MozXULElement {
|
||||
class MozDeck extends MozXULElement {
|
||||
get isAsync() {
|
||||
return this.getAttribute("async") == "true";
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
if (this.delayConnectedCallback()) {
|
||||
return;
|
||||
}
|
||||
this._selectedPanel = null;
|
||||
this._inAsyncOperation = false;
|
||||
|
||||
let selectCurrentIndex = () => {
|
||||
// Try to select the new node if any.
|
||||
let index = this.selectedIndex;
|
||||
let oldPanel = this._selectedPanel;
|
||||
this._selectedPanel = this.children.item(index) || null;
|
||||
this.updateSelectedIndex(index, oldPanel);
|
||||
};
|
||||
|
||||
this._mutationObserver = new MutationObserver(records => {
|
||||
let anyRemovals = records.some(record => !!record.removedNodes.length);
|
||||
if (anyRemovals) {
|
||||
// Try to keep the current selected panel in-place first.
|
||||
let index = Array.from(this.children).indexOf(this._selectedPanel);
|
||||
if (index != -1) {
|
||||
// Try to keep the same node selected.
|
||||
this.setAttribute("selectedIndex", index);
|
||||
}
|
||||
}
|
||||
// Select the current index if needed in case mutations have made that
|
||||
// available where it wasn't before.
|
||||
if (!this._inAsyncOperation) {
|
||||
selectCurrentIndex();
|
||||
}
|
||||
});
|
||||
|
||||
this._mutationObserver.observe(this, {
|
||||
childList: true,
|
||||
});
|
||||
|
||||
selectCurrentIndex();
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this._mutationObserver?.disconnect();
|
||||
this._mutationObserver = null;
|
||||
}
|
||||
|
||||
updateSelectedIndex(
|
||||
val,
|
||||
oldPanel = this.querySelector(":scope > .deck-selected")
|
||||
) {
|
||||
this._inAsyncOperation = false;
|
||||
if (oldPanel != this._selectedPanel) {
|
||||
oldPanel?.classList.remove("deck-selected");
|
||||
this._selectedPanel?.classList.add("deck-selected");
|
||||
}
|
||||
this.setAttribute("selectedIndex", val);
|
||||
}
|
||||
|
||||
set selectedIndex(val) {
|
||||
if (val < 0 || val >= this.children.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
let oldPanel = this._selectedPanel;
|
||||
this._selectedPanel = this.children[val];
|
||||
|
||||
this._inAsyncOperation = this.isAsync;
|
||||
if (!this._inAsyncOperation) {
|
||||
this.updateSelectedIndex(val, oldPanel);
|
||||
}
|
||||
|
||||
if (this._selectedPanel != oldPanel) {
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("select", true, true);
|
||||
this.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
get selectedIndex() {
|
||||
let indexStr = this.getAttribute("selectedIndex");
|
||||
return indexStr ? parseInt(indexStr) : 0;
|
||||
}
|
||||
|
||||
set selectedPanel(val) {
|
||||
this.selectedIndex = Array.from(this.children).indexOf(val);
|
||||
}
|
||||
|
||||
get selectedPanel() {
|
||||
return this._selectedPanel;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("deck", MozDeck);
|
||||
|
||||
class MozTabpanels extends MozDeck {
|
||||
constructor() {
|
||||
super();
|
||||
this._tabbox = null;
|
||||
this._selectedPanel = this.children.item(this.selectedIndex);
|
||||
}
|
||||
|
||||
get tabbox() {
|
||||
|
@ -186,46 +279,6 @@
|
|||
return (this._tabbox = parent);
|
||||
}
|
||||
|
||||
set selectedIndex(val) {
|
||||
if (val < 0 || val >= this.children.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
let panel = this._selectedPanel;
|
||||
this._selectedPanel = this.children[val];
|
||||
|
||||
if (this.getAttribute("async") != "true") {
|
||||
this.setAttribute("selectedIndex", val);
|
||||
}
|
||||
|
||||
if (this._selectedPanel != panel) {
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("select", true, true);
|
||||
this.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
get selectedIndex() {
|
||||
let indexStr = this.getAttribute("selectedIndex");
|
||||
return indexStr ? parseInt(indexStr) : -1;
|
||||
}
|
||||
|
||||
set selectedPanel(val) {
|
||||
let selectedIndex = -1;
|
||||
for (
|
||||
let panel = val;
|
||||
panel != null;
|
||||
panel = panel.previousElementSibling
|
||||
) {
|
||||
++selectedIndex;
|
||||
}
|
||||
this.selectedIndex = selectedIndex;
|
||||
}
|
||||
|
||||
get selectedPanel() {
|
||||
return this._selectedPanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* nsIDOMXULRelatedElement
|
||||
*/
|
||||
|
@ -527,24 +580,25 @@
|
|||
|
||||
set selectedIndex(val) {
|
||||
var tab = this.getItemAtIndex(val);
|
||||
if (tab) {
|
||||
for (let otherTab of this.allTabs) {
|
||||
if (otherTab != tab && otherTab.selected) {
|
||||
otherTab._selected = false;
|
||||
}
|
||||
if (!tab) {
|
||||
return;
|
||||
}
|
||||
for (let otherTab of this.allTabs) {
|
||||
if (otherTab != tab && otherTab.selected) {
|
||||
otherTab._selected = false;
|
||||
}
|
||||
tab._selected = true;
|
||||
}
|
||||
tab._selected = true;
|
||||
|
||||
this.setAttribute("value", tab.value);
|
||||
this.setAttribute("value", tab.value);
|
||||
|
||||
let linkedPanel = this.getRelatedElement(tab);
|
||||
if (linkedPanel) {
|
||||
this.tabbox.setAttribute("selectedIndex", val);
|
||||
let linkedPanel = this.getRelatedElement(tab);
|
||||
if (linkedPanel) {
|
||||
this.tabbox.setAttribute("selectedIndex", val);
|
||||
|
||||
// This will cause an onselect event to fire for the tabpanel
|
||||
// element.
|
||||
this.tabbox.tabpanels.selectedPanel = linkedPanel;
|
||||
}
|
||||
// This will cause an onselect event to fire for the tabpanel
|
||||
// element.
|
||||
this.tabbox.tabpanels.selectedPanel = linkedPanel;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -448,18 +448,34 @@ treechildren::-moz-tree-cell(ltr) {
|
|||
direction: ltr !important;
|
||||
}
|
||||
|
||||
/********** deck & stack *********/
|
||||
/********** deck, tabpanels & stack *********/
|
||||
|
||||
deck {
|
||||
display: -moz-deck;
|
||||
tabpanels > *|*:not(:-moz-native-anonymous) {
|
||||
/* tabpanels is special: we want to avoid displaying them, but we still want
|
||||
* the hidden children to be accessible */
|
||||
-moz-subtree-hidden-only-visually: 1;
|
||||
}
|
||||
|
||||
deck > *|*:not(:-moz-native-anonymous) {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
tabpanels > .deck-selected,
|
||||
deck > .deck-selected {
|
||||
-moz-subtree-hidden-only-visually: 0;
|
||||
visibility: inherit;
|
||||
}
|
||||
|
||||
tabpanels,
|
||||
deck,
|
||||
stack {
|
||||
display: grid;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* We shouldn't style native anonymous children like scrollbars or what not */
|
||||
/* We shouldn't style native anonymous children like scrollbars or what not. */
|
||||
tabpanels > *|*:not(:-moz-native-anonymous),
|
||||
deck > *|*:not(:-moz-native-anonymous),
|
||||
stack > *|*:not(:-moz-native-anonymous) {
|
||||
grid-area: 1 / 1;
|
||||
z-index: 0;
|
||||
|
@ -489,10 +505,6 @@ tab {
|
|||
-moz-box-pack: center;
|
||||
}
|
||||
|
||||
tabpanels {
|
||||
display: -moz-deck;
|
||||
}
|
||||
|
||||
/********** tooltip *********/
|
||||
|
||||
tooltip[titletip="true"] {
|
||||
|
|
|
@ -26,6 +26,9 @@ tabs {
|
|||
padding: 0 10px;
|
||||
margin-bottom: -12px;
|
||||
position: relative;
|
||||
/* Needs to sort on top of the tabbox, which is a grid container (and thus
|
||||
* causes pseudo stacking contexts to be created) */
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
tab {
|
||||
|
|
Загрузка…
Ссылка в новой задаче