diff options
Diffstat (limited to 'layout')
42 files changed, 547 insertions, 482 deletions
diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list index e2cb99e04..6ded4ff3f 100644 --- a/layout/base/crashtests/crashtests.list +++ b/layout/base/crashtests/crashtests.list @@ -448,7 +448,7 @@ load 876092.html load 876221.html load 897852.html asserts(4-6) asserts-if(Android&&!asyncPan,2) load 898913.html # bug 847368 -pref(layers.acceleration.disabled,true) pref(layers.force-active,true) load 919434.html +pref(layers.acceleration.enabled,false) pref(layers.force-active,true) load 919434.html load 926728.html load 930381.html load 931450.html diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index ec676ca92..6642a090d 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -10886,6 +10886,7 @@ nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState, // no? And if we cared we could look through the item list // instead of groveling through the framelist here.. nsStyleContext *frameStyleContext = aFrame->StyleContext(); +#ifdef DEBUG // Report a warning for non-GC frames, for chrome: if (!aFrame->IsGeneratedContentFrame() && mPresShell->GetPresContext()->IsChrome()) { @@ -10904,6 +10905,7 @@ nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState, message, params, ArrayLength(params)); } +#endif RefPtr<nsStyleContext> blockSC = mPresShell->StyleSet()-> ResolveAnonymousBoxStyle(nsCSSAnonBoxes::mozXULAnonymousBlock, diff --git a/layout/base/nsCaret.cpp b/layout/base/nsCaret.cpp index eca22f3ba..8396726c6 100644 --- a/layout/base/nsCaret.cpp +++ b/layout/base/nsCaret.cpp @@ -511,7 +511,7 @@ nsCaret::GetPaintGeometry(nsRect* aRect) CheckSelectionLanguageChange(); int32_t frameOffset; - nsIFrame *frame = GetFrameAndOffset(GetSelectionInternal(), + nsIFrame* frame = GetFrameAndOffset(GetSelectionInternal(), mOverrideContent, mOverrideOffset, &frameOffset); if (!frame) { return nullptr; @@ -521,8 +521,7 @@ nsCaret::GetPaintGeometry(nsRect* aRect) const nsStyleUserInterface* userinterface = frame->StyleUserInterface(); if ((!mIgnoreUserModify && userinterface->mUserModify == StyleUserModify::ReadOnly) || - userinterface->mUserInput == StyleUserInput::None || - userinterface->mUserInput == StyleUserInput::Disabled) { + frame->IsContentDisabled()){ return nullptr; } diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index 5ea7a0188..c0d09d2a0 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -851,12 +851,6 @@ NS_IMPL_ISUPPORTS(VsyncChildCreateCallback, nsIIPCBackgroundChildCreateCallback) static StaticRefPtr<RefreshDriverTimer> sRegularRateTimer; static StaticRefPtr<InactiveRefreshDriverTimer> sThrottledRateTimer; -#ifdef XP_WIN -static int32_t sHighPrecisionTimerRequests = 0; -// a bare pointer to avoid introducing a static constructor -static nsITimer *sDisableHighPrecisionTimersTimer = nullptr; -#endif - static void CreateContentVsyncRefreshTimer(void*) { @@ -934,16 +928,6 @@ nsRefreshDriver::Shutdown() sRegularRateTimer = nullptr; sThrottledRateTimer = nullptr; - -#ifdef XP_WIN - if (sDisableHighPrecisionTimersTimer) { - sDisableHighPrecisionTimersTimer->Cancel(); - NS_RELEASE(sDisableHighPrecisionTimersTimer); - timeEndPeriod(1); - } else if (sHighPrecisionTimerRequests) { - timeEndPeriod(1); - } -#endif } /* static */ int32_t @@ -1062,7 +1046,6 @@ nsRefreshDriver::nsRefreshDriver(nsPresContext* aPresContext) mNeedToRecomputeVisibility(false), mTestControllingRefreshes(false), mViewManagerFlushIsPending(false), - mRequestedHighPrecision(false), mInRefresh(false), mWaitingForTransaction(false), mSkippedPaints(false), @@ -1300,83 +1283,6 @@ nsRefreshDriver::StopTimer() mActiveTimer->RemoveRefreshDriver(this); mActiveTimer = nullptr; - - if (mRequestedHighPrecision) { - SetHighPrecisionTimersEnabled(false); - } -} - -#ifdef XP_WIN -static void -DisableHighPrecisionTimersCallback(nsITimer *aTimer, void *aClosure) -{ - timeEndPeriod(1); - NS_RELEASE(sDisableHighPrecisionTimersTimer); -} -#endif - -void -nsRefreshDriver::ConfigureHighPrecision() -{ - bool haveUnthrottledFrameRequestCallbacks = - mFrameRequestCallbackDocs.Length() > 0; - - // if the only change that's needed is that we need high precision, - // then just set that - if (!mThrottled && !mRequestedHighPrecision && - haveUnthrottledFrameRequestCallbacks) { - SetHighPrecisionTimersEnabled(true); - } else if (mRequestedHighPrecision && !haveUnthrottledFrameRequestCallbacks) { - SetHighPrecisionTimersEnabled(false); - } -} - -void -nsRefreshDriver::SetHighPrecisionTimersEnabled(bool aEnable) -{ - LOG("[%p] SetHighPrecisionTimersEnabled (%s)", this, aEnable ? "true" : "false"); - - if (aEnable) { - NS_ASSERTION(!mRequestedHighPrecision, "SetHighPrecisionTimersEnabled(true) called when already requested!"); -#ifdef XP_WIN - if (++sHighPrecisionTimerRequests == 1) { - // If we had a timer scheduled to disable it, that means that it's already - // enabled; just cancel the timer. Otherwise, really enable it. - if (sDisableHighPrecisionTimersTimer) { - sDisableHighPrecisionTimersTimer->Cancel(); - NS_RELEASE(sDisableHighPrecisionTimersTimer); - } else { - timeBeginPeriod(1); - } - } -#endif - mRequestedHighPrecision = true; - } else { - NS_ASSERTION(mRequestedHighPrecision, "SetHighPrecisionTimersEnabled(false) called when not requested!"); -#ifdef XP_WIN - if (--sHighPrecisionTimerRequests == 0) { - // Don't jerk us around between high precision and low precision - // timers; instead, only allow leaving high precision timers - // after 90 seconds. This is arbitrary, but hopefully good - // enough. - NS_ASSERTION(!sDisableHighPrecisionTimersTimer, "We shouldn't have an outstanding disable-high-precision timer !"); - - nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID); - if (timer) { - timer.forget(&sDisableHighPrecisionTimersTimer); - sDisableHighPrecisionTimersTimer->InitWithFuncCallback(DisableHighPrecisionTimersCallback, - nullptr, - 90 * 1000, - nsITimer::TYPE_ONE_SHOT); - } else { - // might happen if we're shutting down XPCOM; just drop the time period down - // immediately - timeEndPeriod(1); - } - } -#endif - mRequestedHighPrecision = false; - } } uint32_t @@ -1993,8 +1899,6 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime) observer->DidRefresh(); } - ConfigureHighPrecision(); - NS_ASSERTION(mInRefresh, "Still in refresh"); if (mPresContext->IsRoot() && XRE_IsContentProcess() && gfxPrefs::AlwaysPaint()) { @@ -2247,7 +2151,6 @@ nsRefreshDriver::ScheduleFrameRequestCallbacks(nsIDocument* aDocument) } // make sure that the timer is running - ConfigureHighPrecision(); EnsureTimerStarted(); } @@ -2256,7 +2159,6 @@ nsRefreshDriver::RevokeFrameRequestCallbacks(nsIDocument* aDocument) { mFrameRequestCallbackDocs.RemoveElement(aDocument); mThrottledFrameRequestCallbackDocs.RemoveElement(aDocument); - ConfigureHighPrecision(); // No need to worry about restarting our timer in slack mode if it's already // running; that will happen automatically when it fires. } diff --git a/layout/base/nsRefreshDriver.h b/layout/base/nsRefreshDriver.h index b2dd9be4b..4e839e764 100644 --- a/layout/base/nsRefreshDriver.h +++ b/layout/base/nsRefreshDriver.h @@ -450,7 +450,6 @@ private: bool mNeedToRecomputeVisibility; bool mTestControllingRefreshes; bool mViewManagerFlushIsPending; - bool mRequestedHighPrecision; bool mInRefresh; // True if the refresh driver is suspended waiting for transaction @@ -502,10 +501,6 @@ private: friend class mozilla::RefreshDriverTimer; - // turn on or turn off high precision based on various factors - void ConfigureHighPrecision(); - void SetHighPrecisionTimersEnabled(bool aEnable); - static void Shutdown(); // `true` if we are currently in jank-critical mode. diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index 9313b8e45..4455da122 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -178,21 +178,14 @@ static void Shutdown(); #include "AudioChannelService.h" #include "mozilla/net/WebSocketEventService.h" -#include "mozilla/dom/FlyWebService.h" - #include "mozilla/dom/power/PowerManagerService.h" #include "mozilla/dom/time/TimeService.h" #include "StreamingProtocolService.h" -#include "nsIPresentationService.h" - #include "MediaManager.h" #include "GMPService.h" -#include "mozilla/dom/PresentationDeviceManager.h" -#include "mozilla/dom/PresentationTCPSessionTransport.h" - #include "nsScriptError.h" #include "mozilla/TextInputProcessor.h" @@ -236,16 +229,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(HTMLEditor) #define TRANSFORMIIX_NODESET_CONTRACTID \ "@mozilla.org/transformiix-nodeset;1" -// PresentationDeviceManager -/* e1e79dec-4085-4994-ac5b-744b016697e6 */ -#define PRESENTATION_DEVICE_MANAGER_CID \ -{ 0xe1e79dec, 0x4085, 0x4994, { 0xac, 0x5b, 0x74, 0x4b, 0x01, 0x66, 0x97, 0xe6 } } - -#define PRESENTATION_TCP_SESSION_TRANSPORT_CID \ -{ 0xc9d023f4, 0x6228, 0x4c07, { 0x8b, 0x1d, 0x9c, 0x19, 0x57, 0x3f, 0xaa, 0x27 } } - -already_AddRefed<nsIPresentationService> NS_CreatePresentationService(); - // Factory Constructor NS_GENERIC_FACTORY_CONSTRUCTOR(txMozillaXSLTProcessor) NS_GENERIC_FACTORY_CONSTRUCTOR(XPathEvaluator) @@ -289,11 +272,7 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIStreamingProtocolControllerService, NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMediaManagerService, MediaManager::GetInstance) -NS_GENERIC_FACTORY_CONSTRUCTOR(PresentationDeviceManager) NS_GENERIC_FACTORY_CONSTRUCTOR(TextInputProcessor) -NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIPresentationService, - NS_CreatePresentationService) -NS_GENERIC_FACTORY_CONSTRUCTOR(PresentationTCPSessionTransport) NS_GENERIC_FACTORY_CONSTRUCTOR(PushNotifier) //----------------------------------------------------------------------------- @@ -529,17 +508,12 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(Geolocation, Init) #define NS_WEBSOCKETEVENT_SERVICE_CID \ { 0x31689828, 0xda66, 0x49a6, { 0x87, 0x0c, 0xdf, 0x62, 0xb8, 0x3f, 0xe7, 0x89 }} -#define NS_FLYWEB_SERVICE_CID \ - { 0x5de19ef0, 0x895e, 0x4c0c, { 0xa6, 0xe0, 0xea, 0xe0, 0x23, 0x2b, 0x84, 0x5a } } - NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsGeolocationService, nsGeolocationService::GetGeolocationService) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(AudioChannelService, AudioChannelService::GetOrCreate) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(WebSocketEventService, WebSocketEventService::GetOrCreate) -NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(FlyWebService, FlyWebService::GetOrCreateAddRefed) - #ifdef MOZ_WEBSPEECH_TEST_BACKEND NS_GENERIC_FACTORY_CONSTRUCTOR(FakeSpeechRecognitionService) #endif @@ -676,7 +650,6 @@ NS_DEFINE_NAMED_CID(NS_GEOLOCATION_SERVICE_CID); NS_DEFINE_NAMED_CID(NS_GEOLOCATION_CID); NS_DEFINE_NAMED_CID(NS_AUDIOCHANNEL_SERVICE_CID); NS_DEFINE_NAMED_CID(NS_WEBSOCKETEVENT_SERVICE_CID); -NS_DEFINE_NAMED_CID(NS_FLYWEB_SERVICE_CID); NS_DEFINE_NAMED_CID(NS_FOCUSMANAGER_CID); NS_DEFINE_NAMED_CID(NS_CONTENTSECURITYMANAGER_CID); NS_DEFINE_NAMED_CID(CSPSERVICE_CID); @@ -719,10 +692,6 @@ NS_DEFINE_NAMED_CID(NS_ACCESSIBILITY_SERVICE_CID); NS_DEFINE_NAMED_CID(GECKO_MEDIA_PLUGIN_SERVICE_CID); -NS_DEFINE_NAMED_CID(PRESENTATION_SERVICE_CID); -NS_DEFINE_NAMED_CID(PRESENTATION_DEVICE_MANAGER_CID); -NS_DEFINE_NAMED_CID(PRESENTATION_TCP_SESSION_TRANSPORT_CID); - NS_DEFINE_NAMED_CID(TEXT_INPUT_PROCESSOR_CID); NS_DEFINE_NAMED_CID(NS_SCRIPTERROR_CID); @@ -942,7 +911,6 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = { { &kNS_GEOLOCATION_CID, false, nullptr, GeolocationConstructor }, { &kNS_AUDIOCHANNEL_SERVICE_CID, false, nullptr, AudioChannelServiceConstructor }, { &kNS_WEBSOCKETEVENT_SERVICE_CID, false, nullptr, WebSocketEventServiceConstructor }, - { &kNS_FLYWEB_SERVICE_CID, false, nullptr, FlyWebServiceConstructor }, { &kNS_FOCUSMANAGER_CID, false, nullptr, CreateFocusManager }, #ifdef MOZ_WEBSPEECH_TEST_BACKEND { &kNS_FAKE_SPEECH_RECOGNITION_SERVICE_CID, false, nullptr, FakeSpeechRecognitionServiceConstructor }, @@ -981,9 +949,6 @@ static const mozilla::Module::CIDEntry kLayoutCIDs[] = { #ifdef ACCESSIBILITY { &kNS_ACCESSIBILITY_SERVICE_CID, false, nullptr, CreateA11yService }, #endif - { &kPRESENTATION_SERVICE_CID, false, nullptr, nsIPresentationServiceConstructor }, - { &kPRESENTATION_DEVICE_MANAGER_CID, false, nullptr, PresentationDeviceManagerConstructor }, - { &kPRESENTATION_TCP_SESSION_TRANSPORT_CID, false, nullptr, PresentationTCPSessionTransportConstructor }, { &kTEXT_INPUT_PROCESSOR_CID, false, nullptr, TextInputProcessorConstructor }, { &kNS_SCRIPTERROR_CID, false, nullptr, nsScriptErrorConstructor }, { nullptr } @@ -1072,8 +1037,6 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = { { "@mozilla.org/geolocation;1", &kNS_GEOLOCATION_CID }, { "@mozilla.org/audiochannel/service;1", &kNS_AUDIOCHANNEL_SERVICE_CID }, { "@mozilla.org/websocketevent/service;1", &kNS_WEBSOCKETEVENT_SERVICE_CID }, - { "@mozilla.org/flyweb-service;1", &kNS_FLYWEB_SERVICE_CID }, - { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "flyweb", &kNS_FLYWEB_SERVICE_CID }, { "@mozilla.org/focus-manager;1", &kNS_FOCUSMANAGER_CID }, #ifdef MOZ_WEBSPEECH_TEST_BACKEND { NS_SPEECH_RECOGNITION_SERVICE_CONTRACTID_PREFIX "fake", &kNS_FAKE_SPEECH_RECOGNITION_SERVICE_CID }, @@ -1113,9 +1076,6 @@ static const mozilla::Module::ContractIDEntry kLayoutContracts[] = { { "@mozilla.org/accessibleRetrieval;1", &kNS_ACCESSIBILITY_SERVICE_CID }, #endif { "@mozilla.org/gecko-media-plugin-service;1", &kGECKO_MEDIA_PLUGIN_SERVICE_CID }, - { PRESENTATION_SERVICE_CONTRACTID, &kPRESENTATION_SERVICE_CID }, - { PRESENTATION_DEVICE_MANAGER_CONTRACTID, &kPRESENTATION_DEVICE_MANAGER_CID }, - { PRESENTATION_TCP_SESSION_TRANSPORT_CONTRACTID, &kPRESENTATION_TCP_SESSION_TRANSPORT_CID }, { "@mozilla.org/text-input-processor;1", &kTEXT_INPUT_PROCESSOR_CID }, { NS_SCRIPTERROR_CONTRACTID, &kNS_SCRIPTERROR_CID }, { nullptr } @@ -1134,8 +1094,6 @@ static const mozilla::Module::CategoryEntry kLayoutCategories[] = { { "clear-origin-attributes-data", "QuotaManagerService", "service," QUOTAMANAGER_SERVICE_CONTRACTID }, { OBSERVER_TOPIC_IDLE_DAILY, "QuotaManagerService", QUOTAMANAGER_SERVICE_CONTRACTID }, CONTENTDLF_CATEGORIES - { "profile-after-change", "PresentationDeviceManager", PRESENTATION_DEVICE_MANAGER_CONTRACTID }, - { "profile-after-change", "PresentationService", PRESENTATION_SERVICE_CONTRACTID }, { nullptr } }; diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index 5a9438939..78185616f 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -1165,9 +1165,7 @@ nsComboboxControlFrame::HandleEvent(nsPresContext* aPresContext, // If we have style that affects how we are selected, feed event down to // nsFrame::HandleEvent so that selection takes place when appropriate. - const nsStyleUserInterface* uiStyle = StyleUserInterface(); - if (uiStyle->mUserInput == StyleUserInput::None || - uiStyle->mUserInput == StyleUserInput::Disabled) { + if (IsContentDisabled()) { return nsBlockFrame::HandleEvent(aPresContext, aEvent, aEventStatus); } return NS_OK; diff --git a/layout/forms/nsFormControlFrame.cpp b/layout/forms/nsFormControlFrame.cpp index 4ee62acbf..8dbe564dd 100644 --- a/layout/forms/nsFormControlFrame.cpp +++ b/layout/forms/nsFormControlFrame.cpp @@ -183,10 +183,8 @@ nsFormControlFrame::HandleEvent(nsPresContext* aPresContext, WidgetGUIEvent* aEvent, nsEventStatus* aEventStatus) { - // Check for user-input:none style - const nsStyleUserInterface* uiStyle = StyleUserInterface(); - if (uiStyle->mUserInput == StyleUserInput::None || - uiStyle->mUserInput == StyleUserInput::Disabled) { + // Check for disabled content so that selection works properly (?). + if (IsContentDisabled()) { return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus); } return NS_OK; diff --git a/layout/forms/nsGfxButtonControlFrame.cpp b/layout/forms/nsGfxButtonControlFrame.cpp index 90da437f7..393145e0b 100644 --- a/layout/forms/nsGfxButtonControlFrame.cpp +++ b/layout/forms/nsGfxButtonControlFrame.cpp @@ -227,10 +227,7 @@ nsGfxButtonControlFrame::HandleEvent(nsPresContext* aPresContext, // from being called. The nsFrame::HandleEvent causes the button label // to be selected (Drawn with an XOR rectangle over the label) - // do we have user-input style? - const nsStyleUserInterface* uiStyle = StyleUserInterface(); - if (uiStyle->mUserInput == StyleUserInput::None || - uiStyle->mUserInput == StyleUserInput::Disabled) { + if (IsContentDisabled()) { return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus); } return NS_OK; diff --git a/layout/forms/nsImageControlFrame.cpp b/layout/forms/nsImageControlFrame.cpp index 212fa9356..8aef41538 100644 --- a/layout/forms/nsImageControlFrame.cpp +++ b/layout/forms/nsImageControlFrame.cpp @@ -150,15 +150,9 @@ nsImageControlFrame::HandleEvent(nsPresContext* aPresContext, return NS_OK; } - // do we have user-input style? - const nsStyleUserInterface* uiStyle = StyleUserInterface(); - if (uiStyle->mUserInput == StyleUserInput::None || - uiStyle->mUserInput == StyleUserInput::Disabled) { + if (IsContentDisabled()) { return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus); } - if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled)) { // XXX cache disabled - return NS_OK; - } *aEventStatus = nsEventStatus_eIgnore; diff --git a/layout/forms/nsListControlFrame.cpp b/layout/forms/nsListControlFrame.cpp index cc5f37f9a..58e81039f 100644 --- a/layout/forms/nsListControlFrame.cpp +++ b/layout/forms/nsListControlFrame.cpp @@ -920,16 +920,11 @@ nsListControlFrame::HandleEvent(nsPresContext* aPresContext, if (nsEventStatus_eConsumeNoDefault == *aEventStatus) return NS_OK; - // do we have style that affects how we are selected? - // do we have user-input style? - const nsStyleUserInterface* uiStyle = StyleUserInterface(); - if (uiStyle->mUserInput == StyleUserInput::None || - uiStyle->mUserInput == StyleUserInput::Disabled) { + // disabled state affects how we're selected, but we don't want to go through + // nsHTMLScrollFrame if we're disabled. + if (IsContentDisabled()) { return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus); } - EventStates eventStates = mContent->AsElement()->State(); - if (eventStates.HasState(NS_EVENT_STATE_DISABLED)) - return NS_OK; return nsHTMLScrollFrame::HandleEvent(aPresContext, aEvent, aEventStatus); } diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index abf687c9b..3ff6c9bf1 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -1031,6 +1031,7 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame, if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) { PositionFrameView(aKidFrame); + PositionChildViews(aKidFrame); } // Reflow the child frame @@ -1074,6 +1075,7 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame, if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) { PositionFrameView(aKidFrame); + PositionChildViews(aKidFrame); } // Reflow the child frame @@ -1925,6 +1927,10 @@ nsContainerFrame::RenumberFrameAndDescendants(int32_t* aOrdinal, nsIFrame *f = bullet; do { nsIFrame *parent = f->GetParent(); + if (!parent) { + // We may have an orphan situation in some corner cases. + break; + } parent->ChildIsDirty(f); f = parent; } while (f != listItem); diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index bbbb5c332..0d0c7108c 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -5557,6 +5557,19 @@ nsFrame::Reflow(nsPresContext* aPresContext, NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize); } +bool +nsIFrame::IsContentDisabled() const +{ + // FIXME(emilio): Doing this via CSS means callers must ensure the style is up + // to date, and they don't! + if (StyleUserInterface()->mUserInput == StyleUserInput::None) { + return true; + } + + auto* element = nsGenericHTMLElement::FromContentOrNull(GetContent()); + return element && element->IsDisabled(); +} + nsresult nsFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo) { @@ -8434,9 +8447,13 @@ UnionBorderBoxes(nsIFrame* aFrame, bool aApplyTransform, Maybe<nsRect> clipPropClipRect = aFrame->GetClipPropClipRect(disp, effects, bounds.Size()); - // Iterate over all children except pop-ups. + // Iterate over all children except pop-ups, absolutely positioned children, + // fixed-positioned children and floats. const nsIFrame::ChildListIDs skip(nsIFrame::kPopupList | - nsIFrame::kSelectPopupList); + nsIFrame::kSelectPopupList | + nsIFrame::kAbsoluteList | + nsIFrame::kFixedList | + nsIFrame::kFloatList); for (nsIFrame::ChildListIterator childLists(aFrame); !childLists.IsDone(); childLists.Next()) { if (skip.Contains(childLists.CurrentID())) { @@ -8446,6 +8463,12 @@ UnionBorderBoxes(nsIFrame* aFrame, bool aApplyTransform, nsFrameList children = childLists.CurrentList(); for (nsFrameList::Enumerator e(children); !e.AtEnd(); e.Next()) { nsIFrame* child = e.get(); + + if (child->GetType() == nsGkAtoms::placeholderFrame) { + // Skip placeholders too. + continue; + } + // Note that passing |true| for aApplyTransform when // child->Combines3DTransformWithAncestors() is incorrect if our // aApplyTransform is false... but the opposite would be as diff --git a/layout/generic/nsGridContainerFrame.cpp b/layout/generic/nsGridContainerFrame.cpp index 959061e33..f771c9d7c 100644 --- a/layout/generic/nsGridContainerFrame.cpp +++ b/layout/generic/nsGridContainerFrame.cpp @@ -4822,14 +4822,14 @@ nsGridContainerFrame::Tracks::StretchFlexibleTracks( : ri->ComputedMaxISize(); } Maybe<nsTArray<TrackSize>> origSizes; + bool applyMinMax = (minSize != 0 || maxSize != NS_UNCONSTRAINEDSIZE) && + aAvailableSize == NS_UNCONSTRAINEDSIZE; // We iterate twice at most. The 2nd time if the grid size changed after // applying a min/max-size (can only occur if aAvailableSize is indefinite). while (true) { float fr = FindUsedFlexFraction(aState, aGridItems, flexTracks, aFunctions, aAvailableSize); if (fr != 0.0f) { - bool applyMinMax = (minSize != 0 || maxSize != NS_UNCONSTRAINEDSIZE) && - aAvailableSize == NS_UNCONSTRAINEDSIZE; for (uint32_t i : flexTracks) { float flexFactor = aFunctions.MaxSizingFor(i).GetFlexFractionValue(); nscoord flexLength = NSToCoordRound(flexFactor * fr); @@ -4841,36 +4841,36 @@ nsGridContainerFrame::Tracks::StretchFlexibleTracks( base = flexLength; } } - if (applyMinMax && origSizes.isSome()) { - // https://drafts.csswg.org/css-grid/#algo-flex-tracks - // "If using this flex fraction would cause the grid to be smaller than - // the grid container’s min-width/height (or larger than the grid - // container’s max-width/height), then redo this step, treating the free - // space as definite [...]" - nscoord newSize = 0; - for (auto& sz : mSizes) { - newSize += sz.mBase; - } - const auto sumOfGridGaps = SumOfGridGaps(); - newSize += sumOfGridGaps; - if (newSize > maxSize) { - aAvailableSize = maxSize; - } else if (newSize < minSize) { - aAvailableSize = minSize; - } - if (aAvailableSize != NS_UNCONSTRAINEDSIZE) { - // Reset min/max-size to ensure 'applyMinMax' becomes false next time. - minSize = 0; - maxSize = NS_UNCONSTRAINEDSIZE; - aAvailableSize = std::max(0, aAvailableSize - sumOfGridGaps); - // Restart with the original track sizes and definite aAvailableSize. + } + if (applyMinMax) { + applyMinMax = false; + // https://drafts.csswg.org/css-grid/#algo-flex-tracks + // "If using this flex fraction would cause the grid to be smaller than + // the grid container’s min-width/height (or larger than the grid + // container’s max-width/height), then redo this step, treating the free + // space as definite [...]" + nscoord newSize = 0; + for (auto& sz : mSizes) { + newSize += sz.mBase; + } + const auto sumOfGridGaps = SumOfGridGaps(); + newSize += sumOfGridGaps; + if (newSize > maxSize) { + aAvailableSize = maxSize; + } else if (newSize < minSize) { + aAvailableSize = minSize; + } + if (aAvailableSize != NS_UNCONSTRAINEDSIZE) { + aAvailableSize = std::max(0, aAvailableSize - sumOfGridGaps); + // Restart with the original track sizes and definite aAvailableSize. + if (origSizes.isSome()) { mSizes = Move(*origSizes); origSizes.reset(); - if (aAvailableSize == 0) { - break; // zero available size wouldn't change any sizes though... - } - continue; + } // else, no mSizes[].mBase were changed above so it's still correct + if (aAvailableSize == 0) { + break; // zero available size wouldn't change any sizes though... } + continue; } } break; diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 57f5c460c..93eb95099 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -2436,6 +2436,11 @@ public: nsIWidget* GetNearestWidget(nsPoint& aOffset) const; /** + * Whether the content for this frame is disabled, used for event handling. + */ + bool IsContentDisabled() const; + + /** * Get the "type" of the frame. May return nullptr. * * @see nsGkAtoms diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index ff75ab85d..5ccb2d8bf 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -2882,16 +2882,15 @@ nsFrameSelection::UnselectCells(nsIContent *aTableContent, nsTableCellFrame* cellFrame = tableFrame->GetCellFrameAt(curRowIndex, curColIndex); - int32_t origRowIndex, origColIndex; - cellFrame->GetRowIndex(origRowIndex); - cellFrame->GetColIndex(origColIndex); + uint32_t origRowIndex = cellFrame->RowIndex(); + uint32_t origColIndex = cellFrame->ColIndex(); uint32_t actualRowSpan = tableFrame->GetEffectiveRowSpanAt(origRowIndex, origColIndex); uint32_t actualColSpan = tableFrame->GetEffectiveColSpanAt(curRowIndex, curColIndex); - if (origRowIndex <= maxRowIndex && maxRowIndex >= 0 && + if (origRowIndex <= static_cast<uint32_t>(maxRowIndex) && maxRowIndex >= 0 && origRowIndex + actualRowSpan - 1 >= static_cast<uint32_t>(minRowIndex) && - origColIndex <= maxColIndex && maxColIndex >= 0 && + origColIndex <= static_cast<uint32_t>(maxColIndex) && maxColIndex >= 0 && origColIndex + actualColSpan - 1 >= static_cast<uint32_t>(minColIndex)) { mDomSelections[index]->RemoveRange(range); @@ -2925,33 +2924,32 @@ nsFrameSelection::AddCellsToSelection(nsIContent *aTableContent, return NS_ERROR_FAILURE; nsresult result = NS_OK; - int32_t row = aStartRowIndex; + uint32_t row = aStartRowIndex; while(true) { - int32_t col = aStartColumnIndex; + uint32_t col = aStartColumnIndex; while(true) { nsTableCellFrame* cellFrame = tableFrame->GetCellFrameAt(row, col); // Skip cells that are spanned from previous locations or are already selected if (cellFrame) { - int32_t origRow, origCol; - cellFrame->GetRowIndex(origRow); - cellFrame->GetColIndex(origCol); + uint32_t origRow = cellFrame->RowIndex(); + uint32_t origCol = cellFrame->ColIndex(); if (origRow == row && origCol == col && !cellFrame->IsSelected()) { result = SelectCellElement(cellFrame->GetContent()); if (NS_FAILED(result)) return result; } } // Done when we reach end column - if (col == aEndColumnIndex) break; + if (col == static_cast<uint32_t>(aEndColumnIndex)) break; if (aStartColumnIndex < aEndColumnIndex) col ++; else col--; } - if (row == aEndRowIndex) break; + if (row == static_cast<uint32_t>(aEndRowIndex)) break; if (aStartRowIndex < aEndRowIndex) row++; @@ -3846,7 +3844,7 @@ Selection::AddItem(nsRange* aItem, int32_t* aOutIndex, bool aNoStartSelect) if (mUserInitiated) { AutoTArray<RefPtr<nsRange>, 4> rangesToAdd; - *aOutIndex = -1; + *aOutIndex = int32_t(mRanges.Length()) - 1; nsIDocument* doc = GetParentObject(); bool selectEventsEnabled = diff --git a/layout/mathml/nsMathMLmtableFrame.cpp b/layout/mathml/nsMathMLmtableFrame.cpp index fd184e637..4bd7d4395 100644 --- a/layout/mathml/nsMathMLmtableFrame.cpp +++ b/layout/mathml/nsMathMLmtableFrame.cpp @@ -183,10 +183,8 @@ static void ApplyBorderToStyle(const nsMathMLmtdFrame* aFrame, nsStyleBorder& aStyleBorder) { - int32_t rowIndex; - int32_t columnIndex; - aFrame->GetRowIndex(rowIndex); - aFrame->GetColIndex(columnIndex); + uint32_t rowIndex = aFrame->RowIndex(); + uint32_t columnIndex = aFrame->ColIndex(); nscoord borderWidth = aFrame->PresContext()->GetBorderWidthTable()[NS_STYLE_BORDER_WIDTH_THIN]; @@ -201,7 +199,7 @@ ApplyBorderToStyle(const nsMathMLmtdFrame* aFrame, if (rowIndex > 0 && rowLinesList) { // If the row number is greater than the number of provided rowline // values, we simply repeat the last value. - int32_t listLength = rowLinesList->Length(); + uint32_t listLength = rowLinesList->Length(); if (rowIndex < listLength) { aStyleBorder.SetBorderStyle(NS_SIDE_TOP, rowLinesList->ElementAt(rowIndex - 1)); @@ -216,7 +214,7 @@ ApplyBorderToStyle(const nsMathMLmtdFrame* aFrame, if (columnIndex > 0 && columnLinesList) { // If the column number is greater than the number of provided columline // values, we simply repeat the last value. - int32_t listLength = columnLinesList->Length(); + uint32_t listLength = columnLinesList->Length(); if (columnIndex < listLength) { aStyleBorder.SetBorderStyle(NS_SIDE_LEFT, columnLinesList->ElementAt(columnIndex - 1)); @@ -1160,47 +1158,6 @@ nsMathMLmtdFrame::Init(nsIContent* aContent, RemoveStateBits(NS_FRAME_FONT_INFLATION_FLOW_ROOT); } -int32_t -nsMathMLmtdFrame::GetRowSpan() -{ - int32_t rowspan = 1; - - // Don't look at the content's rowspan if we're not an mtd or a pseudo cell. - if (mContent->IsMathMLElement(nsGkAtoms::mtd_) && - !StyleContext()->GetPseudo()) { - nsAutoString value; - mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::rowspan, value); - if (!value.IsEmpty()) { - nsresult error; - rowspan = value.ToInteger(&error); - if (NS_FAILED(error) || rowspan < 0) - rowspan = 1; - rowspan = std::min(rowspan, MAX_ROWSPAN); - } - } - return rowspan; -} - -int32_t -nsMathMLmtdFrame::GetColSpan() -{ - int32_t colspan = 1; - - // Don't look at the content's colspan if we're not an mtd or a pseudo cell. - if (mContent->IsMathMLElement(nsGkAtoms::mtd_) && - !StyleContext()->GetPseudo()) { - nsAutoString value; - mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::columnspan_, value); - if (!value.IsEmpty()) { - nsresult error; - colspan = value.ToInteger(&error); - if (NS_FAILED(error) || colspan <= 0 || colspan > MAX_COLSPAN) - colspan = 1; - } - } - return colspan; -} - nsresult nsMathMLmtdFrame::AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, @@ -1243,12 +1200,11 @@ nsMathMLmtdFrame::GetVerticalAlign() const nsTArray<int8_t>* alignmentList = FindCellProperty(this, RowAlignProperty()); if (alignmentList) { - int32_t rowIndex; - GetRowIndex(rowIndex); + uint32_t rowIndex = RowIndex(); // If the row number is greater than the number of provided rowalign values, // we simply repeat the last value. - if (rowIndex < (int32_t)alignmentList->Length()) + if (rowIndex < alignmentList->Length()) alignment = alignmentList->ElementAt(rowIndex); else alignment = alignmentList->ElementAt(alignmentList->Length() - 1); @@ -1335,12 +1291,11 @@ nsStyleText* nsMathMLmtdInnerFrame::StyleTextForLineLayout() if (alignmentList) { nsMathMLmtdFrame* cellFrame = (nsMathMLmtdFrame*)GetParent(); - int32_t columnIndex; - cellFrame->GetColIndex(columnIndex); + uint32_t columnIndex = cellFrame->ColIndex(); // If the column number is greater than the number of provided columalign // values, we simply repeat the last value. - if (columnIndex < (int32_t)alignmentList->Length()) + if (columnIndex < alignmentList->Length()) alignment = alignmentList->ElementAt(columnIndex); else alignment = alignmentList->ElementAt(alignmentList->Length() - 1); diff --git a/layout/mathml/nsMathMLmtableFrame.h b/layout/mathml/nsMathMLmtableFrame.h index 5cb4fc4a2..725991c17 100644 --- a/layout/mathml/nsMathMLmtableFrame.h +++ b/layout/mathml/nsMathMLmtableFrame.h @@ -257,8 +257,6 @@ public: nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) override; - virtual int32_t GetRowSpan() override; - virtual int32_t GetColSpan() override; virtual bool IsFrameOfType(uint32_t aFlags) const override { return nsTableCellFrame::IsFrameOfType(aFlags & ~(nsIFrame::eMathML)); diff --git a/layout/reftests/css-grid/grid-max-sizing-flex-007-ref.html b/layout/reftests/css-grid/grid-max-sizing-flex-007-ref.html index c5392d32c..b17a1cc02 100644 --- a/layout/reftests/css-grid/grid-max-sizing-flex-007-ref.html +++ b/layout/reftests/css-grid/grid-max-sizing-flex-007-ref.html @@ -107,4 +107,28 @@ <div class="item"></div> </div> +<pre>The first 6 grids should look the same:</pre> +<div class="grid rows" style="grid: 1fr / 30px; height:83px"> + <div class="item"></div> +</div> +<div class="grid rows" style="grid: 10px 1fr / 30px; height:83px"> + <div class="item" style="grid-row:span 2"></div> +</div> +<div class="grid rows" style="grid: 1fr / 30px; height:83px"> + <div class="item"></div> +</div> +<div class="grid rows" style="grid: 1fr 1fr / 30px; height:83px"> + <div class="item" style="grid-row:span 2"><div style="height:90px"></div></div> +</div> +<div class="grid rows" style="grid: 1fr auto / 30px; height:83px"> + <div class="item" style="grid-row:span 2"><div style="height:90px"></div></div> +</div> +<div class="grid rows" style="grid: 10px 1fr / 30px; height:83px"> + <div class="item" style="grid-row:span 2"><div style="height:90px"></div></div> +</div> +<div class="grid rows" style="grid: 1fr 1fr / 30px; grid-row-gap:10px; height:83px"> + <div class="item" style="grid-row:span 2"><div style="height:40px"></div></div> + <div class="item"><div style="height:40px"></div></div> +</div> + </body></html> diff --git a/layout/reftests/css-grid/grid-max-sizing-flex-007.html b/layout/reftests/css-grid/grid-max-sizing-flex-007.html index ac9dcc77c..a2f39e95b 100644 --- a/layout/reftests/css-grid/grid-max-sizing-flex-007.html +++ b/layout/reftests/css-grid/grid-max-sizing-flex-007.html @@ -105,4 +105,28 @@ <div class="item"></div> </div> +<pre>The first 6 grids should look the same:</pre> +<div class="grid rows" style="grid: 1fr / 30px; min-height:83px"> + <div class="item"></div> +</div> +<div class="grid rows" style="grid: 10px 1fr / 30px; min-height:83px"> + <div class="item" style="grid-row:span 2"></div> +</div> +<div class="grid rows" style="grid: 1fr / 30px; max-height:30px; min-height:83px"> + <div class="item"></div> +</div> +<div class="grid rows" style="grid: 1fr 1fr / 30px; max-height:83px"> + <div class="item" style="grid-row:span 2"><div style="height:90px"></div></div> +</div> +<div class="grid rows" style="grid: 1fr auto / 30px; max-height:83px"> + <div class="item" style="grid-row:span 2"><div style="height:90px"></div></div> +</div> +<div class="grid rows" style="grid: 10px 1fr / 30px; max-height:83px"> + <div class="item" style="grid-row:span 2"><div style="height:90px"></div></div> +</div> +<div class="grid rows" style="grid: 1fr 1fr / 30px; grid-row-gap:10px; max-height:83px"> + <div class="item" style="grid-row:span 2"><div style="height:40px"></div></div> + <div class="item"><div style="height:40px"></div></div> +</div> + </body></html> diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index a8309314f..556e35406 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -1056,6 +1056,7 @@ protected: bool ParseOneFamily(nsAString& aFamily, bool& aOneKeyword, bool& aQuoted); bool ParseFamily(nsCSSValue& aValue); bool ParseFontFeatureSettings(nsCSSValue& aValue); + bool ParseFontVariationSettings(nsCSSValue& aValue); bool ParseFontSrc(nsCSSValue& aValue); bool ParseFontSrcFormat(InfallibleTArray<nsCSSValue>& values); bool ParseFontRanges(nsCSSValue& aValue); @@ -12092,6 +12093,8 @@ CSSParserImpl::ParseSingleValuePropertyByFunction(nsCSSValue& aValue, return ParseFontVariantNumeric(aValue); case eCSSProperty_font_feature_settings: return ParseFontFeatureSettings(aValue); + case eCSSProperty_font_variation_settings: + return ParseFontVariationSettings(aValue); case eCSSProperty_font_weight: return ParseFontWeight(aValue); case eCSSProperty_image_orientation: @@ -15315,6 +15318,19 @@ CSSParserImpl::ParseFontFeatureSettings(nsCSSValue& aValue) return true; } +bool
+CSSParserImpl::ParseFontVariationSettings(nsCSSValue& aValue)
+{
+ // TODO: Actually implement this.
+
+ // This stub is here because websites insist on considering this
+ // very hardware-dependent and O.S.-variable low-level font-control
+ // as a "critical feature" which it isn't as there is 0 guarantee
+ // that font variation settings are supported or honored by any
+ // operating system used by the client.
+ return true;
+} + bool CSSParserImpl::ParseListStyle() { diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index 07db6d3dd..411f982a4 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -2037,6 +2037,20 @@ CSS_PROP_FONT( CSS_PROP_NO_OFFSET, eStyleAnimType_Discrete) CSS_PROP_FONT( + font-variation-settings, + font_variation_settings, + FontVariationSettings, + CSS_PROPERTY_PARSE_VALUE | + CSS_PROPERTY_VALUE_PARSER_FUNCTION | + CSS_PROPERTY_VALUE_LIST_USES_COMMAS | + CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE | + CSS_PROPERTY_APPLIES_TO_PLACEHOLDER, + "layout.css.font-variations.stub", + 0, + nullptr, + CSS_PROP_NO_OFFSET, + eStyleAnimType_Discrete) +CSS_PROP_FONT( font-weight, font_weight, FontWeight, diff --git a/layout/style/nsCSSProps.cpp b/layout/style/nsCSSProps.cpp index ac2978c27..289a16ecd 100644 --- a/layout/style/nsCSSProps.cpp +++ b/layout/style/nsCSSProps.cpp @@ -2189,8 +2189,6 @@ const KTableEntry nsCSSProps::kUserFocusKTable[] = { const KTableEntry nsCSSProps::kUserInputKTable[] = { { eCSSKeyword_none, StyleUserInput::None }, - { eCSSKeyword_enabled, StyleUserInput::Enabled }, - { eCSSKeyword_disabled, StyleUserInput::Disabled }, { eCSSKeyword_auto, StyleUserInput::Auto }, { eCSSKeyword_UNKNOWN, -1 } }; diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 647f7f6dc..910c1de8a 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -674,9 +674,9 @@ nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush) mPresShell->GetPresContext()->GetRestyleGeneration(); if (mStyleContext) { - // We can't rely on the undisplayed restyle generation if mElement is
- // out-of-document, since that generation is not incremented for DOM changes
- // on out-of-document elements.
+ // We can't rely on the undisplayed restyle generation if mElement is + // out-of-document, since that generation is not incremented for DOM changes + // on out-of-document elements. if (mStyleContextGeneration == currentGeneration && mElement->IsInComposedDoc()) { // Our cached style context is still valid. @@ -1620,6 +1620,16 @@ nsComputedDOMStyle::DoGetFontFeatureSettings() } already_AddRefed<CSSValue> +nsComputedDOMStyle::DoGetFontVariationSettings() +{ + // TODO: This is still a stub, always returning "normal" + RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue; + + val->SetIdent(eCSSKeyword_normal); + return val.forget(); +} + +already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetFontKerning() { RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue; diff --git a/layout/style/nsComputedDOMStyle.h b/layout/style/nsComputedDOMStyle.h index 7fbf49afe..e94d8dbf6 100644 --- a/layout/style/nsComputedDOMStyle.h +++ b/layout/style/nsComputedDOMStyle.h @@ -251,6 +251,7 @@ private: already_AddRefed<CSSValue> DoGetColor(); already_AddRefed<CSSValue> DoGetFontFamily(); already_AddRefed<CSSValue> DoGetFontFeatureSettings(); + already_AddRefed<CSSValue> DoGetFontVariationSettings(); already_AddRefed<CSSValue> DoGetFontKerning(); already_AddRefed<CSSValue> DoGetFontLanguageOverride(); already_AddRefed<CSSValue> DoGetFontSize(); diff --git a/layout/style/nsComputedDOMStylePropertyList.h b/layout/style/nsComputedDOMStylePropertyList.h index 825976b58..557281810 100644 --- a/layout/style/nsComputedDOMStylePropertyList.h +++ b/layout/style/nsComputedDOMStylePropertyList.h @@ -144,6 +144,7 @@ COMPUTED_STYLE_PROP(font_variant_east_asian, FontVariantEastAsian) COMPUTED_STYLE_PROP(font_variant_ligatures, FontVariantLigatures) COMPUTED_STYLE_PROP(font_variant_numeric, FontVariantNumeric) COMPUTED_STYLE_PROP(font_variant_position, FontVariantPosition) +COMPUTED_STYLE_PROP(font_variation_settings, FontVariationSettings) COMPUTED_STYLE_PROP(font_weight, FontWeight) COMPUTED_STYLE_PROP(grid_auto_columns, GridAutoColumns) COMPUTED_STYLE_PROP(grid_auto_flow, GridAutoFlow) diff --git a/layout/style/nsStyleConsts.h b/layout/style/nsStyleConsts.h index 6d207aec9..5412eed26 100644 --- a/layout/style/nsStyleConsts.h +++ b/layout/style/nsStyleConsts.h @@ -241,8 +241,6 @@ enum class StyleUserSelect : uint8_t { // user-input enum class StyleUserInput : uint8_t { None, - Enabled, - Disabled, Auto, }; diff --git a/layout/style/nsTransitionManager.cpp b/layout/style/nsTransitionManager.cpp index 118702e8f..a317f9943 100644 --- a/layout/style/nsTransitionManager.cpp +++ b/layout/style/nsTransitionManager.cpp @@ -44,6 +44,7 @@ using mozilla::dom::CSSTransition; using mozilla::dom::KeyframeEffectReadOnly; using namespace mozilla; +using namespace mozilla::dom; using namespace mozilla::css; namespace { diff --git a/layout/style/res/forms.css b/layout/style/res/forms.css index e7566e183..95025221d 100644 --- a/layout/style/res/forms.css +++ b/layout/style/res/forms.css @@ -425,7 +425,6 @@ optgroup:disabled, select:disabled:disabled /* Need the pseudo-class twice to have the specificity be at least the same as select[size][multiple] above */ { - -moz-user-input: disabled; color: GrayText; background-color: ThreeDLightShadow; cursor: inherit; diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index c75f7b498..3486d15d0 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -2203,7 +2203,7 @@ var gCSSProperties = { inherited: true, type: CSS_TYPE_LONGHAND, initial_values: [ "auto" ], - other_values: [ "none", "enabled", "disabled" ], + other_values: [ "none" ], invalid_values: [] }, "-moz-user-modify": { diff --git a/layout/tables/celldata.h b/layout/tables/celldata.h index b744b5175..ac7be58d7 100644 --- a/layout/tables/celldata.h +++ b/layout/tables/celldata.h @@ -6,6 +6,7 @@ #define CellData_h__ #include "nsISupports.h" +#include "nsITableCellLayout.h" // for MAX_COLSPAN / MAX_ROWSPAN #include "nsCoord.h" #include "mozilla/gfx/Types.h" #include "mozilla/WritingModes.h" @@ -15,11 +16,6 @@ class nsTableCellFrame; class nsCellMap; class BCCellData; - -#define MAX_ROWSPAN 65534 // the cellmap can not handle more. -#define MAX_COLSPAN 1000 // limit as IE and opera do. If this ever changes, - // change COL_SPAN_OFFSET/COL_SPAN_SHIFT accordingly. - /** * Data stored by nsCellMap to rationalize rowspan and colspan cells. */ diff --git a/layout/tables/nsCellMap.cpp b/layout/tables/nsCellMap.cpp index bdd12cf70..4852a4bdd 100644 --- a/layout/tables/nsCellMap.cpp +++ b/layout/tables/nsCellMap.cpp @@ -2431,9 +2431,8 @@ void nsCellMap::Dump(bool aIsBorderCollapse) const if (cd) { if (cd->IsOrig()) { nsTableCellFrame* cellFrame = cd->GetCellFrame(); - int32_t cellFrameColIndex; - cellFrame->GetColIndex(cellFrameColIndex); - printf("C%d,%d=%p(%d) ", rIndex, colIndex, (void*)cellFrame, + uint32_t cellFrameColIndex = cellFrame->ColIndex(); + printf("C%d,%d=%p(%u) ", rIndex, colIndex, (void*)cellFrame, cellFrameColIndex); cellCount++; } @@ -2520,8 +2519,7 @@ nsCellMap::GetCellInfoAt(const nsTableCellMap& aMap, cellFrame = GetCellFrame(aRowX, aColX, *data, true); } if (cellFrame && aColSpan) { - int32_t initialColIndex; - cellFrame->GetColIndex(initialColIndex); + uint32_t initialColIndex = cellFrame->ColIndex(); *aColSpan = GetEffectiveColSpan(aMap, aRowX, initialColIndex); } } diff --git a/layout/tables/nsITableCellLayout.h b/layout/tables/nsITableCellLayout.h index e761d76be..fdf693b06 100644 --- a/layout/tables/nsITableCellLayout.h +++ b/layout/tables/nsITableCellLayout.h @@ -7,9 +7,14 @@ #include "nsQueryFrame.h" +#define MAX_ROWSPAN 65534 // the cellmap can not handle more. +#define MAX_COLSPAN 1000 // limit as IE and opera do. If this ever changes, +// change COL_SPAN_OFFSET/COL_SPAN_SHIFT accordingly. + /** * nsITableCellLayout * interface for layout objects that act like table cells. + * XXX: This interface should really go away... * * @author sclark */ @@ -22,11 +27,6 @@ public: /** return the mapped cell's row and column indexes (starting at 0 for each) */ NS_IMETHOD GetCellIndexes(int32_t &aRowIndex, int32_t &aColIndex)=0; - /** return the mapped cell's row index (starting at 0 for the first row) */ - virtual nsresult GetRowIndex(int32_t &aRowIndex) const = 0; - - /** return the mapped cell's column index (starting at 0 for the first column) */ - virtual nsresult GetColIndex(int32_t &aColIndex) const = 0; }; #endif diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp index ec9458f76..8b811df1e 100644 --- a/layout/tables/nsTableCellFrame.cpp +++ b/layout/tables/nsTableCellFrame.cpp @@ -59,20 +59,6 @@ nsTableCellFrame::~nsTableCellFrame() NS_IMPL_FRAMEARENA_HELPERS(nsTableCellFrame) -nsTableCellFrame* -nsTableCellFrame::GetNextCell() const -{ - nsIFrame* childFrame = GetNextSibling(); - while (childFrame) { - nsTableCellFrame *cellFrame = do_QueryFrame(childFrame); - if (cellFrame) { - return cellFrame; - } - childFrame = childFrame->GetNextSibling(); - } - return nullptr; -} - void nsTableCellFrame::Init(nsIContent* aContent, nsContainerFrame* aParent, @@ -88,8 +74,7 @@ nsTableCellFrame::Init(nsIContent* aContent, if (aPrevInFlow) { // Set the column index nsTableCellFrame* cellFrame = (nsTableCellFrame*)aPrevInFlow; - int32_t colIndex; - cellFrame->GetColIndex(colIndex); + uint32_t colIndex = cellFrame->ColIndex(); SetColIndex(colIndex); } } @@ -183,34 +168,6 @@ nsTableCellFrame::NeedsToObserve(const ReflowInput& aReflowInput) } nsresult -nsTableCellFrame::GetRowIndex(int32_t &aRowIndex) const -{ - nsresult result; - nsTableRowFrame* row = static_cast<nsTableRowFrame*>(GetParent()); - if (row) { - aRowIndex = row->GetRowIndex(); - result = NS_OK; - } - else { - aRowIndex = 0; - result = NS_ERROR_NOT_INITIALIZED; - } - return result; -} - -nsresult -nsTableCellFrame::GetColIndex(int32_t &aColIndex) const -{ - if (GetPrevInFlow()) { - return static_cast<nsTableCellFrame*>(FirstInFlow())->GetColIndex(aColIndex); - } - else { - aColIndex = mColIndex; - return NS_OK; - } -} - -nsresult nsTableCellFrame::AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, int32_t aModType) @@ -238,13 +195,13 @@ nsTableCellFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext) nsTableFrame* tableFrame = GetTableFrame(); if (tableFrame->IsBorderCollapse() && tableFrame->BCRecalcNeeded(aOldStyleContext, StyleContext())) { - int32_t colIndex, rowIndex; - GetColIndex(colIndex); - GetRowIndex(rowIndex); + uint32_t colIndex = ColIndex(); + uint32_t rowIndex = RowIndex(); // row span needs to be clamped as we do not create rows in the cellmap // which do not have cells originating in them TableArea damageArea(colIndex, rowIndex, GetColSpan(), - std::min(GetRowSpan(), tableFrame->GetRowCount() - rowIndex)); + std::min(static_cast<uint32_t>(GetRowSpan()), + tableFrame->GetRowCount() - rowIndex)); tableFrame->AddBCDamageArea(damageArea); } } @@ -464,19 +421,40 @@ PaintTableCellSelection(nsIFrame* aFrame, DrawTarget* aDrawTarget, aPt); } +bool +nsTableCellFrame::ShouldPaintBordersAndBackgrounds() const +{ + // If we're not visible, we don't paint. + if (!StyleVisibility()->IsVisible()) { + return false; + } + + // Consider 'empty-cells', but only in separated borders mode. + if (!GetContentEmpty()) { + return true; + } + + nsTableFrame* tableFrame = GetTableFrame(); + if (tableFrame->IsBorderCollapse()) { + return true; + } + + return StyleTableBorder()->mEmptyCells == NS_STYLE_TABLE_EMPTY_CELLS_SHOW; +} + +bool +nsTableCellFrame::ShouldPaintBackground(nsDisplayListBuilder* aBuilder) +{ + return ShouldPaintBordersAndBackgrounds() && IsVisibleInSelection(aBuilder); +} + void nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) { DO_GLOBAL_REFLOW_COUNT_DSP("nsTableCellFrame"); - nsTableFrame* tableFrame = GetTableFrame(); - int32_t emptyCellStyle = GetContentEmpty() && !tableFrame->IsBorderCollapse() ? - StyleTableBorder()->mEmptyCells - : NS_STYLE_TABLE_EMPTY_CELLS_SHOW; - // take account of 'empty-cells' - if (StyleVisibility()->IsVisible() && - (NS_STYLE_TABLE_EMPTY_CELLS_HIDE != emptyCellStyle)) { + if (ShouldPaintBordersAndBackgrounds()) { // display outset box-shadows if we need to. bool hasBoxShadow = !!StyleEffects()->mBoxShadow; if (hasBoxShadow) { @@ -501,7 +479,7 @@ nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, } // display borders if we need to - ProcessBorders(tableFrame, aBuilder, aLists); + ProcessBorders(GetTableFrame(), aBuilder, aLists); // and display the selection border if we need to if (IsSelected()) { @@ -704,16 +682,18 @@ nsTableCellFrame::GetCellBaseline() const borderPadding; } -int32_t nsTableCellFrame::GetRowSpan() +int32_t +nsTableCellFrame::GetRowSpan() { int32_t rowSpan=1; - nsGenericHTMLElement *hc = nsGenericHTMLElement::FromContent(mContent); // Don't look at the content's rowspan if we're a pseudo cell - if (hc && !StyleContext()->GetPseudo()) { - const nsAttrValue* attr = hc->GetParsedAttr(nsGkAtoms::rowspan); + if (!StyleContext()->GetPseudo()) { + dom::Element* elem = mContent->AsElement(); + const nsAttrValue* attr = elem->GetParsedAttr(nsGkAtoms::rowspan); // Note that we don't need to check the tag name, because only table cells - // and table headers parse the "rowspan" attribute into an integer. + // (including MathML <mtd>) and table headers parse the "rowspan" attribute + // into an integer. if (attr && attr->Type() == nsAttrValue::eInteger) { rowSpan = attr->GetIntegerValue(); } @@ -721,16 +701,20 @@ int32_t nsTableCellFrame::GetRowSpan() return rowSpan; } -int32_t nsTableCellFrame::GetColSpan() +int32_t +nsTableCellFrame::GetColSpan() { int32_t colSpan=1; - nsGenericHTMLElement *hc = nsGenericHTMLElement::FromContent(mContent); // Don't look at the content's colspan if we're a pseudo cell - if (hc && !StyleContext()->GetPseudo()) { - const nsAttrValue* attr = hc->GetParsedAttr(nsGkAtoms::colspan); + if (!StyleContext()->GetPseudo()) { + dom::Element* elem = mContent->AsElement(); + const nsAttrValue* attr = elem->GetParsedAttr( + MOZ_UNLIKELY(elem->IsMathMLElement()) ? nsGkAtoms::columnspan_ + : nsGkAtoms::colspan); // Note that we don't need to check the tag name, because only table cells - // and table headers parse the "colspan" attribute into an integer. + // (including MathML <mtd>) and table headers parse the "colspan" attribute + // into an integer. if (attr && attr->Type() == nsAttrValue::eInteger) { colSpan = attr->GetIntegerValue(); } @@ -807,14 +791,13 @@ CalcUnpaginatedBSize(nsTableCellFrame& aCellFrame, nsTableRowGroupFrame* firstRGInFlow = static_cast<nsTableRowGroupFrame*>(row->GetParent()); - int32_t rowIndex; - firstCellInFlow->GetRowIndex(rowIndex); + uint32_t rowIndex = firstCellInFlow->RowIndex(); int32_t rowSpan = aTableFrame.GetEffectiveRowSpan(*firstCellInFlow); nscoord computedBSize = firstTableInFlow->GetRowSpacing(rowIndex, rowIndex + rowSpan - 1); computedBSize -= aBlockDirBorderPadding; - int32_t rowX; + uint32_t rowX; for (row = firstRGInFlow->GetFirstRow(), rowX = 0; row; row = row->GetNextRow(), rowX++) { if (rowX > rowIndex + rowSpan - 1) { break; @@ -1029,12 +1012,7 @@ nsTableCellFrame::AccessibleType() NS_IMETHODIMP nsTableCellFrame::GetCellIndexes(int32_t &aRowIndex, int32_t &aColIndex) { - nsresult res = GetRowIndex(aRowIndex); - if (NS_FAILED(res)) - { - aColIndex = 0; - return res; - } + aRowIndex = RowIndex(); aColIndex = mColIndex; return NS_OK; } diff --git a/layout/tables/nsTableCellFrame.h b/layout/tables/nsTableCellFrame.h index 5f87c5f6d..f626a45b0 100644 --- a/layout/tables/nsTableCellFrame.h +++ b/layout/tables/nsTableCellFrame.h @@ -165,11 +165,11 @@ public: /** * return the cell's specified row span. this is what was specified in the - * content model or in the style info, and is always >= 1. + * content model or in the style info, and is always >= 0. * to get the effective row span (the actual value that applies), use GetEffectiveRowSpan() * @see nsTableFrame::GetEffectiveRowSpan() */ - virtual int32_t GetRowSpan(); + int32_t GetRowSpan(); // there is no set row index because row index depends on the cell's parent row only @@ -183,7 +183,10 @@ public: NS_IMETHOD GetCellIndexes(int32_t &aRowIndex, int32_t &aColIndex) override; /** return the mapped cell's row index (starting at 0 for the first row) */ - virtual nsresult GetRowIndex(int32_t &aRowIndex) const override; + uint32_t RowIndex() const + { + return static_cast<nsTableRowFrame*>(GetParent())->GetRowIndex(); + } /** * return the cell's specified col span. this is what was specified in the @@ -191,10 +194,19 @@ public: * to get the effective col span (the actual value that applies), use GetEffectiveColSpan() * @see nsTableFrame::GetEffectiveColSpan() */ - virtual int32_t GetColSpan(); + int32_t GetColSpan(); /** return the cell's column index (starting at 0 for the first column) */ - virtual nsresult GetColIndex(int32_t &aColIndex) const override; + uint32_t ColIndex() const + { + // NOTE: We copy this from previous continuations, and we don't ever have + // dynamic updates when tables split, so our mColIndex always matches our + // first continuation's. + MOZ_ASSERT(static_cast<nsTableCellFrame*>(FirstContinuation())->mColIndex == + mColIndex, + "mColIndex out of sync with first continuation"); + return mColIndex; + } void SetColIndex(int32_t aColIndex); /** return the available isize given to this frame during its last reflow */ @@ -209,13 +221,23 @@ public: /** set the desired size returned by this frame during its last reflow */ inline void SetDesiredSize(const ReflowOutput & aDesiredSize); - bool GetContentEmpty(); + bool GetContentEmpty() const; void SetContentEmpty(bool aContentEmpty); bool HasPctOverBSize(); void SetHasPctOverBSize(bool aValue); - nsTableCellFrame* GetNextCell() const; + nsTableCellFrame* GetNextCell() const + { + nsIFrame* sibling = GetNextSibling(); +#ifdef DEBUG + if (sibling) { + nsTableCellFrame* cellFrame = do_QueryFrame(sibling); + MOZ_ASSERT(cellFrame, "How do we have a non-cell sibling?"); + } +#endif // DEBUG + return static_cast<nsTableCellFrame*>(sibling); + } virtual LogicalMargin GetBorderWidth(WritingMode aWM) const; @@ -237,6 +259,10 @@ public: virtual void InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey = 0) override; virtual void InvalidateFrameForRemoval() override { InvalidateFrameSubtree(); } + bool ShouldPaintBordersAndBackgrounds() const; + + bool ShouldPaintBackground(nsDisplayListBuilder* aBuilder); + protected: virtual LogicalSides GetLogicalSkipSides(const ReflowInput* aReflowInput = nullptr) const override; @@ -273,7 +299,7 @@ inline void nsTableCellFrame::SetDesiredSize(const ReflowOutput & aDesiredSize) mDesiredSize = aDesiredSize.Size(wm).ConvertTo(GetWritingMode(), wm); } -inline bool nsTableCellFrame::GetContentEmpty() +inline bool nsTableCellFrame::GetContentEmpty() const { return HasAnyStateBits(NS_TABLE_CELL_CONTENT_EMPTY); } @@ -350,4 +376,17 @@ private: BCPixelSize mIStartBorder; }; +// Implemented here because that's a sane-ish way to make the includes work out. +inline nsTableCellFrame* nsTableRowFrame::GetFirstCell() const +{ + nsIFrame* firstChild = mFrames.FirstChild(); +#ifdef DEBUG + if (firstChild) { + nsTableCellFrame* cellFrame = do_QueryFrame(firstChild); + MOZ_ASSERT(cellFrame, "How do we have a non-cell sibling?"); + } +#endif // DEBUG + return static_cast<nsTableCellFrame*>(firstChild); +} + #endif diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index 890d050fd..e5a48139a 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -368,9 +368,8 @@ nsTableFrame::AttributeChangedFor(nsIFrame* aFrame, nsTableCellMap* cellMap = GetCellMap(); if (cellMap) { // for now just remove the cell from the map and reinsert it - int32_t rowIndex, colIndex; - cellFrame->GetRowIndex(rowIndex); - cellFrame->GetColIndex(colIndex); + uint32_t rowIndex = cellFrame->RowIndex(); + uint32_t colIndex = cellFrame->ColIndex(); RemoveCell(cellFrame, rowIndex); AutoTArray<nsTableCellFrame*, 1> cells; cells.AppendElement(cellFrame); @@ -447,9 +446,7 @@ nsTableFrame::GetEffectiveRowSpan(int32_t aRowIndex, nsTableCellMap* cellMap = GetCellMap(); NS_PRECONDITION (nullptr != cellMap, "bad call, cellMap not yet allocated."); - int32_t colIndex; - aCell.GetColIndex(colIndex); - return cellMap->GetEffectiveRowSpan(aRowIndex, colIndex); + return cellMap->GetEffectiveRowSpan(aRowIndex, aCell.ColIndex()); } int32_t @@ -458,9 +455,8 @@ nsTableFrame::GetEffectiveRowSpan(const nsTableCellFrame& aCell, { nsTableCellMap* tableCellMap = GetCellMap(); if (!tableCellMap) ABORT1(1); - int32_t colIndex, rowIndex; - aCell.GetColIndex(colIndex); - aCell.GetRowIndex(rowIndex); + uint32_t colIndex = aCell.ColIndex(); + uint32_t rowIndex = aCell.RowIndex(); if (aCellMap) return aCellMap->GetRowSpan(rowIndex, colIndex, true); @@ -474,9 +470,8 @@ nsTableFrame::GetEffectiveColSpan(const nsTableCellFrame& aCell, { nsTableCellMap* tableCellMap = GetCellMap(); if (!tableCellMap) ABORT1(1); - int32_t colIndex, rowIndex; - aCell.GetColIndex(colIndex); - aCell.GetRowIndex(rowIndex); + uint32_t colIndex = aCell.ColIndex(); + uint32_t rowIndex = aCell.RowIndex(); if (aCellMap) return aCellMap->GetEffectiveColSpan(*tableCellMap, rowIndex, colIndex); @@ -1192,11 +1187,19 @@ PaintRowBackground(nsTableRowFrame* aRow, nsIFrame* aFrame, nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists, + const nsRect& aDirtyRect, const nsPoint& aOffset = nsPoint()) { // Compute background rect by iterating over all cell frames. for (nsTableCellFrame* cell = aRow->GetFirstCell(); cell; cell = cell->GetNextCell()) { + if (!cell->ShouldPaintBackground(aBuilder)) { + continue; + } + auto cellRect = cell->GetRectRelativeToSelf() + cell->GetNormalPosition() + aOffset; + if (!aDirtyRect.Intersects(cellRect)) { + continue; + } nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect, aLists.BorderBackground(), true, nullptr, @@ -1209,10 +1212,14 @@ static void PaintRowGroupBackground(nsTableRowGroupFrame* aRowGroup, nsIFrame* aFrame, nsDisplayListBuilder* aBuilder, - const nsDisplayListSet& aLists) + const nsDisplayListSet& aLists, + const nsRect& aDirtyRect) { for (nsTableRowFrame* row = aRowGroup->GetFirstRow(); row; row = row->GetNextRow()) { - PaintRowBackground(row, aFrame, aBuilder, aLists, row->GetNormalPosition()); + if (!aDirtyRect.Intersects(nsRect(row->GetNormalPosition(), row->GetSize()))) { + continue; + } + PaintRowBackground(row, aFrame, aBuilder, aLists, aDirtyRect, row->GetNormalPosition()); } } @@ -1221,23 +1228,112 @@ PaintRowGroupBackgroundByColIdx(nsTableRowGroupFrame* aRowGroup, nsIFrame* aFrame, nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists, - const nsTArray<int32_t>& aColIdx, + const nsRect& aDirtyRect, + const nsTArray<uint32_t>& aColIdx, const nsPoint& aOffset) { + MOZ_DIAGNOSTIC_ASSERT(!aColIdx.IsEmpty(), + "Must be painting backgrounds for something"); for (nsTableRowFrame* row = aRowGroup->GetFirstRow(); row; row = row->GetNextRow()) { + auto rowPos = row->GetNormalPosition() + aOffset; + if (!aDirtyRect.Intersects(nsRect(rowPos, row->GetSize()))) { + continue; + } for (nsTableCellFrame* cell = row->GetFirstCell(); cell; cell = cell->GetNextCell()) { - int32_t curColIdx; - cell->GetColIndex(curColIdx); - if (aColIdx.Contains(curColIdx)) { - auto cellRect = cell->GetRectRelativeToSelf() + cell->GetNormalPosition() + row->GetNormalPosition() + aOffset; + + uint32_t curColIdx = cell->ColIndex(); + if (!aColIdx.Contains(curColIdx)) { + if (curColIdx > aColIdx.LastElement()) { + // We can just stop looking at this row. + break; + } + continue; + } + + if (!cell->ShouldPaintBackground(aBuilder)) { + continue; + } + + auto cellPos = cell->GetNormalPosition() + rowPos; + auto cellRect = nsRect(cellPos, cell->GetSize()); + if (!aDirtyRect.Intersects(cellRect)) { + continue; + } nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect, aLists.BorderBackground(), true, nullptr, aFrame->GetRectRelativeToSelf(), cell); + } + } +} + +static inline bool FrameHasBorder(nsIFrame* f) +{ + if (!f->StyleVisibility()->IsVisible()) { + return false; + } + + if (f->StyleBorder()->HasBorder()) { + return true; + } + + return false; +} + +void nsTableFrame::CalcHasBCBorders() +{ + if (!IsBorderCollapse()) { + SetHasBCBorders(false); + return; + } + + if (FrameHasBorder(this)) { + SetHasBCBorders(true); + return; + } + + // Check col and col group has borders. + for (nsIFrame* f : this->GetChildList(kColGroupList)) { + if (FrameHasBorder(f)) { + SetHasBCBorders(true); + return; + } + + nsTableColGroupFrame *colGroup = static_cast<nsTableColGroupFrame*>(f); + for (nsTableColFrame* col = colGroup->GetFirstColumn(); col; col = col->GetNextCol()) { + if (FrameHasBorder(col)) { + SetHasBCBorders(true); + return; } } } + + // check row group, row and cell has borders. + RowGroupArray rowGroups; + OrderRowGroups(rowGroups); + for (nsTableRowGroupFrame* rowGroup : rowGroups) { + if (FrameHasBorder(rowGroup)) { + SetHasBCBorders(true); + return; + } + + for (nsTableRowFrame* row = rowGroup->GetFirstRow(); row; row = row->GetNextRow()) { + if (FrameHasBorder(row)) { + SetHasBCBorders(true); + return; + } + + for (nsTableCellFrame* cell = row->GetFirstCell(); cell; cell = cell->GetNextCell()) { + if (FrameHasBorder(cell)) { + SetHasBCBorders(true); + return; + } + } + } + } + + SetHasBCBorders(false); } /* static */ void @@ -1247,66 +1343,94 @@ nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists, DisplayGenericTablePartTraversal aTraversal) { - if (aFrame->IsVisibleForPainting(aBuilder)) { + bool isVisible = aFrame->IsVisibleForPainting(aBuilder); + bool isTable = (aFrame->GetType() == nsGkAtoms::tableFrame); + + if (isVisible || !isTable) { nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem(); // currentItem may be null, when none of the table parts have a // background or border if (currentItem) { currentItem->UpdateForFrameBackground(aFrame); } + } + + if (isVisible) { + // XXX: should box-shadow for rows/rowgroups/columns/colgroups get painted + // just because we're visible? Or should it depend on the cell visibility + // when we're not the whole table? // Paint the outset box-shadows for the table frames - bool hasBoxShadow = aFrame->StyleEffects()->mBoxShadow != nullptr; - if (hasBoxShadow) { + if (aFrame->StyleEffects()->mBoxShadow) { aLists.BorderBackground()->AppendNewToTop( new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, aFrame)); } + } - if (aFrame->GetType() == nsGkAtoms::tableRowGroupFrame) { - nsTableRowGroupFrame* rowGroup = static_cast<nsTableRowGroupFrame*>(aFrame); - PaintRowGroupBackground(rowGroup, aFrame, aBuilder, aLists); - } else if (aFrame->GetType() == nsGkAtoms::tableRowFrame) { - nsTableRowFrame* row = static_cast<nsTableRowFrame*>(aFrame); - PaintRowBackground(row, aFrame, aBuilder, aLists); - } else if (aFrame->GetType() == nsGkAtoms::tableColGroupFrame) { - // Compute background rect by iterating all cell frame. - nsTableColGroupFrame* colGroup = static_cast<nsTableColGroupFrame*>(aFrame); - // Collecting column index. - AutoTArray<int32_t, 1> colIdx; - for (nsTableColFrame* col = colGroup->GetFirstColumn(); col; col = col->GetNextCol()) { - colIdx.AppendElement(col->GetColIndex()); - } + // Background visibility for rows, rowgroups, columns, colgroups depends on + // the visibility of the _cell_, not of the row/col(group). + // See spec at https://drafts.csswg.org/css-tables-3/#drawing-cell-backgrounds + if (aFrame->GetType() == nsGkAtoms::tableRowGroupFrame) { + nsTableRowGroupFrame* rowGroup = static_cast<nsTableRowGroupFrame*>(aFrame); + PaintRowGroupBackground(rowGroup, aFrame, aBuilder, aLists, aDirtyRect); + } else if (aFrame->GetType() == nsGkAtoms::tableRowFrame) { + nsTableRowFrame* row = static_cast<nsTableRowFrame*>(aFrame); + PaintRowBackground(row, aFrame, aBuilder, aLists, aDirtyRect); + } else if (aFrame->GetType() == nsGkAtoms::tableColGroupFrame) { + // Compute background rect by iterating all cell frame. + nsTableColGroupFrame* colGroup = static_cast<nsTableColGroupFrame*>(aFrame); + // Collecting column index. + AutoTArray<uint32_t, 1> colIdx; + for (nsTableColFrame* col = colGroup->GetFirstColumn(); col; col = col->GetNextCol()) { + MOZ_ASSERT(colIdx.IsEmpty() || + static_cast<uint32_t>(col->GetColIndex()) > colIdx.LastElement()); + colIdx.AppendElement(col->GetColIndex()); + } + if (!colIdx.IsEmpty()) { + // We have some actual cells that live inside this rowgroup. nsTableFrame* table = colGroup->GetTableFrame(); RowGroupArray rowGroups; table->OrderRowGroups(rowGroups); for (nsTableRowGroupFrame* rowGroup : rowGroups) { auto offset = rowGroup->GetNormalPosition() - colGroup->GetNormalPosition(); - PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, colIdx, offset); + if (!aDirtyRect.Intersects(nsRect(offset, rowGroup->GetSize()))) { + continue; + } + PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, aDirtyRect, colIdx, offset); } - } else if (aFrame->GetType() == nsGkAtoms::tableColFrame) { - // Compute background rect by iterating all cell frame. - nsTableColFrame* col = static_cast<nsTableColFrame*>(aFrame); - AutoTArray<int32_t, 1> colIdx; - colIdx.AppendElement(col->GetColIndex()); + } + } else if (aFrame->GetType() == nsGkAtoms::tableColFrame) { + // Compute background rect by iterating all cell frame. + nsTableColFrame* col = static_cast<nsTableColFrame*>(aFrame); + AutoTArray<uint32_t, 1> colIdx; + colIdx.AppendElement(col->GetColIndex()); - nsTableFrame* table = col->GetTableFrame(); - RowGroupArray rowGroups; - table->OrderRowGroups(rowGroups); - for (nsTableRowGroupFrame* rowGroup : rowGroups) { - auto offset = rowGroup->GetNormalPosition() - - col->GetNormalPosition() - - col->GetTableColGroupFrame()->GetNormalPosition(); - PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, colIdx, offset); + nsTableFrame* table = col->GetTableFrame(); + RowGroupArray rowGroups; + table->OrderRowGroups(rowGroups); + for (nsTableRowGroupFrame* rowGroup : rowGroups) { + auto offset = rowGroup->GetNormalPosition() - + col->GetNormalPosition() - + col->GetTableColGroupFrame()->GetNormalPosition(); + if (!aDirtyRect.Intersects(nsRect(offset, rowGroup->GetSize()))) { + continue; } - } else { - nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, - aFrame->GetRectRelativeToSelf(), - aLists.BorderBackground()); + PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, aDirtyRect, colIdx, offset); } + } else if (isVisible) { + nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, + aFrame->GetRectRelativeToSelf(), + aLists.BorderBackground()); + } + + if (isVisible) { + // XXX: should box-shadow for rows/rowgroups/columns/colgroups get painted + // just because we're visible? Or should it depend on the cell visibility + // when we're not the whole table? // Paint the inset box-shadows for the table frames - if (hasBoxShadow) { + if (aFrame->StyleEffects()->mBoxShadow) { aLists.BorderBackground()->AppendNewToTop( new (aBuilder) nsDisplayBoxShadowInner(aBuilder, aFrame)); } @@ -1314,16 +1438,21 @@ nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder, aTraversal(aBuilder, aFrame, aDirtyRect, aLists); - if (aFrame->IsVisibleForPainting(aBuilder)) { - if (aFrame->GetType() == nsGkAtoms::tableFrame) { + if (isVisible) { + if (isTable) { nsTableFrame* table = static_cast<nsTableFrame*>(aFrame); // In the collapsed border model, overlay all collapsed borders. if (table->IsBorderCollapse()) { - aLists.BorderBackground()->AppendNewToTop( - new (aBuilder) nsDisplayTableBorderCollapse(aBuilder, table)); + if (table->HasBCBorders()) { + aLists.BorderBackground()->AppendNewToTop( + new (aBuilder) nsDisplayTableBorderCollapse(aBuilder, table)); + } } else { - aLists.BorderBackground()->AppendNewToTop( - new (aBuilder) nsDisplayBorder(aBuilder, table)); + const nsStyleBorder* borderStyle = aFrame->StyleBorder(); + if (borderStyle->HasBorder()) { + aLists.BorderBackground()->AppendNewToTop( + new (aBuilder) nsDisplayBorder(aBuilder, table)); + } } } } @@ -3911,9 +4040,8 @@ nsTableFrame::DumpRowGroup(nsIFrame* aKidFrame) for (nsIFrame* childFrame : cFrame->PrincipalChildList()) { nsTableCellFrame *cellFrame = do_QueryFrame(childFrame); if (cellFrame) { - int32_t colIndex; - cellFrame->GetColIndex(colIndex); - printf("cell(%d)=%p ", colIndex, static_cast<void*>(childFrame)); + uint32_t colIndex = cellFrame->ColIndex(); + printf("cell(%u)=%p ", colIndex, static_cast<void*>(childFrame)); } } printf("\n"); @@ -4046,6 +4174,7 @@ nsTableFrame::AddBCDamageArea(const TableArea& aValue) #endif SetNeedToCalcBCBorders(true); + SetNeedToCalcHasBCBorders(true); // Get the property BCPropertyData* value = GetOrCreateBCProperty(); if (value) { @@ -4086,6 +4215,7 @@ nsTableFrame::SetFullBCDamageArea() NS_ASSERTION(IsBorderCollapse(), "invalid SetFullBCDamageArea call"); SetNeedToCalcBCBorders(true); + SetNeedToCalcHasBCBorders(true); BCPropertyData* value = GetOrCreateBCProperty(); if (value) { diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h index a6b786402..d739faa72 100644 --- a/layout/tables/nsTableFrame.h +++ b/layout/tables/nsTableFrame.h @@ -761,6 +761,13 @@ public: bool NeedToCollapse() const; void SetNeedToCollapse(bool aValue); + bool NeedToCalcHasBCBorders() const; + void SetNeedToCalcHasBCBorders(bool aValue); + + void CalcHasBCBorders(); + bool HasBCBorders(); + void SetHasBCBorders(bool aValue); + /** The GeometryDirty bit is similar to the NS_FRAME_IS_DIRTY frame * state bit, which implies that all descendants are dirty. The * GeometryDirty still implies that all the parts of the table are @@ -870,6 +877,8 @@ protected: uint32_t mIStartContBCBorder:8; uint32_t mNeedToCollapse:1; // rows, cols that have visibility:collapse need to be collapsed uint32_t mResizedColumns:1; // have we resized columns since last reflow? + uint32_t mNeedToCalcHasBCBorders:1; + uint32_t mHasBCBorders:1; } mBits; nsTableCellMap* mCellMap; // maintains the relationships between rows, cols, and cells @@ -965,6 +974,30 @@ inline void nsTableFrame::SetNeedToCalcBCBorders(bool aValue) mBits.mNeedToCalcBCBorders = (unsigned)aValue; } +inline bool nsTableFrame::NeedToCalcHasBCBorders() const +{ + return (bool)mBits.mNeedToCalcHasBCBorders; +} + +inline void nsTableFrame::SetNeedToCalcHasBCBorders(bool aValue) +{ + mBits.mNeedToCalcHasBCBorders = (unsigned)aValue; +} + +inline bool nsTableFrame::HasBCBorders() +{ + if (NeedToCalcHasBCBorders()) { + CalcHasBCBorders(); + SetNeedToCalcHasBCBorders(false); + } + return (bool)mBits.mHasBCBorders; +} + +inline void nsTableFrame::SetHasBCBorders(bool aValue) +{ + mBits.mHasBCBorders = (unsigned)aValue; +} + inline nscoord nsTableFrame::GetContinuousIStartBCBorderWidth() const { diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp index ea2477b73..02b85a141 100644 --- a/layout/tables/nsTableRowFrame.cpp +++ b/layout/tables/nsTableRowFrame.cpp @@ -235,7 +235,7 @@ nsTableRowFrame::InsertFrames(ChildListID aListID, // insert the cells into the cell map int32_t colIndex = -1; if (prevCellFrame) { - prevCellFrame->GetColIndex(colIndex); + colIndex = prevCellFrame->ColIndex(); } tableFrame->InsertCells(cellChildren, GetRowIndex(), colIndex); @@ -304,18 +304,6 @@ GetBSizeOfRowsSpannedBelowFirst(nsTableCellFrame& aTableCellFrame, return bsize; } -nsTableCellFrame* -nsTableRowFrame::GetFirstCell() -{ - for (nsIFrame* childFrame : mFrames) { - nsTableCellFrame *cellFrame = do_QueryFrame(childFrame); - if (cellFrame) { - return cellFrame; - } - } - return nullptr; -} - /** * Post-reflow hook. This is where the table row does its post-processing */ @@ -659,8 +647,7 @@ CalcAvailISize(nsTableFrame& aTableFrame, nsTableCellFrame& aCellFrame) { nscoord cellAvailISize = 0; - int32_t colIndex; - aCellFrame.GetColIndex(colIndex); + uint32_t colIndex = aCellFrame.ColIndex(); int32_t colspan = aTableFrame.GetEffectiveColSpan(aCellFrame); NS_ASSERTION(colspan > 0, "effective colspan should be positive"); nsTableFrame* fifTable = @@ -799,12 +786,12 @@ nsTableRowFrame::ReflowChildren(nsPresContext* aPresContext, } } - int32_t cellColIndex; - cellFrame->GetColIndex(cellColIndex); + uint32_t cellColIndex = cellFrame->ColIndex(); cellColSpan = aTableFrame.GetEffectiveColSpan(*cellFrame); // If the adjacent cell is in a prior row (because of a rowspan) add in the space - if (prevColIndex != (cellColIndex - 1)) { + // NOTE: prevColIndex can be -1 here. + if (prevColIndex != (static_cast<int32_t>(cellColIndex) - 1)) { iCoord += GetSpaceBetween(prevColIndex, cellColIndex, cellColSpan, aTableFrame, false); } @@ -1172,8 +1159,7 @@ nsTableRowFrame::CollapseRowIfNecessary(nscoord aRowOffset, shift = rowRect.BSize(wm); nsTableCellFrame* cellFrame = GetFirstCell(); if (cellFrame) { - int32_t rowIndex; - cellFrame->GetRowIndex(rowIndex); + uint32_t rowIndex = cellFrame->RowIndex(); shift += tableFrame->GetRowSpacing(rowIndex); while (cellFrame) { LogicalRect cRect = cellFrame->GetLogicalRect(wm, containerSize); @@ -1204,13 +1190,13 @@ nsTableRowFrame::CollapseRowIfNecessary(nscoord aRowOffset, for (nsIFrame* kidFrame : mFrames) { nsTableCellFrame *cellFrame = do_QueryFrame(kidFrame); if (cellFrame) { - int32_t cellColIndex; - cellFrame->GetColIndex(cellColIndex); + uint32_t cellColIndex = cellFrame->ColIndex(); int32_t cellColSpan = tableFrame->GetEffectiveColSpan(*cellFrame); // If the adjacent cell is in a prior row (because of a rowspan) add in // the space - if (prevColIndex != (cellColIndex - 1)) { + // NOTE: prevColIndex can be -1 here. + if (prevColIndex != (static_cast<int32_t>(cellColIndex) - 1)) { iPos += GetSpaceBetween(prevColIndex, cellColIndex, cellColSpan, *tableFrame, true); } @@ -1323,9 +1309,9 @@ nsTableRowFrame::InsertCellFrame(nsTableCellFrame* aFrame, for (nsIFrame* child : mFrames) { nsTableCellFrame *cellFrame = do_QueryFrame(child); if (cellFrame) { - int32_t colIndex; - cellFrame->GetColIndex(colIndex); - if (colIndex < aColIndex) { + uint32_t colIndex = cellFrame->ColIndex(); + // Can aColIndex be -1 here? Let's assume it can for now. + if (static_cast<int32_t>(colIndex) < aColIndex) { priorCell = cellFrame; } else break; diff --git a/layout/tables/nsTableRowFrame.h b/layout/tables/nsTableRowFrame.h index 9e15d851f..c53c81ff1 100644 --- a/layout/tables/nsTableRowFrame.h +++ b/layout/tables/nsTableRowFrame.h @@ -82,7 +82,9 @@ public: const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; - nsTableCellFrame* GetFirstCell() ; + // Implemented in nsTableCellFrame.h, because it needs to know about the + // nsTableCellFrame class, but we can't include nsTableCellFrame.h here. + inline nsTableCellFrame* GetFirstCell() const; /** calls Reflow for all of its child cells. * Cells with rowspan=1 are all set to the same height and stacked horizontally. diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp index f613c8b79..37f577f5c 100644 --- a/layout/tables/nsTableRowGroupFrame.cpp +++ b/layout/tables/nsTableRowGroupFrame.cpp @@ -137,8 +137,7 @@ nsTableRowGroupFrame::InitRepeatedFrame(nsTableRowGroupFrame* aHeaderFooterFrame while (copyCellFrame && originalCellFrame) { NS_ASSERTION(originalCellFrame->GetContent() == copyCellFrame->GetContent(), "cell frames have different content"); - int32_t colIndex; - originalCellFrame->GetColIndex(colIndex); + uint32_t colIndex = originalCellFrame->ColIndex(); copyCellFrame->SetColIndex(colIndex); // Move to the next cell frame @@ -998,8 +997,7 @@ nsTableRowGroupFrame::SplitSpanningCells(nsPresContext& aPresContext, nsTableCellFrame* contCell = static_cast<nsTableCellFrame*>( aPresContext.PresShell()->FrameConstructor()-> CreateContinuingFrame(&aPresContext, cell, &aLastRow)); - int32_t colIndex; - cell->GetColIndex(colIndex); + uint32_t colIndex = cell->ColIndex(); aContRow->InsertCellFrame(contCell, colIndex); } } diff --git a/layout/tools/reftest/reftestcommandline.py b/layout/tools/reftest/reftestcommandline.py index da76fbd9a..f983be528 100644 --- a/layout/tools/reftest/reftestcommandline.py +++ b/layout/tools/reftest/reftestcommandline.py @@ -323,7 +323,8 @@ class DesktopArgumentsParser(ReftestArgumentsParser): def _prefs_gpu(self): if mozinfo.os != "win": - return ["layers.acceleration.force-enabled=true"] + return ["layers.acceleration.enabled=true", + "layers.acceleration.force=true"] return [] def validate(self, options, reftest): diff --git a/layout/tools/reftest/runreftest.py b/layout/tools/reftest/runreftest.py index 7845903bd..7061b16ca 100644 --- a/layout/tools/reftest/runreftest.py +++ b/layout/tools/reftest/runreftest.py @@ -287,11 +287,6 @@ class RefTest(object): prefs['browser.tabs.remote.autostart'] = True prefs['extensions.e10sBlocksEnabling'] = False - # Bug 1262954: For winXP + e10s disable acceleration - if platform.system() in ("Windows", "Microsoft") and \ - '5.1' in platform.version() and options.e10s: - prefs['layers.acceleration.disabled'] = True - # Bug 1300355: Disable canvas cache for win7 as it uses # too much memory and causes OOMs. if platform.system() in ("Windows", "Microsoft") and \ |