Bug 820839 - Draw OSX titlebar content into a retained buffer during the ThebesLayer painting phase, before we clear invalidation state. r=roc

This commit is contained in:
Matt Woodrow 2013-01-17 11:59:23 +13:00
Родитель 6e702dcb08
Коммит c4cfe33e02
11 изменённых файлов: 88 добавлений и 8 удалений

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

@ -1109,7 +1109,7 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
BuildContainerLayerFor(aBuilder, layerManager, aForFrame, nullptr, *this,
containerParameters, nullptr);
if (widgetTransaction) {
if (widgetTransaction && !(aFlags & PAINT_NO_CLEAR_INVALIDATIONS)) {
aForFrame->ClearInvalidationStateBits();
}

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

@ -1390,7 +1390,8 @@ public:
PAINT_USE_WIDGET_LAYERS = 0x01,
PAINT_FLUSH_LAYERS = 0x02,
PAINT_EXISTING_TRANSACTION = 0x04,
PAINT_NO_COMPOSITE = 0x08
PAINT_NO_COMPOSITE = 0x08,
PAINT_NO_CLEAR_INVALIDATIONS = 0x10
};
void PaintRoot(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
uint32_t aFlags) const;

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

@ -1973,6 +1973,9 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram
if (aFlags & PAINT_NO_COMPOSITE) {
flags |= nsDisplayList::PAINT_NO_COMPOSITE;
}
if (aFlags & PAINT_NO_CLEAR_INVALIDATIONS) {
flags |= nsDisplayList::PAINT_NO_CLEAR_INVALIDATIONS;
}
list.PaintRoot(&builder, aRenderingContext, flags);

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

