Backed out changeset 2f74f8f2ed19 (bug 1689816) for causing reftest failures on skip-ink-multiline-position.html.
This commit is contained in:
@@ -75,6 +75,7 @@
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPrefs_accessibility.h"
|
||||
#include "mozilla/SVGGeometryFrame.h"
|
||||
#include "nsDeckFrame.h"
|
||||
|
||||
#include "XULAlertAccessible.h"
|
||||
#include "XULComboboxAccessible.h"
|
||||
@@ -442,20 +443,63 @@ LocalAccessible* nsAccessibilityService::GetRootDocumentAccessible(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void nsAccessibilityService::NotifyOfTabPanelVisibilityChange(
|
||||
PresShell* aPresShell, Element* aPanel, bool aNowVisible) {
|
||||
MOZ_ASSERT(aPanel->GetParent()->IsXULElement(nsGkAtoms::tabpanels));
|
||||
|
||||
void nsAccessibilityService::DeckPanelSwitched(PresShell* aPresShell,
|
||||
nsIContent* aDeckNode,
|
||||
nsIFrame* aPrevBoxFrame,
|
||||
nsIFrame* aCurrentBoxFrame) {
|
||||
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 (LocalAccessible* acc = document->GetAccessible(aPanel)) {
|
||||
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, aNowVisible);
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsAccessibilityService::ContentRangeInserted(PresShell* aPresShell,
|
||||
@@ -1084,6 +1128,16 @@ 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,6 +153,13 @@ 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.
|
||||
@@ -233,10 +240,6 @@ 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,6 +14,7 @@
|
||||
#include "nsAccCache.h"
|
||||
#include "nsAccessiblePivot.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsDeckFrame.h"
|
||||
#include "nsEventShell.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsTextEquivUtils.h"
|
||||
@@ -1051,6 +1052,21 @@ 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,6 +50,7 @@
|
||||
#include "nsIContent.h"
|
||||
#include "nsIFormControl.h"
|
||||
|
||||
#include "nsDeckFrame.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIFrame.h"
|
||||
@@ -69,7 +70,6 @@
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsWhitespaceTokenizer.h"
|
||||
#include "nsAttrName.h"
|
||||
#include "nsContainerFrame.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/BasicEvents.h"
|
||||
@@ -324,16 +324,22 @@ uint64_t LocalAccessible::VisibilityState() const {
|
||||
return states::INVISIBLE;
|
||||
}
|
||||
|
||||
if (nsLayoutUtils::IsPopup(curFrame)) {
|
||||
return 0;
|
||||
}
|
||||
if (nsLayoutUtils::IsPopup(curFrame)) return 0;
|
||||
|
||||
if (curFrame->StyleUIReset()->mMozSubtreeHiddenOnlyVisually) {
|
||||
// Offscreen state for background tab content.
|
||||
// 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;
|
||||
}
|
||||
|
||||
nsIFrame* parentFrame = curFrame->GetParent();
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Children of not selected deck panel are not accessible.");
|
||||
return states::INVISIBLE;
|
||||
}
|
||||
|
||||
// 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,6 +13,7 @@
|
||||
#include "XULTabAccessible.h"
|
||||
#include "HTMLFormControlAccessible.h"
|
||||
|
||||
#include "nsDeckFrame.h"
|
||||
#include "nsObjCExceptions.h"
|
||||
|
||||
using namespace mozilla::a11y;
|
||||
@@ -125,17 +126,26 @@ enum CheckboxValue {
|
||||
@implementation mozPaneAccessible
|
||||
|
||||
- (NSArray*)moxChildren {
|
||||
// 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 (!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);
|
||||
}
|
||||
|
||||
if (selectedAcc) {
|
||||
mozAccessible* curNative = GetNativeFromGeckoAccessible(selectedAcc);
|
||||
if (curNative)
|
||||
return
|
||||
[NSArray arrayWithObjects:GetObjectOrRepresentedView(curNative), nil];
|
||||
}
|
||||
MOZ_ASSERT_UNREACHABLE("We have no on screen tab content?");
|
||||
return @[];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
// CSS display
|
||||
testCSSAttrs("display_mozbox");
|
||||
testCSSAttrs("display_mozinlinebox");
|
||||
testCSSAttrs("display_mozdeck");
|
||||
testCSSAttrs("display_mozpopup");
|
||||
|
||||
SimpleTest.finish();
|
||||
@@ -49,6 +50,7 @@
|
||||
|
||||
<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.
|
||||
// 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.
|
||||
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();
|
||||
}
|
||||
});
|
||||
|
||||
// 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: ${win.document.activeElement?.nodeName}`
|
||||
uri + ": the active element is expected"
|
||||
);
|
||||
Assert.equal(win.gURLBar.value, "", uri + ": urlbar is empty");
|
||||
Assert.ok(win.gURLBar.placeholder, uri + ": placeholder text is present");
|
||||
|
||||
@@ -254,7 +254,11 @@ 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 = () => {
|
||||
@@ -265,7 +269,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"
|
||||
);
|
||||
|
||||
@@ -316,7 +320,11 @@ 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.
|
||||
@@ -459,7 +467,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.updateSelectedIndex(index);
|
||||
tabpanels.setAttribute("selectedIndex", 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,11 +397,9 @@ 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,7 +113,6 @@ 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,14 +10,18 @@
|
||||
#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"
|
||||
@@ -29,9 +33,13 @@
|
||||
|
||||
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;
|
||||
@@ -797,11 +805,12 @@ bool DisplayPortUtils::CalculateAndSetDisplayPortMargins(
|
||||
aRepaintMode);
|
||||
}
|
||||
|
||||
bool DisplayPortUtils::MaybeCreateDisplayPort(
|
||||
nsDisplayListBuilder* aBuilder, nsIFrame* aScrollFrame,
|
||||
nsIScrollableFrame* aScrollFrameAsScrollable, RepaintMode aRepaintMode) {
|
||||
bool DisplayPortUtils::MaybeCreateDisplayPort(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aScrollFrame,
|
||||
RepaintMode aRepaintMode) {
|
||||
nsIContent* content = aScrollFrame->GetContent();
|
||||
if (!content) {
|
||||
nsIScrollableFrame* scrollableFrame = do_QueryFrame(aScrollFrame);
|
||||
if (!content || !scrollableFrame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -814,7 +823,7 @@ bool DisplayPortUtils::MaybeCreateDisplayPort(
|
||||
if (aBuilder->IsPaintingToWindow() &&
|
||||
nsLayoutUtils::AsyncPanZoomEnabled(aScrollFrame) &&
|
||||
!aBuilder->HaveScrollableDisplayPort() &&
|
||||
aScrollFrameAsScrollable->WantAsyncScroll()) {
|
||||
scrollableFrame->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
|
||||
@@ -826,7 +835,7 @@ bool DisplayPortUtils::MaybeCreateDisplayPort(
|
||||
sDisplayportLog, LogLevel::Debug,
|
||||
("Setting DP on first-encountered scrollId=%" PRIu64 "\n", viewId));
|
||||
|
||||
CalculateAndSetDisplayPortMargins(aScrollFrameAsScrollable, aRepaintMode);
|
||||
CalculateAndSetDisplayPortMargins(scrollableFrame, aRepaintMode);
|
||||
#ifdef DEBUG
|
||||
haveDisplayPort = HasNonMinimalDisplayPort(content);
|
||||
MOZ_ASSERT(haveDisplayPort,
|
||||
@@ -875,8 +884,10 @@ bool DisplayPortUtils::MaybeCreateDisplayPortInFirstScrollFrameEncountered(
|
||||
aFrame->GetContent()->GetID() == nsGkAtoms::tabbrowser_arrowscrollbox) {
|
||||
return false;
|
||||
}
|
||||
if (nsIScrollableFrame* sf = do_QueryFrame(aFrame)) {
|
||||
if (MaybeCreateDisplayPort(aBuilder, aFrame, sf, RepaintMode::Repaint)) {
|
||||
|
||||
nsIScrollableFrame* sf = do_QueryFrame(aFrame);
|
||||
if (sf) {
|
||||
if (MaybeCreateDisplayPort(aBuilder, aFrame, RepaintMode::Repaint)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -890,21 +901,28 @@ bool DisplayPortUtils::MaybeCreateDisplayPortInFirstScrollFrameEncountered(
|
||||
if (aFrame->IsSubDocumentFrame()) {
|
||||
PresShell* presShell = static_cast<nsSubDocumentFrame*>(aFrame)
|
||||
->GetSubdocumentPresShellForPainting(0);
|
||||
if (nsIFrame* root = presShell ? presShell->GetRootFrame() : nullptr) {
|
||||
nsIFrame* root = presShell ? presShell->GetRootFrame() : nullptr;
|
||||
if (root) {
|
||||
if (MaybeCreateDisplayPortInFirstScrollFrameEncountered(root, aBuilder)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aFrame->StyleUIReset()->mMozSubtreeHiddenOnlyVisually) {
|
||||
// Only descend the visible card of deck / tabpanels
|
||||
return false;
|
||||
if (aFrame->IsDeckFrame()) {
|
||||
// only descend the visible card of a decks
|
||||
nsIFrame* child = static_cast<nsDeckFrame*>(aFrame)->GetSelectedBox();
|
||||
if (child) {
|
||||
return MaybeCreateDisplayPortInFirstScrollFrameEncountered(child,
|
||||
aBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
nsIScrollableFrame* aScrollFrameAsScrollable, RepaintMode aRepaintMode);
|
||||
static bool MaybeCreateDisplayPort(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aScrollFrame,
|
||||
RepaintMode aRepaintMode);
|
||||
|
||||
/**
|
||||
* Sets a zero margin display port on all proper ancestors of aFrame that
|
||||
|
||||
@@ -3961,24 +3961,38 @@ 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);
|
||||
MOZ_ASSERT(
|
||||
aFrame && aFrame->GetParent() &&
|
||||
aFrame->GetParent()->Type() == LayoutFrameType::Deck,
|
||||
"This function should only be called with a child frame of <deck>");
|
||||
|
||||
nsIContent* capturingContent = GetCapturingContent();
|
||||
if (!capturingContent) {
|
||||
AllowMouseCapture(false);
|
||||
return;
|
||||
}
|
||||
|
||||
nsIFrame* capturingFrame = capturingContent->GetPrimaryFrame();
|
||||
const bool shouldClear =
|
||||
!capturingFrame ||
|
||||
nsLayoutUtils::IsAncestorFrameCrossDocInProcess(aFrame, capturingFrame);
|
||||
if (shouldClear) {
|
||||
ClearMouseCapture();
|
||||
if (!capturingFrame) {
|
||||
ReleaseCapturingContent();
|
||||
AllowMouseCapture(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nsLayoutUtils::IsAncestorFrameCrossDocInProcess(aFrame, capturingFrame)) {
|
||||
ReleaseCapturingContent();
|
||||
AllowMouseCapture(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -205,22 +205,13 @@ class PresShell final : public nsStubDocumentObserver,
|
||||
|
||||
static void ClearMouseCaptureOnView(nsView* aView);
|
||||
|
||||
// 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);
|
||||
|
||||
// Clear the capture content if it exists in this process.
|
||||
static void ClearMouseCapture();
|
||||
|
||||
#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,
|
||||
const ComputedStyle& aOldStyle, const ComputedStyle& aNewStyle,
|
||||
ComputedStyle* aOldComputedStyle, ComputedStyle* aNewComputedStyle,
|
||||
ServoPostTraversalFlags aFlags) {
|
||||
using Flags = ServoPostTraversalFlags;
|
||||
MOZ_ASSERT(!(aFlags & Flags::SkipA11yNotifications) ||
|
||||
@@ -2638,24 +2638,13 @@ 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) {
|
||||
// Propagate the skipping flag to descendants.
|
||||
// Propogate the skipping flag to descendants.
|
||||
return Flags::SkipA11yNotifications;
|
||||
}
|
||||
|
||||
bool needsNotify = false;
|
||||
bool isVisible = aNewStyle.StyleVisibility()->IsVisible();
|
||||
bool isVisible = aNewComputedStyle->StyleVisibility()->IsVisible();
|
||||
if (aFlags & Flags::SendA11yNotificationsIfShown) {
|
||||
if (!isVisible) {
|
||||
// Propagate the sending-if-shown flag to descendants.
|
||||
@@ -2668,7 +2657,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 = aOldStyle.StyleVisibility()->IsVisible();
|
||||
bool wasVisible = aOldComputedStyle->StyleVisibility()->IsVisible();
|
||||
needsNotify = wasVisible != isVisible;
|
||||
}
|
||||
|
||||
@@ -2898,9 +2887,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 =
|
||||
|
||||
10
layout/base/crashtests/344300-2.html
Normal file
10
layout/base/crashtests/344300-2.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<html><body>
|
||||
<object style="display:-moz-deck;">
|
||||
<noscript>
|
||||
</noscript>
|
||||
</object>
|
||||
</body></html>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -58,13 +58,16 @@ 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;">
|
||||
mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m mm m 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 mm m mm m mm m mm m mm m 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
|
||||
<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>
|
||||
@@ -363,6 +366,7 @@ mm m mm m mm m mm m 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>
|
||||
</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; ">
|
||||
@@ -401,6 +405,7 @@ mm m mm m mm m mm m 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>
|
||||
</q>
|
||||
</p>
|
||||
</listing>
|
||||
<q style=" display: table-header-group; ">
|
||||
<q style=" display: table-cell; ">
|
||||
<q style=" display: table; direction: ltr;">
|
||||
@@ -651,7 +656,7 @@ mm m mm m mm m mm m 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>
|
||||
<ol style="display: inline-block;direction: ltr;">
|
||||
<p style="display: inherit;position: fixed;direction: ltr;">
|
||||
<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
|
||||
<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
|
||||
</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
|
||||
|
||||
4
layout/base/crashtests/570038-1.html
Normal file
4
layout/base/crashtests/570038-1.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body><div style="display: -moz-deck;"><div style="overflow: auto; border: 4294967296px solid blue;">M</div></div></body>
|
||||
</html>
|
||||
@@ -105,6 +105,7 @@ 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
|
||||
@@ -315,6 +316,7 @@ 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,6 +215,8 @@ 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);
|
||||
@@ -4547,6 +4549,11 @@ 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,6 +117,7 @@
|
||||
#include "nsCSSPseudoElements.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsTHashMap.h"
|
||||
#include "nsDeckFrame.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsFlexContainerFrame.h"
|
||||
#include "nsFontInflationData.h"
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "nsRepeatService.h"
|
||||
#include "nsFloatManager.h"
|
||||
#include "nsSprocketLayout.h"
|
||||
#include "nsStackLayout.h"
|
||||
#include "nsTextControlFrame.h"
|
||||
#include "txMozillaXSLTProcessor.h"
|
||||
#include "nsTreeSanitizer.h"
|
||||
@@ -328,6 +329,7 @@ void nsLayoutStatics::Shutdown() {
|
||||
nsColorNames::ReleaseTable();
|
||||
nsCSSProps::ReleaseTable();
|
||||
nsRepeatService::Shutdown();
|
||||
nsStackLayout::Shutdown();
|
||||
|
||||
nsXULContentUtils::Finish();
|
||||
nsXULPrototypeCache::ReleaseGlobals();
|
||||
|
||||
16
layout/forms/crashtests/378413-1.xhtml
Normal file
16
layout/forms/crashtests/378413-1.xhtml
Normal file
@@ -0,0 +1,16 @@
|
||||
<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,6 +20,7 @@ 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,6 +22,7 @@ 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),
|
||||
|
||||
14
layout/generic/crashtests/370866-1.xhtml
Normal file
14
layout/generic/crashtests/370866-1.xhtml
Normal file
@@ -0,0 +1,14 @@
|
||||
<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>
|
||||
17
layout/generic/crashtests/381786-1.html
Normal file
17
layout/generic/crashtests/381786-1.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!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>
|
||||
16
layout/generic/crashtests/862947-1.html
Normal file
16
layout/generic/crashtests/862947-1.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
|
||||
div { display: flex; }
|
||||
div:after { display: -moz-deck; content: counter(b); }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -87,6 +87,7 @@ 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
|
||||
@@ -103,6 +104,7 @@ 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
|
||||
@@ -534,6 +536,7 @@ 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,6 +100,7 @@
|
||||
#include "nsBlockFrame.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsChangeHint.h"
|
||||
#include "nsDeckFrame.h"
|
||||
#include "nsSubDocumentFrame.h"
|
||||
#include "RetainedDisplayListBuilder.h"
|
||||
|
||||
@@ -374,19 +375,17 @@ 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 (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 (frame->StyleUIReset()->mMozSubtreeHiddenOnlyVisually) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this != frame && frame->HidesContent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nsIFrame* parent = frame->GetParent()) {
|
||||
if (parent) {
|
||||
frame = parent;
|
||||
} else {
|
||||
parent = nsLayoutUtils::GetCrossDocParentFrameInProcess(frame);
|
||||
@@ -1287,10 +1286,6 @@ void nsIFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
|
||||
scrollableFrame->PostPendingResnap();
|
||||
}
|
||||
}
|
||||
if (StyleUIReset()->mMozSubtreeHiddenOnlyVisually &&
|
||||
!aOldComputedStyle->StyleUIReset()->mMozSubtreeHiddenOnlyVisually) {
|
||||
PresShell::ClearMouseCapture(this);
|
||||
}
|
||||
} else { // !aOldComputedStyle
|
||||
handleStickyChange = disp->mPosition == StylePositionProperty::Sticky;
|
||||
}
|
||||
@@ -3988,21 +3983,22 @@ 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);
|
||||
if (aFrame->HasAnyStateBits(skipFlags)) {
|
||||
return true;
|
||||
}
|
||||
return aFrame->StyleUIReset()->mMozSubtreeHiddenOnlyVisually;
|
||||
|
||||
return aFrame->HasAnyStateBits(skipFlags);
|
||||
}
|
||||
|
||||
void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
8
layout/reftests/bugs/411367-3-ref.html
Normal file
8
layout/reftests/bugs/411367-3-ref.html
Normal file
@@ -0,0 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div style="display: -moz-deck;" id="s">x</div>
|
||||
</body>
|
||||
</html>
|
||||
8
layout/reftests/bugs/411367-3.html
Normal file
8
layout/reftests/bugs/411367-3.html
Normal file
@@ -0,0 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body onload="document.getElementById('s').firstChild.data = 'x';">
|
||||
<div style="display: -moz-deck;" id="s"> </div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -926,6 +926,7 @@ 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
|
||||
|
||||
@@ -607,7 +607,6 @@ 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,6 +91,8 @@ 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,8 +3213,7 @@ nsChangeHint nsStyleUI::CalcDifference(const nsStyleUI& aNewData) const {
|
||||
nsStyleUIReset::nsStyleUIReset(const Document& aDocument)
|
||||
: mUserSelect(StyleUserSelect::Auto),
|
||||
mScrollbarWidth(StyleScrollbarWidth::Auto),
|
||||
mMozForceBrokenImageIcon(false),
|
||||
mMozSubtreeHiddenOnlyVisually(false),
|
||||
mMozForceBrokenImageIcon(0),
|
||||
mIMEMode(StyleImeMode::Auto),
|
||||
mWindowDragging(StyleWindowDragging::Default),
|
||||
mWindowShadow(StyleWindowShadow::Default),
|
||||
@@ -3251,7 +3250,6 @@ 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),
|
||||
@@ -3289,9 +3287,6 @@ 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,8 +1863,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUIReset {
|
||||
return mAnimations[aIndex % mAnimationTimelineCount].GetTimeline();
|
||||
}
|
||||
|
||||
mozilla::StyleBoolInteger mMozForceBrokenImageIcon;
|
||||
mozilla::StyleBoolInteger mMozSubtreeHiddenOnlyVisually;
|
||||
uint8_t mMozForceBrokenImageIcon; // (0 if not forcing, otherwise forcing)
|
||||
mozilla::StyleImeMode mIMEMode;
|
||||
mozilla::StyleWindowDragging mWindowDragging;
|
||||
mozilla::StyleWindowShadow mWindowShadow;
|
||||
|
||||
@@ -104,7 +104,6 @@ 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,6 +134,8 @@ 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]
|
||||
|
||||
42
layout/style/test/test_bug453896_deck.html
Normal file
42
layout/style/test/test_bug453896_deck.html
Normal file
@@ -0,0 +1,42 @@
|
||||
<!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,6 +19,7 @@ const NON_CONTENT_ACCESSIBLE_VALUES = {
|
||||
"-moz-autofill-background",
|
||||
],
|
||||
"display": [
|
||||
"-moz-deck",
|
||||
"-moz-popup",
|
||||
"-moz-box",
|
||||
"-moz-inline-box",
|
||||
|
||||
6
layout/xul/crashtests/290743.html
Normal file
6
layout/xul/crashtests/290743.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<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>
|
||||
12
layout/xul/crashtests/311457-1.html
Normal file
12
layout/xul/crashtests/311457-1.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<html><head>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div style="display: -moz-deck"><div style="display: -moz-popup"></div></div>
|
||||
|
||||
<div style="position: relative">Y</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
5
layout/xul/crashtests/374102-1.xhtml
Normal file
5
layout/xul/crashtests/374102-1.xhtml
Normal file
@@ -0,0 +1,5 @@
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<tabpanels>
|
||||
<treechildren style="display: -moz-deck;"/>
|
||||
</tabpanels>
|
||||
</window>
|
||||
31
layout/xul/crashtests/399013.xhtml
Normal file
31
layout/xul/crashtests/399013.xhtml
Normal file
@@ -0,0 +1,31 @@
|
||||
<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,10 +5,12 @@ 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
|
||||
@@ -22,6 +24,7 @@ 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
|
||||
@@ -36,6 +39,7 @@ 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,6 +23,7 @@ UNIFIED_SOURCES += [
|
||||
"nsBoxFrame.cpp",
|
||||
"nsBoxLayout.cpp",
|
||||
"nsBoxLayoutState.cpp",
|
||||
"nsDeckFrame.cpp",
|
||||
"nsDocElementBoxFrame.cpp",
|
||||
"nsImageBoxFrame.cpp",
|
||||
"nsLeafBoxFrame.cpp",
|
||||
@@ -38,6 +39,7 @@ UNIFIED_SOURCES += [
|
||||
"nsSliderFrame.cpp",
|
||||
"nsSplitterFrame.cpp",
|
||||
"nsSprocketLayout.cpp",
|
||||
"nsStackLayout.cpp",
|
||||
"nsTextBoxFrame.cpp",
|
||||
"nsXULPopupManager.cpp",
|
||||
"nsXULTooltipListener.cpp",
|
||||
|
||||
@@ -308,7 +308,8 @@ nsresult nsIFrame::SyncXULLayout(nsBoxLayoutState& aBoxLayoutState) {
|
||||
nsresult nsIFrame::XULRedraw(nsBoxLayoutState& aState) {
|
||||
if (aState.PaintingDisabled()) return NS_OK;
|
||||
|
||||
// Unclear whether we could get away with just InvalidateFrame().
|
||||
// nsStackLayout, at least, expects us to repaint descendants even
|
||||
// if a damage rect is provided
|
||||
InvalidateFrameSubtree();
|
||||
|
||||
return NS_OK;
|
||||
|
||||
283
layout/xul/nsDeckFrame.cpp
Normal file
283
layout/xul/nsDeckFrame.cpp
Normal file
@@ -0,0 +1,283 @@
|
||||
/* -*- 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;
|
||||
}
|
||||
78
layout/xul/nsDeckFrame.h
Normal file
78
layout/xul/nsDeckFrame.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* -*- 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,6 +15,7 @@
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsBoxFrame.h"
|
||||
#include "nsStackLayout.h"
|
||||
#include "nsIAnonymousContentCreator.h"
|
||||
#include "nsNodeInfoManager.h"
|
||||
#include "nsContentCreatorFunctions.h"
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsBoxFrame.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsStackLayout.h"
|
||||
#include "nsIPopupContainer.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsFrameManager.h"
|
||||
|
||||
209
layout/xul/nsStackLayout.cpp
Normal file
209
layout/xul/nsStackLayout.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
/* -*- 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;
|
||||
}
|
||||
48
layout/xul/nsStackLayout.h
Normal file
48
layout/xul/nsStackLayout.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* -*- 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",
|
||||
"BoolInteger",
|
||||
"MozForceBrokenImageIcon",
|
||||
"text::MozControlCharacterVisibility",
|
||||
"MathDepth",
|
||||
"MozScriptMinSize",
|
||||
|
||||
@@ -108,23 +108,11 @@ ${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",
|
||||
"BoolInteger",
|
||||
"computed::BoolInteger::zero()",
|
||||
"MozForceBrokenImageIcon",
|
||||
"computed::MozForceBrokenImageIcon::false_value()",
|
||||
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, BoolInteger, UserSelect};
|
||||
pub use self::ui::{Cursor, MozForceBrokenImageIcon, 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::{BoolInteger, UserSelect};
|
||||
pub use crate::values::specified::ui::{MozForceBrokenImageIcon, UserSelect};
|
||||
|
||||
/// A computed value for the `cursor` property.
|
||||
pub type Cursor = generics::GenericCursor<CursorImage>;
|
||||
|
||||
@@ -101,6 +101,8 @@ pub enum DisplayInside {
|
||||
#[cfg(feature = "gecko")]
|
||||
MozBox,
|
||||
#[cfg(feature = "gecko")]
|
||||
MozDeck,
|
||||
#[cfg(feature = "gecko")]
|
||||
MozPopup,
|
||||
}
|
||||
|
||||
@@ -214,6 +216,8 @@ 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.
|
||||
@@ -594,6 +598,8 @@ 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, BoolInteger, UserSelect};
|
||||
pub use self::ui::{Cursor, MozForceBrokenImageIcon, UserSelect};
|
||||
pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent;
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
|
||||
@@ -88,32 +88,31 @@ impl SpecifiedValueInfo for CursorImage {
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct BoolInteger(pub bool);
|
||||
pub struct MozForceBrokenImageIcon(pub bool);
|
||||
|
||||
impl BoolInteger {
|
||||
/// Returns 0
|
||||
impl MozForceBrokenImageIcon {
|
||||
/// Return initial value of -moz-force-broken-image-icon which is false.
|
||||
#[inline]
|
||||
pub fn zero() -> Self {
|
||||
Self(false)
|
||||
pub fn false_value() -> MozForceBrokenImageIcon {
|
||||
MozForceBrokenImageIcon(false)
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for BoolInteger {
|
||||
impl Parse for MozForceBrokenImageIcon {
|
||||
fn parse<'i, 't>(
|
||||
_context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
) -> Result<MozForceBrokenImageIcon, ParseError<'i>> {
|
||||
// We intentionally don't support calc values here.
|
||||
match input.expect_integer()? {
|
||||
0 => Ok(Self(false)),
|
||||
1 => Ok(Self(true)),
|
||||
0 => Ok(MozForceBrokenImageIcon(false)),
|
||||
1 => Ok(MozForceBrokenImageIcon(true)),
|
||||
_ => Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for BoolInteger {
|
||||
impl ToCss for MozForceBrokenImageIcon {
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: Write,
|
||||
@@ -122,6 +121,22 @@ impl ToCss for BoolInteger {
|
||||
}
|
||||
}
|
||||
|
||||
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,7 +79,6 @@ 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,13 +5,14 @@
|
||||
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>
|
||||
|
||||
<deck id="deck1" style="padding-top: 5px; padding-bottom: 12px;">
|
||||
<button id="d1b1" label="Button One"/>
|
||||
<button id="d1b2" label="Button Two is larger" style="height: 80px; margin: 1px;"/>
|
||||
<button id="d1b2" label="Button Two is larger" height="80" style="margin: 1px;"/>
|
||||
</deck>
|
||||
<deck id="deck2" selectedIndex="1">
|
||||
<button id="d2b1" label="Button One"/>
|
||||
@@ -43,15 +44,19 @@
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript"><![CDATA[
|
||||
add_task(async function run_tests() {
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function run_tests() {
|
||||
test_deck();
|
||||
await test_deck_child_removal();
|
||||
});
|
||||
test_deck_child_removal();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function test_deck()
|
||||
{
|
||||
var deck = $("deck1");
|
||||
is(deck.selectedIndex, 0, "deck one selectedIndex");
|
||||
ok(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();
|
||||
@@ -61,52 +66,47 @@ 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;
|
||||
is(deck.selectedIndex, 1, "deck one selectedIndex after change");
|
||||
ok(deck.selectedIndex === '1', "deck one selectedIndex after change");
|
||||
synthesizeMouseExpectEvent(deck, 9, 9, { }, $("d1b2"), "click", "mouse on deck one after change");
|
||||
|
||||
deck = $("deck2");
|
||||
is(deck.selectedIndex, 1, "deck two selectedIndex");
|
||||
ok(deck.selectedIndex === '1', "deck two selectedIndex");
|
||||
synthesizeMouseExpectEvent(deck, 9, 9, { }, $("d2b2"), "click", "mouse on deck two");
|
||||
}
|
||||
|
||||
async function test_deck_child_removal()
|
||||
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();
|
||||
|
||||
await Promise.resolve();
|
||||
|
||||
is(deck.selectedIndex, 0, "Should have the deck element at index 0 selected");
|
||||
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, expectedIndex,
|
||||
is(deck.selectedIndex, String(expectedIndex),
|
||||
"Should have the deck element at index " + expectedIndex + " selected");
|
||||
|
||||
for (let i = 0; i < 3; ++i) {
|
||||
deck.firstChild.remove();
|
||||
expectedIndex--;
|
||||
await Promise.resolve();
|
||||
is(deck.selectedIndex, expectedIndex,
|
||||
is(deck.selectedIndex, String(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();
|
||||
await Promise.resolve();
|
||||
is(deck.selectedIndex, expectedIndex,
|
||||
is(deck.selectedIndex, String(expectedIndex),
|
||||
"The selectedIndex should not change when removing the node " +
|
||||
"at the selected index.");
|
||||
|
||||
@@ -114,16 +114,14 @@ async function test_deck_child_removal()
|
||||
// nodes at indexes greater than the selected node.
|
||||
deck = $("deck5");
|
||||
expectedIndex = 2;
|
||||
await Promise.resolve();
|
||||
is(deck.selectedIndex, expectedIndex,
|
||||
is(deck.selectedIndex, String(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();
|
||||
await Promise.resolve();
|
||||
is(deck.selectedIndex, expectedIndex,
|
||||
is(deck.selectedIndex, String(expectedIndex),
|
||||
"Should have the deck element at index " + expectedIndex + " selected");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,40 @@
|
||||
// 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,107 +158,14 @@
|
||||
|
||||
customElements.define("tabbox", MozTabbox);
|
||||
|
||||
class MozDeck extends MozXULElement {
|
||||
get isAsync() {
|
||||
return this.getAttribute("async") == "true";
|
||||
}
|
||||
|
||||
class MozTabpanels extends MozXULElement {
|
||||
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() {
|
||||
@@ -279,6 +186,46 @@
|
||||
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
|
||||
*/
|
||||
@@ -580,9 +527,7 @@
|
||||
|
||||
set selectedIndex(val) {
|
||||
var tab = this.getItemAtIndex(val);
|
||||
if (!tab) {
|
||||
return;
|
||||
}
|
||||
if (tab) {
|
||||
for (let otherTab of this.allTabs) {
|
||||
if (otherTab != tab && otherTab.selected) {
|
||||
otherTab._selected = false;
|
||||
@@ -601,6 +546,7 @@
|
||||
this.tabbox.tabpanels.selectedPanel = linkedPanel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get selectedIndex() {
|
||||
const tabs = this.allTabs;
|
||||
|
||||
@@ -448,34 +448,18 @@ treechildren::-moz-tree-cell(ltr) {
|
||||
direction: ltr !important;
|
||||
}
|
||||
|
||||
/********** deck, tabpanels & stack *********/
|
||||
/********** deck & stack *********/
|
||||
|
||||
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 {
|
||||
display: -moz-deck;
|
||||
}
|
||||
|
||||
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. */
|
||||
tabpanels > *|*:not(:-moz-native-anonymous),
|
||||
deck > *|*:not(:-moz-native-anonymous),
|
||||
/* We shouldn't style native anonymous children like scrollbars or what not */
|
||||
stack > *|*:not(:-moz-native-anonymous) {
|
||||
grid-area: 1 / 1;
|
||||
z-index: 0;
|
||||
@@ -505,6 +489,10 @@ tab {
|
||||
-moz-box-pack: center;
|
||||
}
|
||||
|
||||
tabpanels {
|
||||
display: -moz-deck;
|
||||
}
|
||||
|
||||
/********** tooltip *********/
|
||||
|
||||
tooltip[titletip="true"] {
|
||||
|
||||
@@ -26,9 +26,6 @@ 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 {
|
||||
|
||||
Reference in New Issue
Block a user