diff options
7 files changed, 91 insertions, 43 deletions
diff --git a/chrome/browser/ui/webui/bug_report_ui.cc b/chrome/browser/ui/webui/bug_report_ui.cc index d9abc7e..e7b0c89 100644 --- a/chrome/browser/ui/webui/bug_report_ui.cc +++ b/chrome/browser/ui/webui/bug_report_ui.cc @@ -139,8 +139,11 @@ void ShowHtmlBugReportView(Browser* browser, last_screenshot_png->clear(); gfx::NativeWindow native_window = browser->window()->GetNativeHandle(); - BugReportUtil::SetScreenshotSize( - browser::GrabWindowSnapshot(native_window, last_screenshot_png)); + gfx::Rect snapshot_bounds = gfx::Rect(browser->window()->GetBounds().size()); + 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) + "#" + base::IntToString(browser->active_index()) + diff --git a/chrome/browser/ui/window_snapshot/window_snapshot.h b/chrome/browser/ui/window_snapshot/window_snapshot.h index 5178662..86884af 100644 --- a/chrome/browser/ui/window_snapshot/window_snapshot.h +++ b/chrome/browser/ui/window_snapshot/window_snapshot.h @@ -16,10 +16,12 @@ namespace gfx { namespace browser { -// Grabs a snapshot of the designated window and stores a PNG representation -// into a byte vector. Returns the image bounds. -gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window, - std::vector<unsigned char>* png_representation); +// Grabs a snapshot of the rectangle area |snapshot_bounds| with respect to the +// top left corner of the designated window and stores a PNG representation +// into a byte vector. Returns true if the operation is successful. +bool GrabWindowSnapshot(gfx::NativeWindow window, + std::vector<unsigned char>* png_representation, + const gfx::Rect& snapshot_bounds); } // namespace browser diff --git a/chrome/browser/ui/window_snapshot/window_snapshot_aura.cc b/chrome/browser/ui/window_snapshot/window_snapshot_aura.cc index 843c89c..3a65213 100644 --- a/chrome/browser/ui/window_snapshot/window_snapshot_aura.cc +++ b/chrome/browser/ui/window_snapshot/window_snapshot_aura.cc @@ -9,11 +9,12 @@ namespace browser { -gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window_handle, - std::vector<unsigned char>* png_representation) { +bool GrabWindowSnapshot(gfx::NativeWindow window_handle, + std::vector<unsigned char>* png_representation, + const gfx::Rect& snapshot_bounds) { // TODO(saintlou): Stub for Aura. NOTIMPLEMENTED(); - return gfx::Rect(); + return false; } } // namespace browser diff --git a/chrome/browser/ui/window_snapshot/window_snapshot_gtk.cc b/chrome/browser/ui/window_snapshot/window_snapshot_gtk.cc index 4507996..ded3dfd 100644 --- a/chrome/browser/ui/window_snapshot/window_snapshot_gtk.cc +++ b/chrome/browser/ui/window_snapshot/window_snapshot_gtk.cc @@ -24,25 +24,32 @@ static cairo_status_t SnapshotCallback( return CAIRO_STATUS_SUCCESS; } -gfx::Rect GrabWindowSnapshot(gfx::NativeWindow gtk_window, - std::vector<unsigned char>* png_representation) { - GdkWindow* gdk_window = GTK_WIDGET(gtk_window)->window; +bool GrabWindowSnapshot(gfx::NativeWindow window_handle, + std::vector<unsigned char>* png_representation, + const gfx::Rect& snapshot_bounds) { + GdkWindow* gdk_window = GTK_WIDGET(window_handle)->window; Display* display = GDK_WINDOW_XDISPLAY(gdk_window); XID win = GDK_WINDOW_XID(gdk_window); - XWindowAttributes attr; - if (XGetWindowAttributes(display, win, &attr) == 0) { - LOG(ERROR) << "Couldn't get window attributes"; - return gfx::Rect(); + + gfx::Rect window_bounds; + if (ui::GetWindowRect(win, &window_bounds) == 0) { + 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( - 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) { LOG(ERROR) << "Couldn't get image"; - return gfx::Rect(); + return false; } if (image->depth != 24) { LOG(ERROR)<< "Unsupported image depth " << image->depth; - return gfx::Rect(); + return false; } cairo_surface_t* surface = cairo_image_surface_create_for_data( @@ -54,13 +61,13 @@ gfx::Rect GrabWindowSnapshot(gfx::NativeWindow gtk_window, if (!surface) { LOG(ERROR) << "Unable to create Cairo surface from XImage data"; - return gfx::Rect(); + return false; } cairo_surface_write_to_png_stream( surface, SnapshotCallback, png_representation); cairo_surface_destroy(surface); - return gfx::Rect(image->width, image->height); + return true; } } // namespace browser diff --git a/chrome/browser/ui/window_snapshot/window_snapshot_mac.mm b/chrome/browser/ui/window_snapshot/window_snapshot_mac.mm index ab79087..b31baa0 100644 --- a/chrome/browser/ui/window_snapshot/window_snapshot_mac.mm +++ b/chrome/browser/ui/window_snapshot/window_snapshot_mac.mm @@ -13,18 +13,36 @@ namespace browser { -gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window, - std::vector<unsigned char>* png_representation) { +bool GrabWindowSnapshot(gfx::NativeWindow window, + 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(); // Make sure to grab the "window frame" view so we get current tab + // tabstrip. NSView* view = [[window contentView] superview]; base::mac::ScopedCFTypeRef<CGImageRef> windowSnapshot(CGWindowListCreateImage( - CGRectNull, kCGWindowListOptionIncludingWindow, + screen_snapshot_bounds.ToCGRect(), kCGWindowListOptionIncludingWindow, [[view window] windowNumber], kCGWindowImageBoundsIgnoreFraming)); if (CGImageGetWidth(windowSnapshot) <= 0) - return gfx::Rect(); + return false; scoped_nsobject<NSBitmapImageRep> rep( [[NSBitmapImageRep alloc] initWithCGImage:windowSnapshot]); @@ -32,13 +50,12 @@ gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window, const unsigned char* buf = static_cast<const unsigned char*>([data bytes]); NSUInteger length = [data length]; if (buf == NULL || length == 0) - return gfx::Rect(); + return false; png_representation->assign(buf, buf + length); DCHECK(!png_representation->empty()); - return gfx::Rect(static_cast<int>([rep pixelsWide]), - static_cast<int>([rep pixelsHigh])); + return true; } } // namespace browser diff --git a/chrome/browser/ui/window_snapshot/window_snapshot_mac_unittest.mm b/chrome/browser/ui/window_snapshot/window_snapshot_mac_unittest.mm index 5a41fd1..7641891 100644 --- a/chrome/browser/ui/window_snapshot/window_snapshot_mac_unittest.mm +++ b/chrome/browser/ui/window_snapshot/window_snapshot_mac_unittest.mm @@ -30,7 +30,9 @@ TEST_F(GrabWindowSnapshotTest, TestGrabWindowSnapshot) { scoped_ptr<std::vector<unsigned char> > png_representation( 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. scoped_nsobject<NSData> image_data( diff --git a/chrome/browser/ui/window_snapshot/window_snapshot_win.cc b/chrome/browser/ui/window_snapshot/window_snapshot_win.cc index 2d30dad..f3c5269 100644 --- a/chrome/browser/ui/window_snapshot/window_snapshot_win.cc +++ b/chrome/browser/ui/window_snapshot/window_snapshot_win.cc @@ -12,22 +12,35 @@ #include "ui/gfx/rect.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 { -gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window_handle, - std::vector<unsigned char>* png_representation) { +bool GrabWindowSnapshot(gfx::NativeWindow window_handle, + 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. HDC window_hdc = GetWindowDC(window_handle); 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; - gfx::CreateBitmapHeader(width, height, &hdr); + gfx::CreateBitmapHeader(snapshot_bounds.width(), + snapshot_bounds.height(), + &hdr); unsigned char *bit_ptr = NULL; base::win::ScopedBitmap bitmap( CreateDIBSection(mem_hdc, @@ -41,7 +54,8 @@ gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window_handle, // show up on a white background, and strangely-shaped windows // look reasonable). Not capturing an alpha mask saves a // 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 // First, see if PrintWindow is defined (it's not in Windows 2000). typedef BOOL (WINAPI *PrintWindowPointer)(HWND, HDC, UINT); @@ -54,22 +68,24 @@ gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window_handle, // Otherwise grab the bits we can get with BitBlt; it's better // than nothing and will work fine in the average case (window is // completely on screen). - if (print_window) + if (snapshot_bounds.origin() == gfx::Point() && print_window) (*print_window)(window_handle, mem_hdc, 0); 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 // encode it into a useful format for posting to the bug report // server. 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>(), png_representation); ReleaseDC(window_handle, window_hdc); - return gfx::Rect(width, height); + return true; } } // namespace browser |