@ -644,7 +644,8 @@ public:
PAINT_ALL_CONTINUATIONS = 0x40,
PAINT_TO_WINDOW = 0x80,
PAINT_EXISTING_TRANSACTION = 0x100,
PAINT_NO_COMPOSITE = 0x200
PAINT_NO_COMPOSITE = 0x200,
PAINT_NO_CLEAR_INVALIDATIONS = 0x400
};
/**

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

@ -5385,6 +5385,9 @@ PresShell::Paint(nsView* aViewToPaint,
if (!(aFlags & PAINT_COMPOSITE)) {
flags |= nsLayoutUtils::PAINT_NO_COMPOSITE;
}
if (aViewToPaint->InAlternatePaint()) {
flags |= nsLayoutUtils::PAINT_NO_CLEAR_INVALIDATIONS;
}
if (frame) {
// Defer invalidates that are triggered during painting, and discard

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

@ -295,6 +295,13 @@ public:
}
}
/**
* Returns true if the view is currently painting
* into an alternate destination, such as the titlebar
* area on OSX.
*/
bool InAlternatePaint() { return mInAlternatePaint; }
/**
* Make aWidget direct its events to this view.
* The caller must call DetachWidgetEventHandler before this view

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

@ -390,12 +390,13 @@ void nsViewManager::ProcessPendingUpdatesForView(nsView* aView,
NS_ASSERTION(aView->HasWidget(), "Must have a widget!");
SetPainting(true);
#ifdef DEBUG_INVALIDATIONS
printf("---- PAINT START ----PresShell(%p), nsView(%p), nsIWidget(%p)\n", mPresShell, aView, widget);
#endif
nsAutoScriptBlocker scriptBlocker;
NS_ASSERTION(aView->HasWidget(), "Must have a widget!");
aView->GetWidget()->WillPaint();
SetPainting(true);
mPresShell->Paint(aView, nsRegion(),
nsIPresShell::PAINT_LAYERS |
nsIPresShell::PAINT_WILL_SEND_DID_PAINT);

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

@ -21,6 +21,7 @@
#include "nsWeakPtr.h"
#include "TextInputHandler.h"
#include "nsCocoaUtils.h"
#include "gfxQuartzSurface.h"
#include "nsString.h"
#include "nsIDragService.h"
@ -280,6 +281,8 @@ typedef NSInteger NSEventGestureAxis;
- (void)drawRect:(NSRect)aRect inTitlebarContext:(CGContextRef)aContext;
- (void)drawTitlebar:(NSRect)aRect inTitlebarContext:(CGContextRef)aContext;
- (void)sendMouseEnterOrExitEvent:(NSEvent*)aEvent
enter:(BOOL)aEnter
type:(nsMouseEvent::exitType)aType;
@ -505,6 +508,8 @@ public:
NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent);
virtual void WillPaint() MOZ_OVERRIDE;
mozilla::widget::TextInputHandler* GetTextInputHandler()
{
return mTextInputHandler;
@ -524,6 +529,8 @@ public:
return nsCocoaUtils::DevPixelsToCocoaPoints(aRect, BackingScaleFactor());
}
void CompositeTitlebar(const gfxSize& aSize, CGContextRef aContext);
protected:
void ReportMoveEvent();
@ -560,6 +567,9 @@ protected:
nsRefPtr<gfxASurface> mTempThebesSurface;
nsRefPtr<mozilla::gl::TextureImage> mResizerImage;
nsRefPtr<gfxQuartzSurface> mTitlebarSurf;
gfxSize mTitlebarSize;
// Cached value of [mView backingScaleFactor], to avoid sending two obj-c
// messages (respondsToSelector, backingScaleFactor) every time we need to
// use it.

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

@ -653,6 +653,45 @@ nsChildView::ReparentNativeWidget(nsIWidget* aNewParent)
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
void
nsChildView::WillPaint()
{
if (!mView || ![mView isKindOfClass:[ChildView class]])
return;
NSWindow* win = [mView window];
if (!win || ![win isKindOfClass:[ToolbarWindow class]])
return;
if (![(ToolbarWindow*)win drawsContentsIntoWindowFrame])
return;
NSRect titlebarRect = [(ToolbarWindow*)win titlebarRect];
gfxSize titlebarSize(titlebarRect.size.width, titlebarRect.size.height);
if (!mTitlebarSurf || mTitlebarSize != titlebarSize) {
mTitlebarSize = titlebarSize;
mTitlebarSurf = new gfxQuartzSurface(titlebarSize, gfxASurface::ImageFormatARGB32);
}
NSRect flippedTitlebarRect = { NSZeroPoint, titlebarRect.size };
CGContextRef context = mTitlebarSurf->GetCGContext();
[(ChildView*)mView drawRect:flippedTitlebarRect inTitlebarContext:context];
}
void
nsChildView::CompositeTitlebar(const gfxSize& aSize, CGContextRef aContext)
{
NS_ASSERTION(mTitlebarSurf, "Must have titlebar surface");
if (!mTitlebarSurf) {
return;
}
CGImageRef image = CGBitmapContextCreateImage(mTitlebarSurf->GetCGContext());
CGContextDrawImage(aContext,
CGRectMake(0, 0, mTitlebarSize.width, mTitlebarSize.height),
image);
CGImageRelease(image);
}
void nsChildView::ResetParent()
{
if (!mOnDestroyCalled) {
@ -2418,6 +2457,14 @@ NSEvent* gLastDragMouseDownEvent = nil;
}
}
- (void)drawTitlebar:(NSRect)aRect inTitlebarContext:(CGContextRef)aContext
{
if (mGeckoChild) {
gfxSize size(aRect.size.width, aRect.size.height);
mGeckoChild->CompositeTitlebar(size, aContext);
}
}
// The display system has told us that a portion of our view is dirty. Tell
// gecko to paint it
- (void)drawRect:(NSRect)aRect

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

@ -2970,8 +2970,7 @@ TitlebarDrawCallback(void* aInfo, CGContextRef aContext)
CGContextScaleCTM(aContext, 1.0f, -1.0f);
CGContextTranslateCTM(aContext, 0.0f, -[window frame].size.height);
NSRect flippedTitlebarRect = { NSZeroPoint, titlebarRect.size };
[(ChildView*)view drawRect:flippedTitlebarRect inTitlebarContext:aContext];
[(ChildView*)view drawTitlebar:[window frame] inTitlebarContext:aContext];
} else {
BOOL isMain = [window isMainWindow];
NSColor *titlebarColor = [window titlebarColorForActiveWindow:isMain];

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

@ -92,8 +92,8 @@ typedef nsEventStatus (* EVENT_CALLBACK)(nsGUIEvent *event);
#endif
#define NS_IWIDGET_IID \
{ 0x476D5716, 0xE225, 0x4497, \
{ 0x80, 0x41, 0x92, 0xF8, 0x67, 0x59, 0xC4, 0x38 } }
{ 0xDAEE334D, 0x9031, 0x4928, \
{ 0x9D, 0xD7, 0x75, 0x2E, 0x8B, 0x6B, 0xF7, 0x0E } }
/*
* Window shadow styles
@ -1643,6 +1643,14 @@ class nsIWidget : public nsISupports {
virtual bool NeedsPaint() {
return true;
}
/**
* This function is called by nsViewManager right before the retained layer
* tree for this widget is about to be updated, and any required
* ThebesLayer painting occurs.
*/
virtual void WillPaint() { }
/**
* Get the natural bounds of this widget. This method is only
* meaningful for widgets for which Gecko implements screen