Camino only - Bug 395033: Use Gecko-based thumbnailing to prevent Tabspose chrashes with plugins. r=josh sr=pink

This commit is contained in:
stuart.morgan%alumni.case.edu 2007-09-19 17:04:56 +00:00
Родитель fe46f9182c
Коммит df1f89a8c9
3 изменённых файлов: 102 добавлений и 43 удалений

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

@ -60,7 +60,6 @@ CGColorSpaceRef getTheGreyColorSpace(void);
- (void)updateGridSizeFor:(int)num;
- (void)layoutThumbnails;
- (void)createThumbnailViews;
- (NSImage*)imageWithScreenShotInTabViewItem:(BrowserTabViewItem*)tabViewItem;
@end
@implementation TabThumbnailGridView
@ -104,7 +103,9 @@ CGColorSpaceRef getTheGreyColorSpace(void);
BrowserTabViewItem* tabViewItem;
while ((tabViewItem = [tabEnum nextObject])) {
NSImage* thumb = [self imageWithScreenShotInTabViewItem:tabViewItem];
NSImage* thumb = [[[tabViewItem view] getBrowserView] snapshot];
if (!thumb)
continue;
ThumbnailView* curThumbView = [[[ThumbnailView alloc] init] autorelease];
if (curThumbView) {
@ -195,47 +196,6 @@ CGColorSpaceRef getTheGreyColorSpace(void);
}
}
//
// Draws the given view on a window placed offscreen and takes a screenshot
//
- (NSImage*)imageWithScreenShotInTabViewItem:(BrowserTabViewItem*)tabViewItem
{
BrowserWrapper* browserWrapper = [[[tabViewItem view] retain] autorelease];
NSRect bounds = [browserWrapper bounds];
NSSize windowSize = bounds.size;
NSRect offscreenRect = NSMakeRect(0, 0, windowSize.width, windowSize.height);
NSWindow* offscreenWindow = [[NSWindow alloc] initWithContentRect:offscreenRect
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreRetained
defer:NO];
NSView* placeholderView = [[[NSView alloc] initWithFrame:[browserWrapper frame]] autorelease];
[tabViewItem setView:placeholderView];
[offscreenWindow setContentView:browserWrapper];
[[offscreenWindow contentView] display];
// Create the NSBitmapImageRep
[[offscreenWindow contentView] lockFocus];
NSBitmapImageRep* rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:offscreenRect];
// Puts the tab's view back where it came from
[tabViewItem setView:browserWrapper];
// Clean up and delete the window, which is no longer needed.
[[offscreenWindow contentView] unlockFocus];
[offscreenWindow release];
// Create an image with the representation
NSImage* image = [[[NSImage alloc] initWithSize:[rep size]] autorelease];
[image addRepresentation:rep];
[rep release];
return image;
}
#pragma mark Core Graphics
//

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

@ -284,6 +284,9 @@ typedef enum {
- (NSString*)getFocusedURLString;
// Gets an NSImage representation of the currently visible section of the page.
- (NSImage*)snapshot;
// charset
- (IBAction)reloadWithNewCharset:(NSString*)charset;
- (NSString*)currentCharset;

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

@ -128,6 +128,11 @@
#include "nsICommandManager.h"
#include "nsICommandParams.h"
// Thumbnailing
#include "gfxContext.h"
#include "gfxImageSurface.h"
#include "nsPresContext.h"
#include "GeckoUtils.h"
@ -674,6 +679,97 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1";
return domElement;
}
- (NSImage*)snapshot
{
NSSize viewportSize = [self bounds].size;
// We don't draw scrollbars, so set the snapshot width to be the smaller of
// the view width and the dom width to prevent a blank strip in the snapshot.
nsCOMPtr<nsIDOMWindow> domWindow = [self getContentWindow];
if (!domWindow)
return nil;
int pageWidth;
int pageHeight;
GeckoUtils::GetIntrisicSize(domWindow, &pageWidth, &pageHeight);
NSSize snapshotSize = NSMakeSize(MIN(pageWidth, viewportSize.width),
viewportSize.height);
// Create a context to draw into.
// TODO: use a quartz-based surface, so that widgets will draw onto it.
nsRefPtr<gfxImageSurface> surface = new gfxImageSurface(gfxIntSize(snapshotSize.width,
snapshotSize.height),
gfxImageSurface::ImageFormatARGB32);
if (!surface)
return nil;
nsRefPtr<gfxContext> context = new gfxContext(surface);
if (!context)
return nil;
// Get the page presentation.
nsCOMPtr<nsIDocShell> docShell = [self getDocShell];
if (!docShell)
return nil;
nsCOMPtr<nsPresContext> presContext;
docShell->GetPresContext(getter_AddRefs(presContext));
if (!presContext)
return nil;
nsIPresShell* presShell = presContext->PresShell();
if (!presShell)
return nil;
// Draw the desired section of the page into our context.
PRInt32 scrollX, scrollY;
domWindow->GetScrollX(&scrollX);
domWindow->GetScrollY(&scrollY);
PRInt32 appUnitsPerPixel = presContext->AppUnitsPerDevPixel();
nsRect viewRect(NSIntPixelsToAppUnits(scrollX, appUnitsPerPixel),
NSIntPixelsToAppUnits(scrollY, appUnitsPerPixel),
NSIntPixelsToAppUnits(viewportSize.width, appUnitsPerPixel),
NSIntPixelsToAppUnits(viewportSize.height, appUnitsPerPixel));
presShell->RenderDocument(viewRect, PR_FALSE, PR_TRUE, NS_RGB(255, 255, 255), context);
// The data is ARGB, in host endianness, which doesn't convert nicely to an
// NSImage, so pass it through CGImage to extract the data.
size_t bitsPerComponent = 8;
size_t componentsPerPixel = 4;
size_t imageBytes = componentsPerPixel * snapshotSize.width * snapshotSize.height;
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL,
surface->Data(),
imageBytes,
NULL);
if (!dataProvider)
return nil;
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
if (!colorSpace) {
CGDataProviderRelease(dataProvider);
return nil;
}
CGImageRef cgImage = CGImageCreate(snapshotSize.width, snapshotSize.height,
bitsPerComponent,
bitsPerComponent * componentsPerPixel,
surface->Stride(),
colorSpace,
kCGImageAlphaFirst | kCGBitmapByteOrder32Host,
dataProvider,
NULL, // no decode
true, // enable interpolation
kCGRenderingIntentDefault);
CGDataProviderRelease(dataProvider);
CGColorSpaceRelease(colorSpace);
if (!cgImage)
return nil;
// Finally, get it into an NSImage.
NSImage* snapshot = [[[NSImage alloc] initWithSize:snapshotSize] autorelease];
NSRect imageRect = NSMakeRect(0, 0, snapshotSize.width, snapshotSize.height);
[snapshot lockFocus];
CGContextDrawImage((CGContextRef)[[NSGraphicsContext currentContext] graphicsPort],
*(CGRect*)&imageRect, cgImage);
[snapshot unlockFocus];
CGImageRelease(cgImage);
return snapshot;
}
-(void) saveInternal: (nsIURI*)aURI
withDocument: (nsIDOMDocument*)aDocument
suggestedFilename: (NSString*)aFileName