| 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
|
|
|