Index: ui/views/cocoa/bridged_native_widget.mm |
diff --git a/ui/views/cocoa/bridged_native_widget.mm b/ui/views/cocoa/bridged_native_widget.mm |
index 2a959daf9e139a6b5ccccc869ba79aa40d727c1c..34d724ca9fbf4de9ae6333e930b4c3e8b3691518 100644 |
--- a/ui/views/cocoa/bridged_native_widget.mm |
+++ b/ui/views/cocoa/bridged_native_widget.mm |
@@ -8,6 +8,9 @@ |
#include "ui/base/ime/input_method.h" |
#include "ui/base/ime/input_method_factory.h" |
#include "ui/base/ui_base_switches_util.h" |
+#include "ui/gfx/display.h" |
+#import "ui/gfx/mac/coordinate_conversion.h" |
+#include "ui/gfx/screen.h" |
#import "ui/views/cocoa/bridged_content_view.h" |
#import "ui/views/cocoa/views_nswindow_delegate.h" |
#include "ui/views/widget/native_widget_mac.h" |
@@ -16,6 +19,25 @@ |
#include "ui/views/view.h" |
#include "ui/views/widget/widget.h" |
+#include "cc/output/copy_output_request.h" |
+#include "cc/output/copy_output_result.h" |
+ |
+#include "third_party/skia/include/core/SkBitmap.h" |
+#include "ui/gfx/codec/png_codec.h" |
+#include "ui/gfx/image/image_skia_rep.h" |
+#include "ui/gfx/canvas.h" |
+ |
+namespace { |
+ |
+float GetDeviceScaleFactorFromDisplay(NSView* view) { |
+ gfx::Display display = gfx::Screen::GetScreenFor(view)-> |
+ GetDisplayNearestWindow(view); |
+ DCHECK(display.is_valid()); |
+ return display.device_scale_factor(); |
+} |
+ |
+} // namespace |
+ |
namespace views { |
BridgedNativeWidget::BridgedNativeWidget(NativeWidgetMac* parent) |
@@ -64,10 +86,22 @@ void BridgedNativeWidget::SetFocusManager(FocusManager* focus_manager) { |
focus_manager_ = focus_manager; |
} |
+void BridgedNativeWidget::SetBounds(const gfx::Rect& new_bounds) { |
+ [window_ setFrame:gfx::ScreenRectToNSRect(new_bounds) |
+ display:YES |
+ animate:NO]; |
+ if (layer()) |
+ SetLayerSize(new_bounds.size()); |
+} |
+ |
void BridgedNativeWidget::SetRootView(views::View* view) { |
if (view == [bridged_view_ hostedView]) |
return; |
+ // If this is ever false, the compositor will need to be properly torn down |
+ // and replaced, pointing at the new view. |
+ DCHECK(!view || !compositor_view_); |
+ |
[bridged_view_ clearView]; |
bridged_view_.reset(); |
// Note that there can still be references to the old |bridged_view_| |
@@ -105,6 +139,34 @@ ui::InputMethod* BridgedNativeWidget::GetHostInputMethod() { |
return input_method_.get(); |
} |
+ui::Layer* BridgedNativeWidget::GetOrCreateLayer() { |
+ if (!bridged_view_) |
+ return NULL; |
+ |
+ if (layer()) |
+ return layer(); |
+ |
+ [bridged_view_ setWantsLayer:YES]; |
+ // Next line does nothing. |
+ [[bridged_view_ layer] |
+ setBackgroundColor:CGColorGetConstantColor(kCGColorClear)]; |
+ |
+ SetLayer(new ui::Layer()); |
+ layer()->set_delegate(this); |
+ DCHECK_EQ(0u, [[bridged_view_ subviews] count]); |
+ compositor_view_.reset(new content::BrowserCompositorViewMac(this)); |
+ |
+ DCHECK(compositor_view_->GetCompositor()); |
+ DCHECK_EQ(compositor_view_->GetCompositor(), layer()->GetCompositor()); |
+ |
+ [window_ setOpaque:NO]; |
+ layer()->GetCompositor()->SetHostHasTransparentBackground(true); |
+ layer()->SetFillsBoundsCompletely(true); |
+ |
+ SetLayerSize(native_widget_mac_->GetWindowBoundsInScreen().size()); |
+ return layer(); |
+} |
+ |
//////////////////////////////////////////////////////////////////////////////// |
// BridgedNativeWidget, internal::InputMethodDelegate: |
@@ -117,6 +179,24 @@ void BridgedNativeWidget::DispatchKeyEventPostIME(const ui::KeyEvent& key) { |
focus_manager_->OnKeyEvent(key); |
} |
+//////////////////////////////////////////////////////////////////////////////// |
+// BridgedNativeWidget, content::BrowserCompositorViewMacClient: |
+ |
+void BridgedNativeWidget::BrowserCompositorViewFrameSwapped( |
+ const std::vector<ui::LatencyInfo>& latency_info) { |
+} |
+ |
+NSView* BridgedNativeWidget::BrowserCompositorSuperview() { |
+ return bridged_view_; |
+} |
+ |
+ui::Layer* BridgedNativeWidget::BrowserCompositorRootLayer() { |
+ return layer(); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// BridgedNativeWidget, FocusChangeListener: |
+ |
void BridgedNativeWidget::OnWillChangeFocus(View* focused_before, |
View* focused_now) { |
} |
@@ -129,6 +209,54 @@ void BridgedNativeWidget::OnDidChangeFocus(View* focused_before, |
} |
//////////////////////////////////////////////////////////////////////////////// |
+// BridgedNativeWidget, LayerDelegate: |
+ |
+static bool WritePNGFile(const SkBitmap& bitmap, const base::FilePath& file_path, |
+ bool discard_transparency) { |
+ std::vector<unsigned char> png_data; |
+ if (gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, |
+ discard_transparency, |
+ &png_data) && |
+ base::CreateDirectory(file_path.DirName())) { |
+ char* data = reinterpret_cast<char*>(&png_data[0]); |
+ int size = static_cast<int>(png_data.size()); |
+ bool result = base::WriteFile(file_path, data, size) == size; |
+ return result; |
+ } |
+ return false; |
+} |
+ |
+static void ReadbackResult(scoped_ptr<cc::CopyOutputResult> result) { |
+ DLOG(INFO) << "result!"; |
+ scoped_ptr<SkBitmap> result_bitmap = result->TakeBitmap().Pass(); |
+ static int filectr = 0; |
+ std::ostringstream oss; |
+ oss << "file" << filectr++ << ".png"; |
+ WritePNGFile(*result_bitmap, base::FilePath().AppendASCII(oss.str().c_str()), false); |
+} |
+ |
+void BridgedNativeWidget::OnPaintLayer(gfx::Canvas* canvas) { |
+ layer()->RequestCopyOfOutput(cc::CopyOutputRequest::CreateBitmapRequest(base::Bind(&ReadbackResult))); |
+ native_widget_mac_->GetWidget()->OnNativeWidgetPaint(canvas); |
+ |
+ gfx::ImageSkiaRep image = canvas->ExtractImageRep(); |
+ static int filectr = 0; |
+ std::ostringstream oss; |
+ oss << "bpass" << filectr++ << ".png"; |
+ WritePNGFile(image.sk_bitmap(), base::FilePath().AppendASCII(oss.str().c_str()), false); |
+ |
+} |
+ |
+void BridgedNativeWidget::OnDeviceScaleFactorChanged( |
+ float device_scale_factor) { |
+} |
+ |
+base::Closure BridgedNativeWidget::PrepareForLayerBoundsChange() { |
+ return base::Bind(&BridgedNativeWidget::OnWindowBoundsChanged, |
+ base::Unretained(this)); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
// BridgedNativeWidget, private: |
void BridgedNativeWidget::RemoveOrDestroyChildren() { |
@@ -138,4 +266,19 @@ void BridgedNativeWidget::RemoveOrDestroyChildren() { |
[child_windows makeObjectsPerformSelector:@selector(close)]; |
} |
+void BridgedNativeWidget::SetLayerSize(const gfx::Size& size_in_dip) { |
+ DCHECK(layer()); |
+ |
+ layer()->SetBounds(gfx::Rect(size_in_dip)); |
+ |
+ float scale_factor = GetDeviceScaleFactorFromDisplay(bridged_view_); |
+ gfx::Size size_in_pixels(size_in_dip.width() * scale_factor, |
+ size_in_dip.height() * scale_factor); |
+ compositor_view_->GetCompositor()->SetScaleAndSize(scale_factor, |
+ size_in_pixels); |
+} |
+ |
+void BridgedNativeWidget::OnWindowBoundsChanged() { |
+} |
+ |
} // namespace views |