Commit d21a8a5f authored by pkotwicz@chromium.org's avatar pkotwicz@chromium.org

This replaces the snapshotting code in the pixel tests with the code used to...

This replaces the snapshotting code in the pixel tests with the code used to get screenshots for reporting issues.
Added a bounds parameter to window_snapshot.cc so that we can take a picture of just the tab contents and not have to rebaseline with chrome ui changes.

BUG=None
TEST=None

Review URL: http://codereview.chromium.org/8523022

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111155 0039d316-1c4b-4281-b951-d872f2087c98
parent 4cdc26a7
...@@ -139,8 +139,11 @@ void ShowHtmlBugReportView(Browser* browser, ...@@ -139,8 +139,11 @@ void ShowHtmlBugReportView(Browser* browser,
last_screenshot_png->clear(); last_screenshot_png->clear();
gfx::NativeWindow native_window = browser->window()->GetNativeHandle(); gfx::NativeWindow native_window = browser->window()->GetNativeHandle();
BugReportUtil::SetScreenshotSize( gfx::Rect snapshot_bounds = gfx::Rect(browser->window()->GetBounds().size());
browser::GrabWindowSnapshot(native_window, last_screenshot_png)); bool success = browser::GrabWindowSnapshot(native_window,
last_screenshot_png,
snapshot_bounds);
BugReportUtil::SetScreenshotSize(success ? snapshot_bounds : gfx::Rect());
std::string bug_report_url = std::string(chrome::kChromeUIBugReportURL) + std::string bug_report_url = std::string(chrome::kChromeUIBugReportURL) +
"#" + base::IntToString(browser->active_index()) + "#" + base::IntToString(browser->active_index()) +
......
...@@ -16,10 +16,12 @@ namespace gfx { ...@@ -16,10 +16,12 @@ namespace gfx {
namespace browser { namespace browser {
// Grabs a snapshot of the designated window and stores a PNG representation // Grabs a snapshot of the rectangle area |snapshot_bounds| with respect to the
// into a byte vector. Returns the image bounds. // top left corner of the designated window and stores a PNG representation
gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window, // into a byte vector. Returns true if the operation is successful.
std::vector<unsigned char>* png_representation); bool GrabWindowSnapshot(gfx::NativeWindow window,
std::vector<unsigned char>* png_representation,
const gfx::Rect& snapshot_bounds);
} // namespace browser } // namespace browser
......
...@@ -9,11 +9,12 @@ ...@@ -9,11 +9,12 @@
namespace browser { namespace browser {
gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window_handle, bool GrabWindowSnapshot(gfx::NativeWindow window_handle,
std::vector<unsigned char>* png_representation) { std::vector<unsigned char>* png_representation,
const gfx::Rect& snapshot_bounds) {
// TODO(saintlou): Stub for Aura. // TODO(saintlou): Stub for Aura.
NOTIMPLEMENTED(); NOTIMPLEMENTED();
return gfx::Rect(); return false;
} }
} // namespace browser } // namespace browser
...@@ -24,25 +24,32 @@ static cairo_status_t SnapshotCallback( ...@@ -24,25 +24,32 @@ static cairo_status_t SnapshotCallback(
return CAIRO_STATUS_SUCCESS; return CAIRO_STATUS_SUCCESS;
} }
gfx::Rect GrabWindowSnapshot(gfx::NativeWindow gtk_window, bool GrabWindowSnapshot(gfx::NativeWindow window_handle,
std::vector<unsigned char>* png_representation) { std::vector<unsigned char>* png_representation,
GdkWindow* gdk_window = GTK_WIDGET(gtk_window)->window; const gfx::Rect& snapshot_bounds) {
GdkWindow* gdk_window = GTK_WIDGET(window_handle)->window;
Display* display = GDK_WINDOW_XDISPLAY(gdk_window); Display* display = GDK_WINDOW_XDISPLAY(gdk_window);
XID win = GDK_WINDOW_XID(gdk_window); XID win = GDK_WINDOW_XID(gdk_window);
XWindowAttributes attr;
if (XGetWindowAttributes(display, win, &attr) == 0) { gfx::Rect window_bounds;
LOG(ERROR) << "Couldn't get window attributes"; if (ui::GetWindowRect(win, &window_bounds) == 0) {
return gfx::Rect(); LOG(ERROR) << "Couldn't get window bounds";
return false;
} }
DCHECK_LE(snapshot_bounds.right(), window_bounds.width());
DCHECK_LE(snapshot_bounds.bottom(), window_bounds.height());
XImage* image = XGetImage( XImage* image = XGetImage(
display, win, 0, 0, attr.width, attr.height, AllPlanes, ZPixmap); display, win, snapshot_bounds.x(), snapshot_bounds.y(),
snapshot_bounds.width(), snapshot_bounds.height(), AllPlanes, ZPixmap);
if (!image) { if (!image) {
LOG(ERROR) << "Couldn't get image"; LOG(ERROR) << "Couldn't get image";
return gfx::Rect(); return false;
} }
if (image->depth != 24) { if (image->depth != 24) {
LOG(ERROR)<< "Unsupported image depth " << image->depth; LOG(ERROR)<< "Unsupported image depth " << image->depth;
return gfx::Rect(); return false;
} }
cairo_surface_t* surface = cairo_surface_t* surface =
cairo_image_surface_create_for_data( cairo_image_surface_create_for_data(
...@@ -54,13 +61,13 @@ gfx::Rect GrabWindowSnapshot(gfx::NativeWindow gtk_window, ...@@ -54,13 +61,13 @@ gfx::Rect GrabWindowSnapshot(gfx::NativeWindow gtk_window,
if (!surface) { if (!surface) {
LOG(ERROR) << "Unable to create Cairo surface from XImage data"; LOG(ERROR) << "Unable to create Cairo surface from XImage data";
return gfx::Rect(); return false;
} }
cairo_surface_write_to_png_stream( cairo_surface_write_to_png_stream(
surface, SnapshotCallback, png_representation); surface, SnapshotCallback, png_representation);
cairo_surface_destroy(surface); cairo_surface_destroy(surface);
return gfx::Rect(image->width, image->height); return true;
} }
} // namespace browser } // namespace browser
...@@ -13,18 +13,36 @@ ...@@ -13,18 +13,36 @@
namespace browser { namespace browser {
gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window, bool GrabWindowSnapshot(gfx::NativeWindow window,
std::vector<unsigned char>* png_representation) { std::vector<unsigned char>* png_representation,
const gfx::Rect& snapshot_bounds) {
NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
gfx::Rect screen_bounds = gfx::Rect(NSRectToCGRect([screen frame]));
gfx::Rect window_bounds = gfx::Rect(NSRectToCGRect([window frame]));
// Flip window coordinates based on the primary screen.
window_bounds.set_y(
screen_bounds.height() - window_bounds.y() - window_bounds.height());
// Convert snapshot bounds relative to window into bounds relative to
// screen.
gfx::Rect screen_snapshot_bounds = gfx::Rect(
window_bounds.origin().Add(snapshot_bounds.origin()),
snapshot_bounds.size());
DCHECK_LE(screen_snapshot_bounds.right(), window_bounds.right());
DCHECK_LE(screen_snapshot_bounds.bottom(), window_bounds.bottom());
png_representation->clear(); png_representation->clear();
// Make sure to grab the "window frame" view so we get current tab + // Make sure to grab the "window frame" view so we get current tab +
// tabstrip. // tabstrip.
NSView* view = [[window contentView] superview]; NSView* view = [[window contentView] superview];
base::mac::ScopedCFTypeRef<CGImageRef> windowSnapshot(CGWindowListCreateImage( base::mac::ScopedCFTypeRef<CGImageRef> windowSnapshot(CGWindowListCreateImage(
CGRectNull, kCGWindowListOptionIncludingWindow, screen_snapshot_bounds.ToCGRect(), kCGWindowListOptionIncludingWindow,
[[view window] windowNumber], kCGWindowImageBoundsIgnoreFraming)); [[view window] windowNumber], kCGWindowImageBoundsIgnoreFraming));
if (CGImageGetWidth(windowSnapshot) <= 0) if (CGImageGetWidth(windowSnapshot) <= 0)
return gfx::Rect(); return false;
scoped_nsobject<NSBitmapImageRep> rep( scoped_nsobject<NSBitmapImageRep> rep(
[[NSBitmapImageRep alloc] initWithCGImage:windowSnapshot]); [[NSBitmapImageRep alloc] initWithCGImage:windowSnapshot]);
...@@ -32,13 +50,12 @@ gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window, ...@@ -32,13 +50,12 @@ gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window,
const unsigned char* buf = static_cast<const unsigned char*>([data bytes]); const unsigned char* buf = static_cast<const unsigned char*>([data bytes]);
NSUInteger length = [data length]; NSUInteger length = [data length];
if (buf == NULL || length == 0) if (buf == NULL || length == 0)
return gfx::Rect(); return false;
png_representation->assign(buf, buf + length); png_representation->assign(buf, buf + length);
DCHECK(!png_representation->empty()); DCHECK(!png_representation->empty());
return gfx::Rect(static_cast<int>([rep pixelsWide]), return true;
static_cast<int>([rep pixelsHigh]));
} }
} // namespace browser } // namespace browser
...@@ -30,7 +30,9 @@ TEST_F(GrabWindowSnapshotTest, TestGrabWindowSnapshot) { ...@@ -30,7 +30,9 @@ TEST_F(GrabWindowSnapshotTest, TestGrabWindowSnapshot) {
scoped_ptr<std::vector<unsigned char> > png_representation( scoped_ptr<std::vector<unsigned char> > png_representation(
new std::vector<unsigned char>); new std::vector<unsigned char>);
browser::GrabWindowSnapshot(window, png_representation.get()); gfx::Rect bounds = gfx::Rect(0, 0, frame.size.width, frame.size.height);
EXPECT_TRUE(browser::GrabWindowSnapshot(window, png_representation.get(),
bounds));
// Copy png back into NSData object so we can make sure we grabbed a png. // Copy png back into NSData object so we can make sure we grabbed a png.
scoped_nsobject<NSData> image_data( scoped_nsobject<NSData> image_data(
......
...@@ -12,22 +12,35 @@ ...@@ -12,22 +12,35 @@
#include "ui/gfx/rect.h" #include "ui/gfx/rect.h"
#include "ui/gfx/size.h" #include "ui/gfx/size.h"
namespace {
gfx::Rect GetWindowBounds(gfx::NativeWindow window_handle) {
RECT content_rect = {0, 0, 0, 0};
::GetWindowRect(window_handle, &content_rect);
content_rect.right++; // Match what PrintWindow wants.
return gfx::Rect(content_rect.right - content_rect.left,
content_rect.bottom - content_rect.top);
}
} // namespace
namespace browser { namespace browser {
gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window_handle, bool GrabWindowSnapshot(gfx::NativeWindow window_handle,
std::vector<unsigned char>* png_representation) { std::vector<unsigned char>* png_representation,
const gfx::Rect& snapshot_bounds) {
DCHECK(snapshot_bounds.right() <= GetWindowBounds(window_handle).right());
DCHECK(snapshot_bounds.bottom() <= GetWindowBounds(window_handle).bottom());
// Create a memory DC that's compatible with the window. // Create a memory DC that's compatible with the window.
HDC window_hdc = GetWindowDC(window_handle); HDC window_hdc = GetWindowDC(window_handle);
base::win::ScopedCreateDC mem_hdc(CreateCompatibleDC(window_hdc)); base::win::ScopedCreateDC mem_hdc(CreateCompatibleDC(window_hdc));
// Create a DIB that's the same size as the window.
RECT content_rect = {0, 0, 0, 0};
::GetWindowRect(window_handle, &content_rect);
content_rect.right++; // Match what PrintWindow wants.
int width = content_rect.right - content_rect.left;
int height = content_rect.bottom - content_rect.top;
BITMAPINFOHEADER hdr; BITMAPINFOHEADER hdr;
gfx::CreateBitmapHeader(width, height, &hdr); gfx::CreateBitmapHeader(snapshot_bounds.width(),
snapshot_bounds.height(),
&hdr);
unsigned char *bit_ptr = NULL; unsigned char *bit_ptr = NULL;
base::win::ScopedBitmap bitmap( base::win::ScopedBitmap bitmap(
CreateDIBSection(mem_hdc, CreateDIBSection(mem_hdc,
...@@ -41,7 +54,8 @@ gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window_handle, ...@@ -41,7 +54,8 @@ gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window_handle,
// show up on a white background, and strangely-shaped windows // show up on a white background, and strangely-shaped windows
// look reasonable). Not capturing an alpha mask saves a // look reasonable). Not capturing an alpha mask saves a
// bit of space. // bit of space.
PatBlt(mem_hdc, 0, 0, width, height, WHITENESS); PatBlt(mem_hdc, 0, 0, snapshot_bounds.width(), snapshot_bounds.height(),
WHITENESS);
// Grab a copy of the window // Grab a copy of the window
// First, see if PrintWindow is defined (it's not in Windows 2000). // First, see if PrintWindow is defined (it's not in Windows 2000).
typedef BOOL (WINAPI *PrintWindowPointer)(HWND, HDC, UINT); typedef BOOL (WINAPI *PrintWindowPointer)(HWND, HDC, UINT);
...@@ -54,22 +68,24 @@ gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window_handle, ...@@ -54,22 +68,24 @@ gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window_handle,
// Otherwise grab the bits we can get with BitBlt; it's better // Otherwise grab the bits we can get with BitBlt; it's better
// than nothing and will work fine in the average case (window is // than nothing and will work fine in the average case (window is
// completely on screen). // completely on screen).
if (print_window) if (snapshot_bounds.origin() == gfx::Point() && print_window)
(*print_window)(window_handle, mem_hdc, 0); (*print_window)(window_handle, mem_hdc, 0);
else else
BitBlt(mem_hdc, 0, 0, width, height, window_hdc, 0, 0, SRCCOPY); BitBlt(mem_hdc, 0, 0, snapshot_bounds.width(), snapshot_bounds.height(),
window_hdc, snapshot_bounds.x(), snapshot_bounds.y(), SRCCOPY);
// We now have a copy of the window contents in a DIB, so // We now have a copy of the window contents in a DIB, so
// encode it into a useful format for posting to the bug report // encode it into a useful format for posting to the bug report
// server. // server.
gfx::PNGCodec::Encode(bit_ptr, gfx::PNGCodec::FORMAT_BGRA, gfx::PNGCodec::Encode(bit_ptr, gfx::PNGCodec::FORMAT_BGRA,
gfx::Size(width, height), width * 4, true, snapshot_bounds.size(),
snapshot_bounds.width() * 4, true,
std::vector<gfx::PNGCodec::Comment>(), std::vector<gfx::PNGCodec::Comment>(),
png_representation); png_representation);
ReleaseDC(window_handle, window_hdc); ReleaseDC(window_handle, window_hdc);
return gfx::Rect(width, height); return true;
} }
} // namespace browser } // namespace browser
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment