Merge pull request #8839 from brenca/offscreen-child-window

Offscreen rendering enhancements
This commit is contained in:
Cheng Zhao 2017-05-11 20:52:47 +09:00 committed by GitHub
commit 1b1c663b32
16 changed files with 675 additions and 285 deletions

View file

@ -49,6 +49,7 @@
#include "chrome/browser/ssl/security_state_tab_helper.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/view_messages.h"
#include "content/public/browser/favicon_status.h"
@ -316,6 +317,9 @@ WebContents::WebContents(v8::Isolate* isolate, const mate::Dictionary& options)
else if (options.Get("offscreen", &b) && b)
type_ = OFF_SCREEN;
// Init embedder earlier
options.Get("embedder", &embedder_);
// Whether to enable DevTools.
options.Get("devTools", &enable_devtools_);
@ -340,7 +344,18 @@ WebContents::WebContents(v8::Isolate* isolate, const mate::Dictionary& options)
session->browser_context(), site_instance);
guest_delegate_.reset(new WebViewGuestDelegate);
params.guest_delegate = guest_delegate_.get();
web_contents = content::WebContents::Create(params);
if (embedder_ && embedder_->IsOffScreen()) {
auto* view = new OffScreenWebContentsView(false,
base::Bind(&WebContents::OnPaint, base::Unretained(this)));
params.view = view;
params.delegate_view = view;
web_contents = content::WebContents::Create(params);
view->SetWebContents(web_contents);
} else {
web_contents = content::WebContents::Create(params);
}
} else if (IsOffScreen()) {
bool transparent = false;
options.Get("transparent", &transparent);
@ -390,7 +405,7 @@ void WebContents::InitWithSessionAndOptions(v8::Isolate* isolate,
guest_delegate_->Initialize(this);
NativeWindow* owner_window = nullptr;
if (options.Get("embedder", &embedder_) && embedder_) {
if (embedder_) {
// New WebContents's owner_window is the embedder's owner_window.
auto relay =
NativeWindowRelay::FromWebContents(embedder_->web_contents());
@ -1404,18 +1419,16 @@ bool WebContents::SendIPCMessage(bool all_frames,
void WebContents::SendInputEvent(v8::Isolate* isolate,
v8::Local<v8::Value> input_event) {
const auto view = web_contents()->GetRenderWidgetHostView();
const auto view = static_cast<content::RenderWidgetHostViewBase*>(
web_contents()->GetRenderWidgetHostView());
if (!view)
return;
const auto host = view->GetRenderWidgetHost();
if (!host)
return;
int type = mate::GetWebInputEventType(isolate, input_event);
if (blink::WebInputEvent::isMouseEventType(type)) {
blink::WebMouseEvent mouse_event;
if (mate::ConvertFromV8(isolate, input_event, &mouse_event)) {
host->ForwardMouseEvent(mouse_event);
view->ProcessMouseEvent(mouse_event, ui::LatencyInfo());
return;
}
} else if (blink::WebInputEvent::isKeyboardEventType(type)) {
@ -1424,13 +1437,13 @@ void WebContents::SendInputEvent(v8::Isolate* isolate,
blink::WebInputEvent::NoModifiers,
ui::EventTimeForNow());
if (mate::ConvertFromV8(isolate, input_event, &keyboard_event)) {
host->ForwardKeyboardEvent(keyboard_event);
view->ProcessKeyboardEvent(keyboard_event);
return;
}
} else if (type == blink::WebInputEvent::MouseWheel) {
blink::WebMouseWheelEvent mouse_wheel_event;
if (mate::ConvertFromV8(isolate, input_event, &mouse_wheel_event)) {
host->ForwardWheelEvent(mouse_wheel_event);
view->ProcessMouseWheelEvent(mouse_wheel_event, ui::LatencyInfo());
return;
}
}
@ -1567,9 +1580,7 @@ bool WebContents::IsOffScreen() const {
}
void WebContents::OnPaint(const gfx::Rect& dirty_rect, const SkBitmap& bitmap) {
mate::Handle<NativeImage> image =
NativeImage::Create(isolate(), gfx::Image::CreateFrom1xBitmap(bitmap));
Emit("paint", dirty_rect, image);
Emit("paint", dirty_rect, gfx::Image::CreateFrom1xBitmap(bitmap));
}
void WebContents::StartPainting() {

View file

@ -147,6 +147,7 @@ class NativeWindow : public base::SupportsUserData,
virtual void SetMenu(AtomMenuModel* menu);
virtual void SetParentWindow(NativeWindow* parent);
virtual void SetBrowserView(NativeBrowserView* browser_view) = 0;
virtual gfx::NativeView GetNativeView() = 0;
virtual gfx::NativeWindow GetNativeWindow() = 0;
virtual gfx::AcceleratedWidget GetAcceleratedWidget() = 0;

View file

@ -89,6 +89,7 @@ class NativeWindowMac : public NativeWindow,
void SetContentProtection(bool enable) override;
void SetBrowserView(NativeBrowserView* browser_view) override;
void SetParentWindow(NativeWindow* parent) override;
gfx::NativeView GetNativeView() override;
gfx::NativeWindow GetNativeWindow() override;
gfx::AcceleratedWidget GetAcceleratedWidget() override;
void SetProgressBar(double progress, const ProgressState state) override;

View file

@ -1314,6 +1314,10 @@ void NativeWindowMac::SetParentWindow(NativeWindow* parent) {
[parent->GetNativeWindow() addChildWindow:window_ ordered:NSWindowAbove];
}
gfx::NativeView NativeWindowMac::GetNativeView() {
return inspectable_web_contents()->GetView()->GetNativeView();
}
gfx::NativeWindow NativeWindowMac::GetNativeWindow() {
return window_;
}

View file

@ -924,6 +924,10 @@ void NativeWindowViews::SetParentWindow(NativeWindow* parent) {
#endif
}
gfx::NativeView NativeWindowViews::GetNativeView() {
return window_->GetNativeView();
}
gfx::NativeWindow NativeWindowViews::GetNativeWindow() {
return window_->GetNativeWindow();
}

View file

@ -106,6 +106,7 @@ class NativeWindowViews : public NativeWindow,
void SetMenu(AtomMenuModel* menu_model) override;
void SetBrowserView(NativeBrowserView* browser_view) override;
void SetParentWindow(NativeWindow* parent) override;
gfx::NativeView GetNativeView() override;
gfx::NativeWindow GetNativeWindow() override;
void SetOverlayIcon(const gfx::Image& overlay,
const std::string& description) override;

View file

@ -4,6 +4,8 @@
#include "atom/browser/osr/osr_output_device.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/src/core/SkDevice.h"
#include "ui/gfx/skia_util.h"
@ -36,8 +38,11 @@ void OffScreenOutputDevice::Resize(
return;
}
if (transparent_)
bitmap_->eraseARGB(0, 0, 0, 0);
if (transparent_) {
bitmap_->eraseColor(SK_ColorTRANSPARENT);
} else {
bitmap_->eraseColor(SK_ColorWHITE);
}
canvas_.reset(new SkCanvas(*bitmap_));
}
@ -47,6 +52,17 @@ SkCanvas* OffScreenOutputDevice::BeginPaint(const gfx::Rect& damage_rect) {
DCHECK(bitmap_.get());
damage_rect_ = damage_rect;
SkIRect damage = SkIRect::MakeXYWH(
damage_rect_.x(),
damage_rect_.y(),
damage_rect_.width(),
damage_rect_.height());
if (transparent_) {
bitmap_->erase(SK_ColorTRANSPARENT, damage);
} else {
bitmap_->erase(SK_ColorWHITE, damage);
}
return canvas_.get();
}

View file

@ -17,6 +17,7 @@
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_frame_subscriber.h"
#include "content/browser/renderer_host/resize_lock.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/context_factory.h"
@ -27,6 +28,7 @@
#include "ui/events/latency_info.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/skbitmap_operations.h"
namespace atom {
@ -35,72 +37,87 @@ namespace {
const float kDefaultScaleFactor = 1.0;
const int kFrameRetryLimit = 2;
#if !defined(OS_MACOSX)
const int kResizeLockTimeoutMs = 67;
class AtomResizeLock : public content::ResizeLock {
public:
AtomResizeLock(OffScreenRenderWidgetHostView* host,
const gfx::Size new_size,
bool defer_compositor_lock)
: ResizeLock(new_size, defer_compositor_lock),
host_(host),
cancelled_(false),
weak_ptr_factory_(this) {
DCHECK(host_);
host_->HoldResize();
content::BrowserThread::PostDelayedTask(content::BrowserThread::UI,
FROM_HERE, base::Bind(&AtomResizeLock::CancelLock,
weak_ptr_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(kResizeLockTimeoutMs));
}
~AtomResizeLock() override {
CancelLock();
}
bool GrabDeferredLock() override {
return ResizeLock::GrabDeferredLock();
}
void UnlockCompositor() override {
ResizeLock::UnlockCompositor();
compositor_lock_ = NULL;
}
protected:
void LockCompositor() override {
ResizeLock::LockCompositor();
compositor_lock_ = host_->GetCompositor()->GetCompositorLock();
}
void CancelLock() {
if (cancelled_)
return;
cancelled_ = true;
UnlockCompositor();
host_->ReleaseResize();
}
private:
OffScreenRenderWidgetHostView* host_;
scoped_refptr<ui::CompositorLock> compositor_lock_;
bool cancelled_;
base::WeakPtrFactory<AtomResizeLock> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(AtomResizeLock);
};
#endif // !defined(OS_MACOSX)
} // namespace
class AtomCopyFrameGenerator {
public:
AtomCopyFrameGenerator(int frame_rate_threshold_ms,
OffScreenRenderWidgetHostView* view)
: frame_rate_threshold_ms_(frame_rate_threshold_ms),
view_(view),
frame_pending_(false),
frame_in_progress_(false),
AtomCopyFrameGenerator(OffScreenRenderWidgetHostView* view,
int frame_rate_threshold_us)
: view_(view),
frame_retry_count_(0),
next_frame_time_(base::TimeTicks::Now()),
frame_duration_(base::TimeDelta::FromMicroseconds(
frame_rate_threshold_us)),
weak_ptr_factory_(this) {
last_time_ = base::Time::Now();
}
void GenerateCopyFrame(
bool force_frame,
const gfx::Rect& damage_rect) {
if (force_frame && !frame_pending_)
frame_pending_ = true;
if (!frame_pending_)
return;
if (!damage_rect.IsEmpty())
pending_damage_rect_.Union(damage_rect);
if (frame_in_progress_)
return;
frame_in_progress_ = true;
const int64_t frame_rate_delta =
(base::TimeTicks::Now() - frame_start_time_).InMilliseconds();
if (frame_rate_delta < frame_rate_threshold_ms_) {
content::BrowserThread::PostDelayedTask(content::BrowserThread::UI,
FROM_HERE,
base::Bind(&AtomCopyFrameGenerator::InternalGenerateCopyFrame,
weak_ptr_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(
frame_rate_threshold_ms_ - frame_rate_delta));
return;
}
InternalGenerateCopyFrame();
}
bool frame_pending() const { return frame_pending_; }
void set_frame_rate_threshold_ms(int frame_rate_threshold_ms) {
frame_rate_threshold_ms_ = frame_rate_threshold_ms;
}
private:
void InternalGenerateCopyFrame() {
frame_pending_ = false;
frame_start_time_ = base::TimeTicks::Now();
void GenerateCopyFrame(const gfx::Rect& damage_rect) {
if (!view_->render_widget_host())
return;
const gfx::Rect damage_rect = pending_damage_rect_;
pending_damage_rect_.SetRect(0, 0, 0, 0);
std::unique_ptr<cc::CopyOutputRequest> request =
cc::CopyOutputRequest::CreateRequest(base::Bind(
cc::CopyOutputRequest::CreateBitmapRequest(base::Bind(
&AtomCopyFrameGenerator::CopyFromCompositingSurfaceHasResult,
weak_ptr_factory_.GetWeakPtr(),
damage_rect));
@ -109,6 +126,12 @@ class AtomCopyFrameGenerator {
view_->GetRootLayer()->RequestCopyOfOutput(std::move(request));
}
void set_frame_rate_threshold_us(int frame_rate_threshold_us) {
frame_duration_ = base::TimeDelta::FromMicroseconds(
frame_rate_threshold_us);
}
private:
void CopyFromCompositingSurfaceHasResult(
const gfx::Rect& damage_rect,
std::unique_ptr<cc::CopyOutputResult> result) {
@ -118,180 +141,62 @@ class AtomCopyFrameGenerator {
return;
}
if (result->HasTexture()) {
PrepareTextureCopyOutputResult(damage_rect, std::move(result));
return;
}
DCHECK(result->HasBitmap());
PrepareBitmapCopyOutputResult(damage_rect, std::move(result));
}
void PrepareTextureCopyOutputResult(
const gfx::Rect& damage_rect,
std::unique_ptr<cc::CopyOutputResult> result) {
DCHECK(result->HasTexture());
base::ScopedClosureRunner scoped_callback_runner(
base::Bind(&AtomCopyFrameGenerator::OnCopyFrameCaptureFailure,
weak_ptr_factory_.GetWeakPtr(),
damage_rect));
const gfx::Size& result_size = result->size();
SkIRect bitmap_size;
if (bitmap_)
bitmap_->getBounds(&bitmap_size);
if (!bitmap_ ||
bitmap_size.width() != result_size.width() ||
bitmap_size.height() != result_size.height()) {
bitmap_.reset(new SkBitmap);
bitmap_->allocN32Pixels(result_size.width(),
result_size.height(),
true);
if (bitmap_->drawsNothing())
return;
}
content::ImageTransportFactory* factory =
content::ImageTransportFactory::GetInstance();
display_compositor::GLHelper* gl_helper = factory->GetGLHelper();
if (!gl_helper)
return;
std::unique_ptr<SkAutoLockPixels> bitmap_pixels_lock(
new SkAutoLockPixels(*bitmap_));
uint8_t* pixels = static_cast<uint8_t*>(bitmap_->getPixels());
cc::TextureMailbox texture_mailbox;
std::unique_ptr<cc::SingleReleaseCallback> release_callback;
result->TakeTexture(&texture_mailbox, &release_callback);
DCHECK(texture_mailbox.IsTexture());
if (!texture_mailbox.IsTexture())
return;
ignore_result(scoped_callback_runner.Release());
gl_helper->CropScaleReadbackAndCleanMailbox(
texture_mailbox.mailbox(),
texture_mailbox.sync_token(),
result_size,
gfx::Rect(result_size),
result_size,
pixels,
kN32_SkColorType,
base::Bind(
&AtomCopyFrameGenerator::CopyFromCompositingSurfaceFinishedProxy,
weak_ptr_factory_.GetWeakPtr(),
base::Passed(&release_callback),
damage_rect,
base::Passed(&bitmap_),
base::Passed(&bitmap_pixels_lock)),
display_compositor::GLHelper::SCALER_QUALITY_FAST);
}
static void CopyFromCompositingSurfaceFinishedProxy(
base::WeakPtr<AtomCopyFrameGenerator> generator,
std::unique_ptr<cc::SingleReleaseCallback> release_callback,
const gfx::Rect& damage_rect,
std::unique_ptr<SkBitmap> bitmap,
std::unique_ptr<SkAutoLockPixels> bitmap_pixels_lock,
bool result) {
gpu::SyncToken sync_token;
if (result) {
display_compositor::GLHelper* gl_helper =
content::ImageTransportFactory::GetInstance()->GetGLHelper();
if (gl_helper)
gl_helper->GenerateSyncToken(&sync_token);
}
const bool lost_resource = !sync_token.HasData();
release_callback->Run(sync_token, lost_resource);
if (generator) {
generator->CopyFromCompositingSurfaceFinished(
damage_rect, std::move(bitmap), std::move(bitmap_pixels_lock),
result);
} else {
bitmap_pixels_lock.reset();
bitmap.reset();
}
}
void CopyFromCompositingSurfaceFinished(
const gfx::Rect& damage_rect,
std::unique_ptr<SkBitmap> bitmap,
std::unique_ptr<SkAutoLockPixels> bitmap_pixels_lock,
bool result) {
DCHECK(!bitmap_);
bitmap_ = std::move(bitmap);
if (result) {
OnCopyFrameCaptureSuccess(damage_rect, *bitmap_,
std::move(bitmap_pixels_lock));
} else {
bitmap_pixels_lock.reset();
OnCopyFrameCaptureFailure(damage_rect);
}
}
void PrepareBitmapCopyOutputResult(
const gfx::Rect& damage_rect,
std::unique_ptr<cc::CopyOutputResult> result) {
DCHECK(result->HasBitmap());
std::unique_ptr<SkBitmap> source = result->TakeBitmap();
DCHECK(source);
if (source) {
std::unique_ptr<SkAutoLockPixels> bitmap_pixels_lock(
new SkAutoLockPixels(*source));
OnCopyFrameCaptureSuccess(damage_rect, *source,
std::move(bitmap_pixels_lock));
base::AutoLock autolock(lock_);
std::shared_ptr<SkBitmap> bitmap(source.release());
base::TimeTicks now = base::TimeTicks::Now();
base::TimeDelta next_frame_in = next_frame_time_ - now;
if (next_frame_in > frame_duration_ / 4) {
next_frame_time_ += frame_duration_;
content::BrowserThread::PostDelayedTask(content::BrowserThread::UI,
FROM_HERE,
base::Bind(&AtomCopyFrameGenerator::OnCopyFrameCaptureSuccess,
weak_ptr_factory_.GetWeakPtr(),
damage_rect,
bitmap),
next_frame_in);
} else {
next_frame_time_ = now + frame_duration_;
OnCopyFrameCaptureSuccess(damage_rect, bitmap);
}
frame_retry_count_ = 0;
} else {
OnCopyFrameCaptureFailure(damage_rect);
}
}
void OnCopyFrameCaptureFailure(
const gfx::Rect& damage_rect) {
pending_damage_rect_.Union(damage_rect);
void OnCopyFrameCaptureFailure(const gfx::Rect& damage_rect) {
const bool force_frame = (++frame_retry_count_ <= kFrameRetryLimit);
OnCopyFrameCaptureCompletion(force_frame);
if (force_frame) {
// Retry with the same |damage_rect|.
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
base::Bind(&AtomCopyFrameGenerator::GenerateCopyFrame,
weak_ptr_factory_.GetWeakPtr(),
damage_rect));
}
}
void OnCopyFrameCaptureSuccess(
const gfx::Rect& damage_rect,
const SkBitmap& bitmap,
std::unique_ptr<SkAutoLockPixels> bitmap_pixels_lock) {
view_->OnPaint(damage_rect, bitmap);
if (frame_retry_count_ > 0)
frame_retry_count_ = 0;
OnCopyFrameCaptureCompletion(false);
std::shared_ptr<SkBitmap> bitmap) {
base::AutoLock lock(onPaintLock_);
view_->OnPaint(damage_rect, *bitmap);
}
void OnCopyFrameCaptureCompletion(bool force_frame) {
frame_in_progress_ = false;
if (frame_pending_) {
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
base::Bind(&AtomCopyFrameGenerator::GenerateCopyFrame,
weak_ptr_factory_.GetWeakPtr(),
force_frame,
gfx::Rect()));
}
}
int frame_rate_threshold_ms_;
base::Lock lock_;
base::Lock onPaintLock_;
OffScreenRenderWidgetHostView* view_;
base::Time last_time_;
base::TimeTicks frame_start_time_;
bool frame_pending_;
bool frame_in_progress_;
int frame_retry_count_;
std::unique_ptr<SkBitmap> bitmap_;
gfx::Rect pending_damage_rect_;
base::TimeTicks next_frame_time_;
base::TimeDelta frame_duration_;
base::WeakPtrFactory<AtomCopyFrameGenerator> weak_ptr_factory_;
@ -300,12 +205,15 @@ class AtomCopyFrameGenerator {
class AtomBeginFrameTimer : public cc::DelayBasedTimeSourceClient {
public:
AtomBeginFrameTimer(int frame_rate_threshold_ms,
AtomBeginFrameTimer(int frame_rate_threshold_us,
const base::Closure& callback)
: callback_(callback) {
time_source_.reset(new cc::DelayBasedTimeSource(
content::BrowserThread::GetTaskRunnerForThread(
content::BrowserThread::UI).get()));
time_source_->SetTimebaseAndInterval(
base::TimeTicks(),
base::TimeDelta::FromMicroseconds(frame_rate_threshold_us));
time_source_->SetClient(this);
}
@ -317,10 +225,10 @@ class AtomBeginFrameTimer : public cc::DelayBasedTimeSourceClient {
return time_source_->Active();
}
void SetFrameRateThresholdMs(int frame_rate_threshold_ms) {
void SetFrameRateThresholdUs(int frame_rate_threshold_us) {
time_source_->SetTimebaseAndInterval(
base::TimeTicks::Now(),
base::TimeDelta::FromMilliseconds(frame_rate_threshold_ms));
base::TimeDelta::FromMicroseconds(frame_rate_threshold_us));
}
private:
@ -338,24 +246,31 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
bool transparent,
const OnPaintCallback& callback,
content::RenderWidgetHost* host,
bool is_guest_view_hack,
OffScreenRenderWidgetHostView* parent_host_view,
NativeWindow* native_window)
: render_widget_host_(content::RenderWidgetHostImpl::From(host)),
parent_host_view_(parent_host_view),
popup_host_view_(nullptr),
child_host_view_(nullptr),
native_window_(native_window),
software_output_device_(nullptr),
transparent_(transparent),
callback_(callback),
parent_callback_(nullptr),
frame_rate_(60),
frame_rate_threshold_ms_(0),
frame_rate_threshold_us_(0),
last_time_(base::Time::Now()),
scale_factor_(kDefaultScaleFactor),
is_showing_(!render_widget_host_->is_hidden()),
size_(native_window->GetSize()),
painting_(true),
is_showing_(!render_widget_host_->is_hidden()),
is_destroyed_(false),
popup_position_(gfx::Rect()),
hold_resize_(false),
pending_resize_(false),
weak_ptr_factory_(this) {
DCHECK(render_widget_host_);
render_widget_host_->SetView(this);
bool is_guest_view_hack = parent_host_view_ != nullptr;
#if !defined(OS_MACOSX)
delegated_frame_host_ = base::MakeUnique<content::DelegatedFrameHost>(
AllocateFrameSinkId(is_guest_view_hack), this);
@ -383,6 +298,8 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
native_window_->AddObserver(this);
ResizeRootLayer();
render_widget_host_->SetView(this);
InstallTransparency();
}
OffScreenRenderWidgetHostView::~OffScreenRenderWidgetHostView() {
@ -400,8 +317,15 @@ OffScreenRenderWidgetHostView::~OffScreenRenderWidgetHostView() {
delegated_frame_host_->ResetCompositor();
#endif
if (copy_frame_generator_.get())
copy_frame_generator_.reset(NULL);
#if defined(OS_MACOSX)
DestroyPlatformWidget();
#else
delegated_frame_host_.reset(NULL);
compositor_.reset(NULL);
root_layer_.reset(NULL);
#endif
}
@ -419,7 +343,7 @@ void OffScreenRenderWidgetHostView::OnWindowClosed() {
void OffScreenRenderWidgetHostView::OnBeginFrameTimerTick() {
const base::TimeTicks frame_time = base::TimeTicks::Now();
const base::TimeDelta vsync_period =
base::TimeDelta::FromMilliseconds(frame_rate_threshold_ms_);
base::TimeDelta::FromMicroseconds(frame_rate_threshold_us_);
SendBeginFrame(frame_time, vsync_period);
}
@ -461,6 +385,17 @@ bool OffScreenRenderWidgetHostView::OnMessageReceived(
}
void OffScreenRenderWidgetHostView::InitAsChild(gfx::NativeView) {
DCHECK(parent_host_view_);
if (parent_host_view_->child_host_view_) {
parent_host_view_->child_host_view_->CancelWidget();
}
parent_host_view_->set_child_host_view(this);
parent_host_view_->Hide();
ResizeRootLayer();
Show();
}
content::RenderWidgetHost* OffScreenRenderWidgetHostView::GetRenderWidgetHost()
@ -470,14 +405,11 @@ content::RenderWidgetHost* OffScreenRenderWidgetHostView::GetRenderWidgetHost()
void OffScreenRenderWidgetHostView::SetSize(const gfx::Size& size) {
size_ = size;
ResizeRootLayer();
if (render_widget_host_)
render_widget_host_->WasResized();
GetDelegatedFrameHost()->WasResized();
WasResized();
}
void OffScreenRenderWidgetHostView::SetBounds(const gfx::Rect& new_bounds) {
SetSize(new_bounds.size());
}
gfx::Vector2dF OffScreenRenderWidgetHostView::GetLastScrollOffset() const {
@ -547,6 +479,9 @@ bool OffScreenRenderWidgetHostView::IsShowing() {
}
gfx::Rect OffScreenRenderWidgetHostView::GetViewBounds() const {
if (IsPopupWidget())
return popup_position_;
return gfx::Rect(size_);
}
@ -587,7 +522,7 @@ void OffScreenRenderWidgetHostView::OnSwapCompositorFrame(
if (!frame.render_pass_list.empty()) {
if (software_output_device_) {
if (!begin_frame_timer_.get()) {
if (!begin_frame_timer_.get() || IsPopupWidget()) {
software_output_device_->SetActive(painting_);
}
@ -601,7 +536,7 @@ void OffScreenRenderWidgetHostView::OnSwapCompositorFrame(
} else {
if (!copy_frame_generator_.get()) {
copy_frame_generator_.reset(
new AtomCopyFrameGenerator(frame_rate_threshold_ms_, this));
new AtomCopyFrameGenerator(this, frame_rate_threshold_us_));
}
// Determine the damage rectangle for the current frame. This is the same
@ -620,7 +555,7 @@ void OffScreenRenderWidgetHostView::OnSwapCompositorFrame(
// Request a copy of the last compositor frame which will eventually call
// OnPaint asynchronously.
copy_frame_generator_->GenerateCopyFrame(true, damage_rect);
copy_frame_generator_->GenerateCopyFrame(damage_rect);
}
}
}
@ -631,10 +566,25 @@ void OffScreenRenderWidgetHostView::ClearCompositorFrame() {
void OffScreenRenderWidgetHostView::InitAsPopup(
content::RenderWidgetHostView* parent_host_view, const gfx::Rect& pos) {
DCHECK_EQ(parent_host_view_, parent_host_view);
if (parent_host_view_->popup_host_view_) {
parent_host_view_->popup_host_view_->CancelWidget();
}
parent_host_view_->set_popup_host_view(this);
parent_host_view_->popup_bitmap_.reset(new SkBitmap);
parent_callback_ = base::Bind(&OffScreenRenderWidgetHostView::OnPopupPaint,
parent_host_view_->weak_ptr_factory_.GetWeakPtr());
popup_position_ = pos;
ResizeRootLayer();
Show();
}
void OffScreenRenderWidgetHostView::InitAsFullscreen(
content::RenderWidgetHostView *) {
content::RenderWidgetHostView *) {
}
void OffScreenRenderWidgetHostView::UpdateCursor(const content::WebCursor &) {
@ -656,6 +606,23 @@ void OffScreenRenderWidgetHostView::RenderProcessGone(base::TerminationStatus,
}
void OffScreenRenderWidgetHostView::Destroy() {
if (!is_destroyed_) {
is_destroyed_ = true;
if (parent_host_view_ != NULL) {
CancelWidget();
} else {
if (popup_host_view_)
popup_host_view_->CancelWidget();
popup_bitmap_.reset();
if (child_host_view_)
child_host_view_->CancelWidget();
for (auto guest_host_view : guest_host_views_)
guest_host_view->CancelWidget();
Hide();
}
}
delete this;
}
@ -692,6 +659,13 @@ void OffScreenRenderWidgetHostView::EndFrameSubscription() {
GetDelegatedFrameHost()->EndFrameSubscription();
}
void OffScreenRenderWidgetHostView::InitAsGuest(
content::RenderWidgetHostView* parent_host_view,
content::RenderWidgetHostViewGuest* guest_view) {
parent_host_view_->AddGuestHostView(this);
parent_host_view_->RegisterGuestViewFrameSwappedCallback(guest_view);
}
bool OffScreenRenderWidgetHostView::HasAcceleratedSurface(const gfx::Size &) {
return false;
}
@ -705,11 +679,35 @@ void OffScreenRenderWidgetHostView::ImeCompositionRangeChanged(
}
gfx::Size OffScreenRenderWidgetHostView::GetPhysicalBackingSize() const {
return size_;
return gfx::ConvertSizeToPixel(scale_factor_, GetRequestedRendererSize());
}
gfx::Size OffScreenRenderWidgetHostView::GetRequestedRendererSize() const {
return size_;
return GetDelegatedFrameHost()->GetRequestedRendererSize();
}
content::RenderWidgetHostViewBase*
OffScreenRenderWidgetHostView::CreateViewForWidget(
content::RenderWidgetHost* render_widget_host,
content::RenderWidgetHost* embedder_render_widget_host,
content::WebContentsView* web_contents_view) {
if (render_widget_host->GetView()) {
return static_cast<content::RenderWidgetHostViewBase*>(
render_widget_host->GetView());
}
OffScreenRenderWidgetHostView* embedder_host_view = nullptr;
if (embedder_render_widget_host) {
embedder_host_view = static_cast<OffScreenRenderWidgetHostView*>(
embedder_render_widget_host->GetView());
}
return new OffScreenRenderWidgetHostView(
transparent_,
callback_,
render_widget_host,
embedder_host_view,
native_window_);
}
#if !defined(OS_MACOSX)
@ -723,22 +721,29 @@ bool OffScreenRenderWidgetHostView::DelegatedFrameHostIsVisible() const {
SkColor OffScreenRenderWidgetHostView::DelegatedFrameHostGetGutterColor(
SkColor color) const {
if (render_widget_host_->delegate() &&
render_widget_host_->delegate()->IsFullscreenForCurrentTab()) {
return SK_ColorWHITE;
}
return color;
}
gfx::Size OffScreenRenderWidgetHostView::DelegatedFrameHostDesiredSizeInDIP()
const {
return size_;
return GetRootLayer()->bounds().size();
}
bool OffScreenRenderWidgetHostView::DelegatedFrameCanCreateResizeLock() const {
return false;
return !render_widget_host_->auto_resize_enabled();
}
std::unique_ptr<content::ResizeLock>
OffScreenRenderWidgetHostView::DelegatedFrameHostCreateResizeLock(
bool defer_compositor_lock) {
return nullptr;
return std::unique_ptr<content::ResizeLock>(new AtomResizeLock(
this,
DelegatedFrameHostDesiredSizeInDIP(),
defer_compositor_lock));
}
void OffScreenRenderWidgetHostView::DelegatedFrameHostResizeLockWasReleased() {
@ -795,6 +800,57 @@ bool OffScreenRenderWidgetHostView::TransformPointToCoordSpaceForView(
point, target_view, transformed_point);
}
void OffScreenRenderWidgetHostView::CancelWidget() {
if (render_widget_host_)
render_widget_host_->LostCapture();
Hide();
if (parent_host_view_) {
if (parent_host_view_->popup_host_view_ == this) {
parent_host_view_->set_popup_host_view(NULL);
parent_host_view_->popup_bitmap_.reset();
} else if (parent_host_view_->child_host_view_ == this) {
parent_host_view_->set_child_host_view(NULL);
parent_host_view_->Show();
} else {
parent_host_view_->RemoveGuestHostView(this);
}
parent_host_view_ = NULL;
}
if (render_widget_host_ && !is_destroyed_) {
is_destroyed_ = true;
// Results in a call to Destroy().
render_widget_host_->ShutdownAndDestroyWidget(true);
}
}
void OffScreenRenderWidgetHostView::AddGuestHostView(
OffScreenRenderWidgetHostView* guest_host) {
guest_host_views_.insert(guest_host);
}
void OffScreenRenderWidgetHostView::RemoveGuestHostView(
OffScreenRenderWidgetHostView* guest_host) {
guest_host_views_.erase(guest_host);
}
void OffScreenRenderWidgetHostView::RegisterGuestViewFrameSwappedCallback(
content::RenderWidgetHostViewGuest* guest_host_view) {
guest_host_view->RegisterFrameSwappedCallback(base::MakeUnique<base::Closure>(
base::Bind(&OffScreenRenderWidgetHostView::OnGuestViewFrameSwapped,
weak_ptr_factory_.GetWeakPtr(),
base::Unretained(guest_host_view))));
}
void OffScreenRenderWidgetHostView::OnGuestViewFrameSwapped(
content::RenderWidgetHostViewGuest* guest_host_view) {
InvalidateBounds(
gfx::ConvertRectToPixel(scale_factor_, guest_host_view->GetViewBounds()));
RegisterGuestViewFrameSwappedCallback(guest_host_view);
}
std::unique_ptr<cc::SoftwareOutputDevice>
OffScreenRenderWidgetHostView::CreateSoftwareOutputDevice(
ui::Compositor* compositor) {
@ -823,7 +879,7 @@ bool OffScreenRenderWidgetHostView::InstallTransparency() {
}
bool OffScreenRenderWidgetHostView::IsAutoResizeEnabled() const {
return false;
return render_widget_host_->auto_resize_enabled();
}
void OffScreenRenderWidgetHostView::SetNeedsBeginFrames(
@ -837,10 +893,147 @@ void OffScreenRenderWidgetHostView::SetNeedsBeginFrames(
}
}
void CopyBitmapTo(
const SkBitmap& destination,
const SkBitmap& source,
const gfx::Rect& pos) {
SkAutoLockPixels source_pixels_lock(source);
SkAutoLockPixels destination_pixels_lock(destination);
char* src = static_cast<char*>(source.getPixels());
char* dest = static_cast<char*>(destination.getPixels());
int pixelsize = source.bytesPerPixel();
if (pos.x() + pos.width() <= destination.width() &&
pos.y() + pos.height() <= destination.height()) {
for (int i = 0; i < pos.height(); i++) {
memcpy(dest + ((pos.y() + i) * destination.width() + pos.x()) * pixelsize,
src + (i * source.width()) * pixelsize,
pos.width() * pixelsize);
}
}
destination.notifyPixelsChanged();
}
void OffScreenRenderWidgetHostView::OnPaint(
const gfx::Rect& damage_rect, const SkBitmap& bitmap) {
TRACE_EVENT0("electron", "OffScreenRenderWidgetHostView::OnPaint");
callback_.Run(damage_rect, bitmap);
HoldResize();
if (parent_callback_) {
parent_callback_.Run(damage_rect, bitmap);
} else if (popup_host_view_ && popup_bitmap_.get()) {
gfx::Rect pos = popup_host_view_->popup_position_;
gfx::Rect damage(damage_rect);
damage.Union(pos);
SkBitmap copy = SkBitmapOperations::CreateTiledBitmap(bitmap,
pos.x(), pos.y(), pos.width(), pos.height());
CopyBitmapTo(bitmap, *popup_bitmap_, pos);
callback_.Run(damage, bitmap);
CopyBitmapTo(bitmap, copy, pos);
} else {
callback_.Run(damage_rect, bitmap);
}
ReleaseResize();
}
void OffScreenRenderWidgetHostView::OnPopupPaint(
const gfx::Rect& damage_rect, const SkBitmap& bitmap) {
if (popup_host_view_ && popup_bitmap_.get())
bitmap.deepCopyTo(popup_bitmap_.get());
InvalidateBounds(popup_host_view_->popup_position_);
}
void OffScreenRenderWidgetHostView::HoldResize() {
if (!hold_resize_)
hold_resize_ = true;
}
void OffScreenRenderWidgetHostView::ReleaseResize() {
if (!hold_resize_)
return;
hold_resize_ = false;
if (pending_resize_) {
pending_resize_ = false;
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
base::Bind(&OffScreenRenderWidgetHostView::WasResized,
weak_ptr_factory_.GetWeakPtr()));
}
}
void OffScreenRenderWidgetHostView::WasResized() {
if (hold_resize_) {
if (!pending_resize_)
pending_resize_ = true;
return;
}
ResizeRootLayer();
if (render_widget_host_)
render_widget_host_->WasResized();
GetDelegatedFrameHost()->WasResized();
}
void OffScreenRenderWidgetHostView::ProcessKeyboardEvent(
const content::NativeWebKeyboardEvent& event) {
if (!render_widget_host_)
return;
render_widget_host_->ForwardKeyboardEvent(event);
}
void OffScreenRenderWidgetHostView::ProcessMouseEvent(
const blink::WebMouseEvent& event,
const ui::LatencyInfo& latency) {
if (!IsPopupWidget()) {
if (popup_host_view_ &&
popup_host_view_->popup_position_.Contains(event.x, event.y)) {
blink::WebMouseEvent popup_event(event);
popup_event.x -= popup_host_view_->popup_position_.x();
popup_event.y -= popup_host_view_->popup_position_.y();
popup_event.windowX = popup_event.x;
popup_event.windowY = popup_event.y;
popup_host_view_->ProcessMouseEvent(popup_event, latency);
return;
}
}
if (!render_widget_host_)
return;
render_widget_host_->ForwardMouseEvent(event);
}
void OffScreenRenderWidgetHostView::ProcessMouseWheelEvent(
const blink::WebMouseWheelEvent& event,
const ui::LatencyInfo& latency) {
if (!IsPopupWidget()) {
if (popup_host_view_) {
if (popup_host_view_->popup_position_.Contains(event.x, event.y)) {
blink::WebMouseWheelEvent popup_event(event);
popup_event.x -= popup_host_view_->popup_position_.x();
popup_event.y -= popup_host_view_->popup_position_.y();
popup_event.windowX = popup_event.x;
popup_event.windowY = popup_event.y;
popup_host_view_->ProcessMouseWheelEvent(popup_event, latency);
return;
} else {
// Scrolling outside of the popup widget so destroy it.
// Execute asynchronously to avoid deleting the widget from inside some
// other callback.
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
base::Bind(&OffScreenRenderWidgetHostView::CancelWidget,
popup_host_view_->weak_ptr_factory_.GetWeakPtr()));
}
}
}
if (!render_widget_host_)
return;
render_widget_host_->ForwardWheelEvent(event);
}
void OffScreenRenderWidgetHostView::SetPainting(bool painting) {
@ -856,12 +1049,22 @@ bool OffScreenRenderWidgetHostView::IsPainting() const {
}
void OffScreenRenderWidgetHostView::SetFrameRate(int frame_rate) {
if (frame_rate <= 0)
frame_rate = 1;
if (frame_rate > 60)
frame_rate = 60;
if (parent_host_view_) {
if (parent_host_view_->GetFrameRate() == GetFrameRate())
return;
frame_rate_ = frame_rate;
frame_rate_ = parent_host_view_->GetFrameRate();
} else {
if (frame_rate <= 0)
frame_rate = 1;
if (frame_rate > 60)
frame_rate = 60;
frame_rate_ = frame_rate;
}
for (auto guest_host_view : guest_host_views_)
guest_host_view->SetFrameRate(frame_rate);
SetupFrameRate(true);
}
@ -886,36 +1089,38 @@ OffScreenRenderWidgetHostView::GetDelegatedFrameHost() const {
#endif
void OffScreenRenderWidgetHostView::SetupFrameRate(bool force) {
if (!force && frame_rate_threshold_ms_ != 0)
if (!force && frame_rate_threshold_us_ != 0)
return;
frame_rate_threshold_ms_ = 1000 / frame_rate_;
frame_rate_threshold_us_ = 1000000 / frame_rate_;
GetCompositor()->vsync_manager()->SetAuthoritativeVSyncInterval(
base::TimeDelta::FromMilliseconds(frame_rate_threshold_ms_));
base::TimeDelta::FromMicroseconds(frame_rate_threshold_us_));
if (copy_frame_generator_) {
copy_frame_generator_->set_frame_rate_threshold_ms(
frame_rate_threshold_ms_);
if (copy_frame_generator_.get()) {
copy_frame_generator_->set_frame_rate_threshold_us(
frame_rate_threshold_us_);
}
if (begin_frame_timer_) {
begin_frame_timer_->SetFrameRateThresholdMs(frame_rate_threshold_ms_);
if (begin_frame_timer_.get()) {
begin_frame_timer_->SetFrameRateThresholdUs(frame_rate_threshold_us_);
} else {
begin_frame_timer_.reset(new AtomBeginFrameTimer(
frame_rate_threshold_ms_,
frame_rate_threshold_us_,
base::Bind(&OffScreenRenderWidgetHostView::OnBeginFrameTimerTick,
weak_ptr_factory_.GetWeakPtr())));
}
}
void OffScreenRenderWidgetHostView::Invalidate() {
const gfx::Rect& bounds_in_pixels = GetViewBounds();
InvalidateBounds(GetViewBounds());
}
void OffScreenRenderWidgetHostView::InvalidateBounds(const gfx::Rect& bounds) {
if (software_output_device_) {
software_output_device_->OnPaint(bounds_in_pixels);
software_output_device_->OnPaint(bounds);
} else if (copy_frame_generator_) {
copy_frame_generator_->GenerateCopyFrame(true, bounds_in_pixels);
copy_frame_generator_->GenerateCopyFrame(bounds);
}
}
@ -925,7 +1130,11 @@ void OffScreenRenderWidgetHostView::ResizeRootLayer() {
const float orgScaleFactor = scale_factor_;
const bool scaleFactorDidChange = (orgScaleFactor != scale_factor_);
gfx::Size size = GetViewBounds().size();
gfx::Size size;
if (!IsPopupWidget())
size = GetViewBounds().size();
else
size = popup_position_.size();
if (!scaleFactorDidChange && size == GetRootLayer()->bounds().size())
return;

View file

@ -5,6 +5,7 @@
#ifndef ATOM_BROWSER_OSR_OSR_RENDER_WIDGET_HOST_VIEW_H_
#define ATOM_BROWSER_OSR_OSR_RENDER_WIDGET_HOST_VIEW_H_
#include <set>
#include <string>
#include <vector>
@ -20,10 +21,13 @@
#include "base/time/time.h"
#include "cc/output/compositor_frame.h"
#include "cc/scheduler/begin_frame_source.h"
#include "content/browser/frame_host/render_widget_host_view_guest.h"
#include "content/browser/renderer_host/delegated_frame_host.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/renderer_host/resize_lock.h"
#include "content/browser/web_contents/web_contents_view.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/compositor/compositor.h"
@ -69,7 +73,7 @@ class OffScreenRenderWidgetHostView
OffScreenRenderWidgetHostView(bool transparent,
const OnPaintCallback& callback,
content::RenderWidgetHost* render_widget_host,
bool is_guest_view_hack,
OffScreenRenderWidgetHostView* parent_host_view,
NativeWindow* native_window);
~OffScreenRenderWidgetHostView() override;
@ -139,6 +143,9 @@ class OffScreenRenderWidgetHostView
void BeginFrameSubscription(
std::unique_ptr<content::RenderWidgetHostViewFrameSubscriber>) override;
void EndFrameSubscription() override;
void InitAsGuest(
content::RenderWidgetHostView*,
content::RenderWidgetHostViewGuest*) override;
bool HasAcceleratedSurface(const gfx::Size &) override;
gfx::Rect GetBoundsInRootWindow(void) override;
void ImeCompositionRangeChanged(
@ -146,6 +153,11 @@ class OffScreenRenderWidgetHostView
gfx::Size GetPhysicalBackingSize() const override;
gfx::Size GetRequestedRendererSize() const override;
content::RenderWidgetHostViewBase* CreateViewForWidget(
content::RenderWidgetHost*,
content::RenderWidgetHost*,
content::WebContentsView*) override;
#if !defined(OS_MACOSX)
// content::DelegatedFrameHostClient:
int DelegatedFrameHostGetGpuMemoryBufferClientId(void) const;
@ -193,7 +205,32 @@ class OffScreenRenderWidgetHostView
void DestroyPlatformWidget();
#endif
void CancelWidget();
void AddGuestHostView(OffScreenRenderWidgetHostView* guest_host);
void RemoveGuestHostView(OffScreenRenderWidgetHostView* guest_host);
void RegisterGuestViewFrameSwappedCallback(
content::RenderWidgetHostViewGuest* guest_host_view);
void OnGuestViewFrameSwapped(
content::RenderWidgetHostViewGuest* guest_host_view);
void OnPaint(const gfx::Rect& damage_rect, const SkBitmap& bitmap);
void OnPopupPaint(const gfx::Rect& damage_rect, const SkBitmap& bitmap);
bool IsPopupWidget() const {
return popup_type_ != blink::WebPopupTypeNone;
}
void HoldResize();
void ReleaseResize();
void WasResized();
void ProcessKeyboardEvent(
const content::NativeWebKeyboardEvent& event) override;
void ProcessMouseEvent(const blink::WebMouseEvent& event,
const ui::LatencyInfo& latency) override;
void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event,
const ui::LatencyInfo& latency) override;
void SetPainting(bool painting);
bool IsPainting() const;
@ -206,6 +243,7 @@ class OffScreenRenderWidgetHostView
content::DelegatedFrameHost* GetDelegatedFrameHost() const;
void Invalidate();
void InvalidateBounds(const gfx::Rect&);
content::RenderWidgetHostImpl* render_widget_host() const
{ return render_widget_host_; }
@ -213,6 +251,14 @@ class OffScreenRenderWidgetHostView
gfx::Size size() const { return size_; }
float scale_factor() const { return scale_factor_; }
void set_popup_host_view(OffScreenRenderWidgetHostView* popup_view) {
popup_host_view_ = popup_view;
}
void set_child_host_view(OffScreenRenderWidgetHostView* child_view) {
child_host_view_ = child_view;
}
private:
void SetupFrameRate(bool force);
void ResizeRootLayer();
@ -221,23 +267,37 @@ class OffScreenRenderWidgetHostView
// Weak ptrs.
content::RenderWidgetHostImpl* render_widget_host_;
OffScreenRenderWidgetHostView* parent_host_view_;
OffScreenRenderWidgetHostView* popup_host_view_;
std::unique_ptr<SkBitmap> popup_bitmap_;
OffScreenRenderWidgetHostView* child_host_view_;
std::set<OffScreenRenderWidgetHostView*> guest_host_views_;
NativeWindow* native_window_;
OffScreenOutputDevice* software_output_device_;
const bool transparent_;
OnPaintCallback callback_;
OnPaintCallback parent_callback_;
int frame_rate_;
int frame_rate_threshold_ms_;
int frame_rate_threshold_us_;
base::Time last_time_;
float scale_factor_;
bool is_showing_;
gfx::Vector2dF last_scroll_offset_;
gfx::Size size_;
bool painting_;
bool is_showing_;
bool is_destroyed_;
gfx::Rect popup_position_;
bool hold_resize_;
bool pending_resize_;
std::unique_ptr<ui::Layer> root_layer_;
std::unique_ptr<ui::Compositor> compositor_;
std::unique_ptr<content::DelegatedFrameHost> delegated_frame_host_;

View file

@ -4,7 +4,11 @@
#include "atom/browser/osr/osr_web_contents_view.h"
#include "atom/common/api/api_messages.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/render_view_host.h"
#include "third_party/WebKit/public/platform/WebScreenInfo.h"
#include "ui/display/screen.h"
namespace atom {
@ -27,19 +31,33 @@ OffScreenWebContentsView::~OffScreenWebContentsView() {
void OffScreenWebContentsView::SetWebContents(
content::WebContents* web_contents) {
web_contents_ = web_contents;
RenderViewCreated(web_contents_->GetRenderViewHost());
}
#if !defined(OS_MACOSX)
gfx::NativeView OffScreenWebContentsView::GetNativeView() const {
return gfx::NativeView();
if (!web_contents_) return gfx::NativeView();
auto relay = NativeWindowRelay::FromWebContents(web_contents_);
if (!relay) return gfx::NativeView();
return relay->window->GetNativeView();
}
gfx::NativeView OffScreenWebContentsView::GetContentNativeView() const {
return gfx::NativeView();
if (!web_contents_) return gfx::NativeView();
auto relay = NativeWindowRelay::FromWebContents(web_contents_);
if (!relay) return gfx::NativeView();
return relay->window->GetNativeView();
}
gfx::NativeWindow OffScreenWebContentsView::GetTopLevelNativeWindow() const {
return gfx::NativeWindow();
if (!web_contents_) return gfx::NativeWindow();
auto relay = NativeWindowRelay::FromWebContents(web_contents_);
if (!relay) return gfx::NativeWindow();
return relay->window->GetNativeWindow();
}
#endif
@ -67,7 +85,7 @@ content::DropData* OffScreenWebContentsView::GetDropData() const {
}
gfx::Rect OffScreenWebContentsView::GetViewBounds() const {
return view_ ? view_->GetViewBounds() : gfx::Rect();
return GetView() ? GetView()->GetViewBounds() : gfx::Rect();
}
void OffScreenWebContentsView::CreateView(const gfx::Size& initial_size,
@ -77,20 +95,40 @@ void OffScreenWebContentsView::CreateView(const gfx::Size& initial_size,
content::RenderWidgetHostViewBase*
OffScreenWebContentsView::CreateViewForWidget(
content::RenderWidgetHost* render_widget_host, bool is_guest_view_hack) {
if (render_widget_host->GetView()) {
return static_cast<content::RenderWidgetHostViewBase*>(
render_widget_host->GetView());
}
auto relay = NativeWindowRelay::FromWebContents(web_contents_);
view_ = new OffScreenRenderWidgetHostView(
transparent_, callback_, render_widget_host,
is_guest_view_hack, relay->window.get());
return view_;
return new OffScreenRenderWidgetHostView(
transparent_,
callback_,
render_widget_host,
nullptr,
relay->window.get());
}
content::RenderWidgetHostViewBase*
OffScreenWebContentsView::CreateViewForPopupWidget(
content::RenderWidgetHost* render_widget_host) {
auto relay = NativeWindowRelay::FromWebContents(web_contents_);
view_ = new OffScreenRenderWidgetHostView(
transparent_, callback_, render_widget_host, false, relay->window.get());
return view_;
content::WebContentsImpl *web_contents_impl =
static_cast<content::WebContentsImpl*>(web_contents_);
OffScreenRenderWidgetHostView *view =
static_cast<OffScreenRenderWidgetHostView*>(
web_contents_impl->GetOuterWebContents()
? web_contents_impl->GetOuterWebContents()->GetRenderWidgetHostView()
: web_contents_impl->GetRenderWidgetHostView());
return new OffScreenRenderWidgetHostView(
transparent_,
callback_,
render_widget_host,
view,
relay->window.get());
}
void OffScreenWebContentsView::SetPageTitle(const base::string16& title) {
@ -98,8 +136,12 @@ void OffScreenWebContentsView::SetPageTitle(const base::string16& title) {
void OffScreenWebContentsView::RenderViewCreated(
content::RenderViewHost* host) {
if (view_)
view_->InstallTransparency();
if (GetView())
GetView()->InstallTransparency();
#if defined(OS_MACOSX)
host->Send(new AtomViewMsg_Offscreen(host->GetRoutingID()));
#endif
}
void OffScreenWebContentsView::RenderViewSwappedIn(
@ -111,14 +153,22 @@ void OffScreenWebContentsView::SetOverscrollControllerEnabled(bool enabled) {
void OffScreenWebContentsView::GetScreenInfo(
content::ScreenInfo* screen_info) const {
screen_info->rect = gfx::Rect(view_->size());
screen_info->available_rect = gfx::Rect(view_->size());
screen_info->depth = 24;
screen_info->depth_per_component = 8;
screen_info->device_scale_factor = view_->scale_factor();
screen_info->orientation_angle = 0;
screen_info->device_scale_factor = 1.0;
screen_info->orientation_type =
content::SCREEN_ORIENTATION_VALUES_LANDSCAPE_PRIMARY;
if (GetView()) {
screen_info->rect = gfx::Rect(GetView()->size());
screen_info->available_rect = gfx::Rect(GetView()->size());
} else {
const display::Display display =
display::Screen::GetScreen()->GetPrimaryDisplay();
screen_info->rect = display.bounds();
screen_info->available_rect = display.work_area();
}
}
#if defined(OS_MACOSX)
@ -152,4 +202,12 @@ void OffScreenWebContentsView::UpdateDragCursor(
blink::WebDragOperation operation) {
}
OffScreenRenderWidgetHostView* OffScreenWebContentsView::GetView() const {
if (web_contents_) {
return static_cast<OffScreenRenderWidgetHostView*>(
web_contents_->GetRenderViewHost()->GetWidget()->GetView());
}
return nullptr;
}
} // namespace atom

View file

@ -75,11 +75,12 @@ class OffScreenWebContentsView : public content::WebContentsView,
void PlatformDestroy();
#endif
OffScreenRenderWidgetHostView* GetView() const;
const bool transparent_;
OnPaintCallback callback_;
// Weak refs.
OffScreenRenderWidgetHostView* view_;
content::WebContents* web_contents_;
#if defined(OS_MACOSX)

View file

@ -35,6 +35,8 @@ IPC_MESSAGE_ROUTED3(AtomViewMsg_Message,
base::string16 /* channel */,
base::ListValue /* arguments */)
IPC_MESSAGE_ROUTED0(AtomViewMsg_Offscreen)
// Sent by the renderer when the draggable regions are updated.
IPC_MESSAGE_ROUTED1(AtomViewHostMsg_UpdateDraggableRegions,
std::vector<atom::DraggableRegion> /* regions */)

View file

@ -202,6 +202,11 @@ void Noop(char*, void*) {
NativeImage::NativeImage(v8::Isolate* isolate, const gfx::Image& image)
: image_(image) {
Init(isolate);
if (image_.HasRepresentation(gfx::Image::kImageRepSkia)) {
isolate->AdjustAmountOfExternalAllocatedMemory(
image_.ToImageSkia()->bitmap()->computeSize64());
}
MarkHighMemoryUsage();
}
#if defined(OS_WIN)
@ -212,10 +217,20 @@ NativeImage::NativeImage(v8::Isolate* isolate, const base::FilePath& hicon_path)
ReadImageSkiaFromICO(&image_skia, GetHICON(256));
image_ = gfx::Image(image_skia);
Init(isolate);
if (image_.HasRepresentation(gfx::Image::kImageRepSkia)) {
isolate->AdjustAmountOfExternalAllocatedMemory(
image_.ToImageSkia()->bitmap()->computeSize64());
}
MarkHighMemoryUsage();
}
#endif
NativeImage::~NativeImage() {}
NativeImage::~NativeImage() {
if (image_.HasRepresentation(gfx::Image::kImageRepSkia)) {
isolate()->AdjustAmountOfExternalAllocatedMemory(
- image_.ToImageSkia()->bitmap()->computeSize64());
}
}
#if defined(OS_WIN)
HICON NativeImage::GetHICON(int size) {

View file

@ -136,6 +136,7 @@ bool AtomRenderViewObserver::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(AtomRenderViewObserver, message)
IPC_MESSAGE_HANDLER(AtomViewMsg_Message, OnBrowserMessage)
IPC_MESSAGE_HANDLER(AtomViewMsg_Offscreen, OnOffscreen)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@ -169,4 +170,8 @@ void AtomRenderViewObserver::OnBrowserMessage(bool send_to_all,
}
}
void AtomRenderViewObserver::OnOffscreen() {
blink::WebView::setUseExternalPopupMenus(false);
}
} // namespace atom

View file

@ -40,6 +40,8 @@ class AtomRenderViewObserver : public content::RenderViewObserver {
const base::string16& channel,
const base::ListValue& args);
void OnOffscreen();
AtomRendererClient* renderer_client_;
// Whether the document object has been created.

2
vendor/native_mate vendored

@ -1 +1 @@
Subproject commit fd0e7dc4ab778f0d1ccda6c9640464ea06ee771e
Subproject commit 7d9c1a80f025f4c46f7da8ea73246fe0f1968579