Bug 1491442 - Make nsChildView create a NativeLayerRootCA and fill it with content when painting using BasicLayers (which used to go through drawRect). r=mattwoodrow

This makes context menus work. Regular windows are still blank at this point.

This introduces a visual regression on 10.9: context menus and panels now no
longer have a shadow. Only 10.10 and above support shadows on transparent windows
that use CoreAnimation; 10.9 is not able to obtain the shadow shape on those
types of windows.
I think this is an acceptable regression to take. We want to use CoreAnimation
for all window types because it simplifies the code (no need to handle two
paths) and because it avoids expensive mode switches if we realize too late
that a window we just opened is supposed to use CoreAnimation.

Differential Revision: https://phabricator.services.mozilla.com/D40516

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Markus Stange 2019-08-16 01:13:35 +00:00
Родитель 3cfb0f5ea9
Коммит 2921208661
3 изменённых файлов: 80 добавлений и 2 удалений

Просмотреть файл

@ -168,3 +168,7 @@ RESOURCE_FILES.__setattr__('MainMenu.nib', [
])
CXXFLAGS += CONFIG['TK_CFLAGS']
OS_LIBS += [
'-framework IOSurface',
]

Просмотреть файл

@ -29,6 +29,7 @@
#include "nsString.h"
#include "nsIDragService.h"
#include "ViewRegion.h"
#include "CFTypeRefPtr.h"
#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
@ -50,6 +51,8 @@ class VibrancyManager;
namespace layers {
class GLManager;
class IAPZCTreeManager;
class NativeLayerRootCA;
class NativeLayerCA;
} // namespace layers
namespace widget {
class RectTextureImage;
@ -460,6 +463,10 @@ class nsChildView final : public nsBaseWidget {
const mozilla::gfx::IntSize& aSurfaceSize);
bool PaintWindowInContext(CGContextRef aContext, const LayoutDeviceIntRegion& aRegion,
mozilla::gfx::IntSize aSurfaceSize);
bool PaintWindowInIOSurface(CFTypeRefPtr<IOSurfaceRef> aSurface,
const LayoutDeviceIntRegion& aInvalidRegion);
void PaintWindowInContentLayer();
void HandleMainThreadCATransaction();
#ifdef ACCESSIBILITY
@ -662,6 +669,13 @@ class nsChildView final : public nsBaseWidget {
// Always null if StaticPrefs::gfx_core_animation_enabled_AtStartup() is true.
mozilla::UniquePtr<GLPresenter> mGLPresenter;
RefPtr<mozilla::layers::NativeLayerRootCA> mNativeLayerRoot;
// The CoreAnimation layer that contains the rendering from Gecko. This is a
// sublayer of mNativeLayerRoot's underlying wrapper layer.
// Always null if StaticPrefs::gfx_core_animation_enabled_AtStartup() is false.
RefPtr<mozilla::layers::NativeLayerCA> mContentLayer;
mozilla::UniquePtr<mozilla::VibrancyManager> mVibrancyManager;
RefPtr<mozilla::SwipeTracker> mSwipeTracker;
mozilla::UniquePtr<mozilla::SwipeEventQueue> mSwipeEventQueue;

Просмотреть файл

@ -11,6 +11,8 @@
#include <unistd.h>
#include <math.h>
#include <IOSurface/IOSurface.h>
#include "nsChildView.h"
#include "nsCocoaWindow.h"
@ -78,6 +80,7 @@
#include "mozilla/layers/BasicCompositor.h"
#include "mozilla/layers/InputAPZContext.h"
#include "mozilla/layers/IpcResourceUpdateQueue.h"
#include "mozilla/layers/NativeLayerCA.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/layers/WebRenderLayerManager.h"
#include "mozilla/webrender/WebRenderAPI.h"
@ -355,6 +358,10 @@ nsChildView::~nsChildView() {
NS_WARNING_ASSERTION(mOnDestroyCalled, "nsChildView object destroyed without calling Destroy()");
if (StaticPrefs::gfx_core_animation_enabled_AtStartup()) {
mNativeLayerRoot->RemoveLayer(mContentLayer); // safe if already removed
}
DestroyCompositor();
// An nsChildView object that was in use can be destroyed without Destroy()
@ -413,6 +420,14 @@ nsresult nsChildView::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
NSRect r = nsCocoaUtils::DevPixelsToCocoaPoints(mBounds, scaleFactor);
mView = [[ChildView alloc] initWithFrame:r geckoChild:this];
if (StaticPrefs::gfx_core_animation_enabled_AtStartup()) {
mNativeLayerRoot = NativeLayerRootCA::CreateForCALayer([mView rootCALayer]);
mNativeLayerRoot->SetBackingScale(scaleFactor);
RefPtr<NativeLayer> contentLayer = mNativeLayerRoot->CreateLayer();
mNativeLayerRoot->AppendLayer(contentLayer);
mContentLayer = contentLayer->AsNativeLayerCA();
}
// If this view was created in a Gecko view hierarchy, the initial state
// is hidden. If the view is attached only to a native NSView but has
// no Gecko parent (as in embedding), the initial state is visible.
@ -809,6 +824,10 @@ void nsChildView::BackingScaleFactorChanged() {
NSRect frame = [mView frame];
mBounds = nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, newScale);
if (StaticPrefs::gfx_core_animation_enabled_AtStartup()) {
mNativeLayerRoot->SetBackingScale(mBackingScaleFactor);
}
if (mWidgetListener && !mWidgetListener->GetXULWindow()) {
if (PresShell* presShell = mWidgetListener->GetPresShell()) {
presShell->BackingScaleFactorChanged();
@ -1209,7 +1228,12 @@ void nsChildView::Invalidate(const LayoutDeviceIntRect& aRect) {
NS_ASSERTION(GetLayerManager()->GetBackendType() != LayersBackend::LAYERS_CLIENT,
"Shouldn't need to invalidate with accelerated OMTC layers!");
[[mView pixelHostingView] setNeedsDisplayInRect:DevPixelsToCocoaPoints(aRect)];
if (StaticPrefs::gfx_core_animation_enabled_AtStartup()) {
mContentLayer->InvalidateRegionThroughoutSwapchain(aRect.ToUnknownRect());
[mView markLayerForDisplay];
} else {
[[mView pixelHostingView] setNeedsDisplayInRect:DevPixelsToCocoaPoints(aRect)];
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
@ -1398,7 +1422,43 @@ bool nsChildView::PaintWindowInContext(CGContextRef aContext, const LayoutDevice
return painted;
}
void nsChildView::HandleMainThreadCATransaction() {}
bool nsChildView::PaintWindowInIOSurface(CFTypeRefPtr<IOSurfaceRef> aSurface,
const LayoutDeviceIntRegion& aInvalidRegion) {
RefPtr<MacIOSurface> surf = new MacIOSurface(std::move(aSurface));
surf->Lock(false);
RefPtr<gfx::DrawTarget> dt = surf->GetAsDrawTargetLocked(gfx::BackendType::SKIA);
bool result = PaintWindowInDrawTarget(dt, aInvalidRegion, dt->GetSize());
surf->Unlock(false);
return result;
}
void nsChildView::PaintWindowInContentLayer() {
mContentLayer->SetRect(GetBounds().ToUnknownRect());
mContentLayer->SetSurfaceIsFlipped(false);
CFTypeRefPtr<IOSurfaceRef> surf = mContentLayer->NextSurface();
if (!surf) {
return;
}
PaintWindowInIOSurface(
surf, LayoutDeviceIntRegion::FromUnknownRegion(mContentLayer->CurrentSurfaceInvalidRegion()));
mContentLayer->NotifySurfaceReady();
}
void nsChildView::HandleMainThreadCATransaction() {
WillPaintWindow();
if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC) {
// We're in BasicLayers mode, i.e. main thread software compositing.
// Composite the window into our layer's surface.
PaintWindowInContentLayer();
}
// Apply the changes from mContentLayer to its underlying CALayer. Now is a
// good time to call this because we know we're currently inside a main thread
// CATransaction.
mNativeLayerRoot->ApplyChanges();
}
#pragma mark -