diff --git a/widget/cocoa/VibrancyManager.h b/widget/cocoa/VibrancyManager.h index d7c96427bca2..19868e2d108d 100644 --- a/widget/cocoa/VibrancyManager.h +++ b/widget/cocoa/VibrancyManager.h @@ -73,6 +73,8 @@ class VibrancyManager { bool HasVibrantRegions() { return !mVibrantRegions.IsEmpty(); } + LayoutDeviceIntRegion GetUnionOfVibrantRegions() const; + /** * Return the fill color that should be drawn on top of the cleared window * parts. Usually this would be drawn by -[NSVisualEffectView drawRect:]. diff --git a/widget/cocoa/VibrancyManager.mm b/widget/cocoa/VibrancyManager.mm index 3922662f5b38..9a6fbaae3aaf 100644 --- a/widget/cocoa/VibrancyManager.mm +++ b/widget/cocoa/VibrancyManager.mm @@ -23,6 +23,14 @@ bool VibrancyManager::UpdateVibrantRegion(VibrancyType aType, }); } +LayoutDeviceIntRegion VibrancyManager::GetUnionOfVibrantRegions() const { + LayoutDeviceIntRegion result; + for (auto it = mVibrantRegions.ConstIter(); !it.Done(); it.Next()) { + result.OrWith(it.UserData()->Region()); + } + return result; +} + @interface NSView (CurrentFillColor) - (NSColor*)_currentFillColor; @end diff --git a/widget/cocoa/nsChildView.h b/widget/cocoa/nsChildView.h index c4f34d11ea07..e505a6420f57 100644 --- a/widget/cocoa/nsChildView.h +++ b/widget/cocoa/nsChildView.h @@ -621,6 +621,8 @@ class nsChildView final : public nsBaseWidget { void UpdateVibrancy(const nsTArray& aThemeGeometries); mozilla::VibrancyManager& EnsureVibrancyManager(); + void UpdateInternalOpaqueRegion(); + nsIWidget* GetWidgetForListenerEvents(); struct SwipeInfo { @@ -736,6 +738,9 @@ class nsChildView final : public nsBaseWidget { RefPtr mUnsuspendAsyncCATransactionsRunnable; + // The widget's opaque region. Written on the main thread, read on any thread. + mozilla::DataMutex mOpaqueRegion; + // This flag is only used when APZ is off. It indicates that the current pan // gesture was processed as a swipe. Sometimes the swipe animation can finish // before momentum events of the pan gesture have stopped firing, so this diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index ebe9879a7628..64039892a969 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -338,6 +338,7 @@ nsChildView::nsChildView() mIsDispatchPaint(false), mPluginFocused{false}, mCompositingState("nsChildView::mCompositingState"), + mOpaqueRegion("nsChildView::mOpaqueRegion"), mCurrentPanGestureBelongsToSwipe{false} {} nsChildView::~nsChildView() { @@ -613,6 +614,8 @@ void nsChildView::SetTransparencyMode(nsTransparencyMode aMode) { windowWidget->SetTransparencyMode(aMode); } + UpdateInternalOpaqueRegion(); + NS_OBJC_END_TRY_ABORT_BLOCK; } @@ -2492,6 +2495,8 @@ void nsChildView::UpdateVibrancy(const nsTArray& aThemeGeometries changed |= vm.UpdateVibrantRegion(VibrancyType::ACTIVE_SOURCE_LIST_SELECTION, activeSourceListSelectionRegion); + UpdateInternalOpaqueRegion(); + if (changed) { SuspendAsyncCATransactions(); } @@ -2515,6 +2520,19 @@ mozilla::VibrancyManager& nsChildView::EnsureVibrancyManager() { return *mVibrancyManager; } +void nsChildView::UpdateInternalOpaqueRegion() { + MOZ_RELEASE_ASSERT(NS_IsMainThread(), "This should only be called on the main thread."); + auto opaqueRegion = mOpaqueRegion.Lock(); + bool widgetIsOpaque = GetTransparencyMode() == eTransparencyOpaque; + if (!widgetIsOpaque) { + opaqueRegion->SetEmpty(); + } else if (VibrancyManager::SystemSupportsVibrancy()) { + opaqueRegion->Sub(mBounds, EnsureVibrancyManager().GetUnionOfVibrantRegions()); + } else { + *opaqueRegion = mBounds; + } +} + nsChildView::SwipeInfo nsChildView::SendMayStartSwipe( const mozilla::PanGestureInput& aSwipeStartEvent) { nsCOMPtr kungFuDeathGrip(this);