diff options
author | msw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-03 06:01:16 +0000 |
---|---|---|
committer | msw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-03 06:01:16 +0000 |
commit | 75b6805083c906bb17192a738b311bd21791e9f8 (patch) | |
tree | bce38efec20d50a7ef55a694f58036ae365d5e0a /chrome/browser/ui/window_snapshot | |
parent | 2aa8b71eb688aa13a4f745027bcd4bb726bf6663 (diff) | |
download | chromium_src-75b6805083c906bb17192a738b311bd21791e9f8.zip chromium_src-75b6805083c906bb17192a738b311bd21791e9f8.tar.gz chromium_src-75b6805083c906bb17192a738b311bd21791e9f8.tar.bz2 |
Cross-platform CL to remove app/win/win_util.h&cc and related work.
See Issue 70141 for the full move details; see my inline review comments.
Changes significantly different from or beyond those prescribed by the bug:
*Consolidated a lot of GrabWindowSnapshot code.
*Moved EnsureRectIsVisibleInRect to views::internal namespace for test access.
*Moved app/win/win_util_unittest.cc to views/window/window_win_unittest.h
*Named ui/base/message_box_win.h instead of ui/base/message_box.h
*Made WindowWin::GetWindowTitleFont static; needed in static contexts.
*Denoted WindowWin::FrameTypeChanged as a Window override, moved code.
*Moved TestGrabWindowSnapshot into new file: chrome/browser/ui/window_snapshot/window_snapshot_mac_unittest.mm
BUG=70141
TEST=none
Review URL: http://codereview.chromium.org/6386009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73589 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/ui/window_snapshot')
5 files changed, 257 insertions, 0 deletions
diff --git a/chrome/browser/ui/window_snapshot/window_snapshot.h b/chrome/browser/ui/window_snapshot/window_snapshot.h new file mode 100755 index 0000000..3372009 --- /dev/null +++ b/chrome/browser/ui/window_snapshot/window_snapshot.h @@ -0,0 +1,26 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WINDOW_SNAPSHOT_WINDOW_SNAPSHOT_H_ +#define CHROME_BROWSER_UI_WINDOW_SNAPSHOT_WINDOW_SNAPSHOT_H_ +#pragma once + +#include <vector> + +#include "gfx/native_widget_types.h" + +namespace gfx { + class Rect; +} + +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); + +} // namespace browser + +#endif // CHROME_BROWSER_UI_WINDOW_SNAPSHOT_WINDOW_SNAPSHOT_H_ diff --git a/chrome/browser/ui/window_snapshot/window_snapshot_mac.mm b/chrome/browser/ui/window_snapshot/window_snapshot_mac.mm new file mode 100755 index 0000000..deb7220 --- /dev/null +++ b/chrome/browser/ui/window_snapshot/window_snapshot_mac.mm @@ -0,0 +1,44 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/window_snapshot/window_snapshot.h" + +#import <Cocoa/Cocoa.h> + +#include "base/logging.h" +#include "base/mac/scoped_cftyperef.h" +#include "base/scoped_nsobject.h" +#include "gfx/rect.h" + +namespace browser { + +gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window, + std::vector<unsigned char>* png_representation) { + 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, + [[view window] windowNumber], kCGWindowImageBoundsIgnoreFraming)); + if (CGImageGetWidth(windowSnapshot) <= 0) + return gfx::Rect(); + + scoped_nsobject<NSBitmapImageRep> rep( + [[NSBitmapImageRep alloc] initWithCGImage:windowSnapshot]); + NSData* data = [rep representationUsingType:NSPNGFileType properties:nil]; + const unsigned char* buf = static_cast<const unsigned char*>([data bytes]); + NSUInteger length = [data length]; + if (buf == NULL || length == 0) + return gfx::Rect(); + + png_representation->assign(buf, buf + length); + DCHECK(png_representation->size() > 0); + + return gfx::Rect(static_cast<int>([rep pixelsWide]), + static_cast<int>([rep pixelsHigh])); +} + +} // 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 new file mode 100755 index 0000000..a7a377b --- /dev/null +++ b/chrome/browser/ui/window_snapshot/window_snapshot_mac_unittest.mm @@ -0,0 +1,49 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/window_snapshot/window_snapshot.h" + +#import <Cocoa/Cocoa.h> + +#include "base/scoped_nsobject.h" +#include "base/scoped_ptr.h" +#include "base/test/mock_chrome_application_mac.h" +#include "gfx/rect.h" +#include "testing/platform_test.h" + +namespace browser { +namespace { + +typedef PlatformTest GrabWindowSnapshotTest; + +TEST_F(GrabWindowSnapshotTest, TestGrabWindowSnapshot) { + // Launch a test window so we can take a snapshot. + NSRect frame = NSMakeRect(0, 0, 400, 400); + scoped_nsobject<NSWindow> window( + [[NSWindow alloc] initWithContentRect:frame + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:NO]); + [window setBackgroundColor:[NSColor whiteColor]]; + [window makeKeyAndOrderFront:NSApp]; + + scoped_ptr<std::vector<unsigned char> > png_representation( + new std::vector<unsigned char>); + browser::GrabWindowSnapshot(window, png_representation.get()); + + // Copy png back into NSData object so we can make sure we grabbed a png. + scoped_nsobject<NSData> image_data( + [[NSData alloc] initWithBytes:&(*png_representation)[0] + length:png_representation->size()]); + NSBitmapImageRep* rep = [NSBitmapImageRep imageRepWithData:image_data.get()]; + EXPECT_TRUE([rep isKindOfClass:[NSBitmapImageRep class]]); + EXPECT_TRUE(CGImageGetWidth([rep CGImage]) == 400); + NSColor* color = [rep colorAtX:200 y:200]; + CGFloat red = 0, green = 0, blue = 0, alpha = 0; + [color getRed:&red green:&green blue:&blue alpha:&alpha]; + EXPECT_GE(red + green + blue, 3.0); +} + +} // namespace +} // namespace browser diff --git a/chrome/browser/ui/window_snapshot/window_snapshot_win.cc b/chrome/browser/ui/window_snapshot/window_snapshot_win.cc new file mode 100755 index 0000000..66e0071 --- /dev/null +++ b/chrome/browser/ui/window_snapshot/window_snapshot_win.cc @@ -0,0 +1,72 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/window_snapshot/window_snapshot.h" + +#include "base/win/scoped_gdi_object.h" +#include "base/win/scoped_hdc.h" +#include "gfx/codec/png_codec.h" +#include "gfx/gdi_util.h" +#include "gfx/rect.h" + +namespace browser { + +gfx::Rect GrabWindowSnapshot(gfx::NativeWindow window_handle, + std::vector<unsigned char>* png_representation) { + // Create a memory DC that's compatible with the window. + HDC window_hdc = GetWindowDC(window_handle); + base::win::ScopedHDC 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); + unsigned char *bit_ptr = NULL; + base::win::ScopedBitmap bitmap( + CreateDIBSection(mem_hdc, + reinterpret_cast<BITMAPINFO*>(&hdr), + DIB_RGB_COLORS, + reinterpret_cast<void **>(&bit_ptr), + NULL, 0)); + + SelectObject(mem_hdc, bitmap); + // Clear the bitmap to white (so that rounded corners on windows + // 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); + // 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); + PrintWindowPointer print_window = + reinterpret_cast<PrintWindowPointer>( + GetProcAddress(GetModuleHandle(L"User32.dll"), "PrintWindow")); + + // If PrintWindow is defined, use it. It will work on partially + // obscured windows, and works better for out of process sub-windows. + // 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) + (*print_window)(window_handle, mem_hdc, 0); + else + BitBlt(mem_hdc, 0, 0, width, height, window_hdc, 0, 0, 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, + width, height, width * 4, true, + png_representation); + + ReleaseDC(window_handle, window_hdc); + + return gfx::Rect(width, height); +} + +} // namespace browser diff --git a/chrome/browser/ui/window_snapshot/window_snapshot_x.cc b/chrome/browser/ui/window_snapshot/window_snapshot_x.cc new file mode 100755 index 0000000..48f8169 --- /dev/null +++ b/chrome/browser/ui/window_snapshot/window_snapshot_x.cc @@ -0,0 +1,66 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/window_snapshot/window_snapshot.h" + +#include <gdk/gdkx.h> +#include <gtk/gtk.h> + +#include "base/logging.h" +#include "gfx/rect.h" +#include "ui/base/x/x11_util.h" + +namespace browser { + +static cairo_status_t SnapshotCallback( + void *closure, const unsigned char *data, unsigned int length) { + std::vector<unsigned char>* png_representation = + static_cast<std::vector<unsigned char>*>(closure); + + size_t old_size = png_representation->size(); + png_representation->resize(old_size + length); + memcpy(&(*png_representation)[old_size], data, length); + 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; + 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(); + } + XImage* image = XGetImage( + display, win, 0, 0, attr.width, attr.height, AllPlanes, ZPixmap); + if (!image) { + LOG(ERROR) << "Couldn't get image"; + return gfx::Rect(); + } + if (image->depth != 24) { + LOG(ERROR)<< "Unsupported image depth " << image->depth; + return gfx::Rect(); + } + cairo_surface_t* surface = + cairo_image_surface_create_for_data( + reinterpret_cast<unsigned char*>(image->data), + CAIRO_FORMAT_RGB24, + image->width, + image->height, + image->bytes_per_line); + + if (!surface) { + LOG(ERROR) << "Unable to create Cairo surface from XImage data"; + return gfx::Rect(); + } + cairo_surface_write_to_png_stream( + surface, SnapshotCallback, png_representation); + cairo_surface_destroy(surface); + + return gfx::Rect(image->width, image->height); +} + +} // namespace browser |