1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ui/snapshot/snapshot.h" 6 7 #import <Cocoa/Cocoa.h> 8 9 #include "base/callback.h" 10 #include "base/logging.h" 11 #include "base/mac/scoped_cftyperef.h" 12 #include "base/mac/scoped_nsobject.h" 13 #include "base/task_runner.h" 14 #include "ui/gfx/image/image.h" 15 #include "ui/gfx/rect.h" 16 17 namespace ui { 18 19 bool GrabViewSnapshot(gfx::NativeView view, 20 std::vector<unsigned char>* png_representation, 21 const gfx::Rect& snapshot_bounds) { 22 NSWindow* window = [view window]; 23 NSScreen* screen = [[NSScreen screens] objectAtIndex:0]; 24 gfx::Rect screen_bounds = gfx::Rect(NSRectToCGRect([screen frame])); 25 26 27 // Get the view bounds relative to the screen 28 NSRect frame = [view convertRect:[view bounds] toView:nil]; 29 frame.origin = [window convertBaseToScreen:frame.origin]; 30 31 gfx::Rect view_bounds = gfx::Rect(NSRectToCGRect(frame)); 32 33 // Flip window coordinates based on the primary screen. 34 view_bounds.set_y( 35 screen_bounds.height() - view_bounds.y() - view_bounds.height()); 36 37 // Convert snapshot bounds relative to window into bounds relative to 38 // screen. 39 gfx::Rect screen_snapshot_bounds = snapshot_bounds; 40 screen_snapshot_bounds.Offset(view_bounds.OffsetFromOrigin()); 41 42 DCHECK_LE(screen_snapshot_bounds.right(), view_bounds.right()); 43 DCHECK_LE(screen_snapshot_bounds.bottom(), view_bounds.bottom()); 44 45 png_representation->clear(); 46 47 base::ScopedCFTypeRef<CGImageRef> windowSnapshot( 48 CGWindowListCreateImage(screen_snapshot_bounds.ToCGRect(), 49 kCGWindowListOptionIncludingWindow, 50 [window windowNumber], 51 kCGWindowImageBoundsIgnoreFraming)); 52 if (CGImageGetWidth(windowSnapshot) <= 0) 53 return false; 54 55 base::scoped_nsobject<NSBitmapImageRep> rep( 56 [[NSBitmapImageRep alloc] initWithCGImage:windowSnapshot]); 57 NSData* data = [rep representationUsingType:NSPNGFileType properties:nil]; 58 const unsigned char* buf = static_cast<const unsigned char*>([data bytes]); 59 NSUInteger length = [data length]; 60 if (buf == NULL || length == 0) 61 return false; 62 63 png_representation->assign(buf, buf + length); 64 DCHECK(!png_representation->empty()); 65 66 return true; 67 } 68 69 bool GrabWindowSnapshot(gfx::NativeWindow window, 70 std::vector<unsigned char>* png_representation, 71 const gfx::Rect& snapshot_bounds) { 72 // Make sure to grab the "window frame" view so we get current tab + 73 // tabstrip. 74 return GrabViewSnapshot([[window contentView] superview], png_representation, 75 snapshot_bounds); 76 } 77 78 void GrabWindowSnapshotAndScaleAsync( 79 gfx::NativeWindow window, 80 const gfx::Rect& snapshot_bounds, 81 const gfx::Size& target_size, 82 scoped_refptr<base::TaskRunner> background_task_runner, 83 GrabWindowSnapshotAsyncCallback callback) { 84 callback.Run(gfx::Image()); 85 } 86 87 void GrabViewSnapshotAsync( 88 gfx::NativeView view, 89 const gfx::Rect& source_rect, 90 scoped_refptr<base::TaskRunner> background_task_runner, 91 const GrabWindowSnapshotAsyncPNGCallback& callback) { 92 callback.Run(scoped_refptr<base::RefCountedBytes>()); 93 } 94 95 void GrabWindowSnapshotAsync( 96 gfx::NativeWindow window, 97 const gfx::Rect& source_rect, 98 scoped_refptr<base::TaskRunner> background_task_runner, 99 const GrabWindowSnapshotAsyncPNGCallback& callback) { 100 return GrabViewSnapshotAsync([[window contentView] superview], source_rect, 101 background_task_runner, callback); 102 } 103 104 } // namespace ui 105