Merge pull request #6723 from electron/dummy-view

Show a dummy view in the offscreen window
This commit is contained in:
Cheng Zhao 2016-08-04 17:04:32 +09:00 committed by GitHub
commit 7624958cf2
12 changed files with 113 additions and 61 deletions

View file

@ -314,7 +314,8 @@ WebContents::WebContents(v8::Isolate* isolate,
options.Get("transparent", &transparent); options.Get("transparent", &transparent);
content::WebContents::CreateParams params(session->browser_context()); content::WebContents::CreateParams params(session->browser_context());
auto* view = new OffScreenWebContentsView(transparent); auto* view = new OffScreenWebContentsView(
transparent, base::Bind(&WebContents::OnPaint, base::Unretained(this)));
params.view = view; params.view = view;
params.delegate_view = view; params.delegate_view = view;
@ -608,15 +609,8 @@ void WebContents::DidChangeThemeColor(SkColor theme_color) {
void WebContents::DocumentLoadedInFrame( void WebContents::DocumentLoadedInFrame(
content::RenderFrameHost* render_frame_host) { content::RenderFrameHost* render_frame_host) {
if (!render_frame_host->GetParent()) { if (!render_frame_host->GetParent())
if (IsOffScreen()) {
auto* rwhv = web_contents()->GetRenderWidgetHostView();
static_cast<OffScreenRenderWidgetHostView*>(rwhv)->SetPaintCallback(
base::Bind(&WebContents::OnPaint, base::Unretained(this)));
}
Emit("dom-ready"); Emit("dom-ready");
}
} }
void WebContents::DidFinishLoad(content::RenderFrameHost* render_frame_host, void WebContents::DidFinishLoad(content::RenderFrameHost* render_frame_host,
@ -1344,19 +1338,14 @@ bool WebContents::IsOffScreen() const {
} }
void WebContents::OnPaint(const gfx::Rect& dirty_rect, void WebContents::OnPaint(const gfx::Rect& dirty_rect,
const gfx::Size& bitmap_size, const SkBitmap& bitmap) {
int pixel_size,
void* bitmap_pixels) {
v8::MaybeLocal<v8::Object> buffer = node::Buffer::Copy( v8::MaybeLocal<v8::Object> buffer = node::Buffer::Copy(
isolate(), reinterpret_cast<char*>(bitmap_pixels), isolate(),
pixel_size * bitmap_size.width() * bitmap_size.height()); reinterpret_cast<char*>(bitmap.getPixels()), bitmap.getSize());
if (!buffer.IsEmpty()) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate()); Emit("paint", dirty_rect, buffer.ToLocalChecked(),
dict.Set("width", bitmap_size.width()); gfx::Size(bitmap.width(), bitmap.height()));
dict.Set("height", bitmap_size.height()); }
if (!buffer.IsEmpty())
Emit("paint", dirty_rect, buffer.ToLocalChecked(), dict);
} }
void WebContents::StartPainting() { void WebContents::StartPainting() {

View file

@ -158,10 +158,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
// Methods for offscreen rendering // Methods for offscreen rendering
bool IsOffScreen() const; bool IsOffScreen() const;
void OnPaint(const gfx::Rect& dirty_rect, void OnPaint(const gfx::Rect& dirty_rect, const SkBitmap& bitmap);
const gfx::Size& bitmap_size,
const int pixel_size,
void* bitmap_pixels);
void StartPainting(); void StartPainting();
void StopPainting(); void StopPainting();
bool IsPainting() const; bool IsPainting() const;

View file

@ -86,8 +86,7 @@ void OffScreenOutputDevice::OnPaint(const gfx::Rect& damage_rect) {
return; return;
SkAutoLockPixels bitmap_pixels_lock(*bitmap_); SkAutoLockPixels bitmap_pixels_lock(*bitmap_);
callback_.Run(rect, gfx::Size(bitmap_->width(), bitmap_->height()), callback_.Run(rect, *bitmap_);
bitmap_->bytesPerPixel(), bitmap_->getPixels());
} }
} // namespace atom } // namespace atom

View file

@ -12,8 +12,7 @@
namespace atom { namespace atom {
typedef base::Callback<void(const gfx::Rect&, const gfx::Size&, typedef base::Callback<void(const gfx::Rect&, const SkBitmap&)> OnPaintCallback;
const int, void*)> OnPaintCallback;
class OffScreenOutputDevice : public cc::SoftwareOutputDevice { class OffScreenOutputDevice : public cc::SoftwareOutputDevice {
public: public:

View file

@ -260,9 +260,7 @@ class AtomCopyFrameGenerator {
const gfx::Rect& damage_rect, const gfx::Rect& damage_rect,
const SkBitmap& bitmap, const SkBitmap& bitmap,
std::unique_ptr<SkAutoLockPixels> bitmap_pixels_lock) { std::unique_ptr<SkAutoLockPixels> bitmap_pixels_lock) {
view_->OnPaint(damage_rect, view_->OnPaint(damage_rect, bitmap);
gfx::Size(bitmap.width(), bitmap.height()),
bitmap.bytesPerPixel(), bitmap.getPixels());
if (frame_retry_count_ > 0) if (frame_retry_count_ > 0)
frame_retry_count_ = 0; frame_retry_count_ = 0;
@ -338,15 +336,17 @@ class AtomBeginFrameTimer : public cc::DelayBasedTimeSourceClient {
OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView( OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView(
bool transparent, bool transparent,
const OnPaintCallback& callback,
content::RenderWidgetHost* host, content::RenderWidgetHost* host,
NativeWindow* native_window) NativeWindow* native_window)
: render_widget_host_(content::RenderWidgetHostImpl::From(host)), : render_widget_host_(content::RenderWidgetHostImpl::From(host)),
native_window_(native_window), native_window_(native_window),
software_output_device_(nullptr), software_output_device_(nullptr),
transparent_(transparent),
callback_(callback),
frame_rate_(60), frame_rate_(60),
frame_rate_threshold_ms_(0), frame_rate_threshold_ms_(0),
last_time_(base::Time::Now()), last_time_(base::Time::Now()),
transparent_(transparent),
scale_factor_(kDefaultScaleFactor), scale_factor_(kDefaultScaleFactor),
is_showing_(!render_widget_host_->is_hidden()), is_showing_(!render_widget_host_->is_hidden()),
size_(native_window->GetSize()), size_(native_window->GetSize()),
@ -754,7 +754,8 @@ std::unique_ptr<cc::SoftwareOutputDevice>
DCHECK(!copy_frame_generator_); DCHECK(!copy_frame_generator_);
DCHECK(!software_output_device_); DCHECK(!software_output_device_);
software_output_device_ = new OffScreenOutputDevice(transparent_, software_output_device_ = new OffScreenOutputDevice(
transparent_,
base::Bind(&OffScreenRenderWidgetHostView::OnPaint, base::Bind(&OffScreenRenderWidgetHostView::OnPaint,
weak_ptr_factory_.GetWeakPtr())); weak_ptr_factory_.GetWeakPtr()));
return base::WrapUnique(software_output_device_); return base::WrapUnique(software_output_device_);
@ -783,20 +784,10 @@ void OffScreenRenderWidgetHostView::OnSetNeedsBeginFrames(bool enabled) {
} }
} }
void OffScreenRenderWidgetHostView::SetPaintCallback(
const OnPaintCallback& callback) {
callback_ = callback;
}
void OffScreenRenderWidgetHostView::OnPaint( void OffScreenRenderWidgetHostView::OnPaint(
const gfx::Rect& damage_rect, const gfx::Rect& damage_rect, const SkBitmap& bitmap) {
const gfx::Size& bitmap_size,
const int pixel_size,
void* bitmap_pixels) {
TRACE_EVENT0("electron", "OffScreenRenderWidgetHostView::OnPaint"); TRACE_EVENT0("electron", "OffScreenRenderWidgetHostView::OnPaint");
callback_.Run(damage_rect, bitmap);
if (!callback_.is_null())
callback_.Run(damage_rect, bitmap_size, pixel_size, bitmap_pixels);
} }
void OffScreenRenderWidgetHostView::SetPainting(bool painting) { void OffScreenRenderWidgetHostView::SetPainting(bool painting) {

View file

@ -63,6 +63,7 @@ class OffScreenRenderWidgetHostView
public content::DelegatedFrameHostClient { public content::DelegatedFrameHostClient {
public: public:
OffScreenRenderWidgetHostView(bool transparent, OffScreenRenderWidgetHostView(bool transparent,
const OnPaintCallback& callback,
content::RenderWidgetHost* render_widget_host, content::RenderWidgetHost* render_widget_host,
NativeWindow* native_window); NativeWindow* native_window);
~OffScreenRenderWidgetHostView() override; ~OffScreenRenderWidgetHostView() override;
@ -189,11 +190,7 @@ class OffScreenRenderWidgetHostView
void DestroyPlatformWidget(); void DestroyPlatformWidget();
#endif #endif
void SetPaintCallback(const OnPaintCallback& callback); void OnPaint(const gfx::Rect& damage_rect, const SkBitmap& bitmap);
void OnPaint(const gfx::Rect& damage_rect,
const gfx::Size& bitmap_size,
const int pixel_size,
void* bitmap_pixels);
void SetPainting(bool painting); void SetPainting(bool painting);
bool IsPainting() const; bool IsPainting() const;
@ -214,6 +211,7 @@ class OffScreenRenderWidgetHostView
NativeWindow* native_window_; NativeWindow* native_window_;
OffScreenOutputDevice* software_output_device_; OffScreenOutputDevice* software_output_device_;
const bool transparent_;
OnPaintCallback callback_; OnPaintCallback callback_;
int frame_rate_; int frame_rate_;
@ -221,7 +219,6 @@ class OffScreenRenderWidgetHostView
base::Time last_time_; base::Time last_time_;
const bool transparent_;
float scale_factor_; float scale_factor_;
bool is_showing_; bool is_showing_;
gfx::Vector2dF last_scroll_offset_; gfx::Vector2dF last_scroll_offset_;

View file

@ -6,12 +6,20 @@
namespace atom { namespace atom {
OffScreenWebContentsView::OffScreenWebContentsView(bool transparent) OffScreenWebContentsView::OffScreenWebContentsView(
bool transparent, const OnPaintCallback& callback)
: transparent_(transparent), : transparent_(transparent),
callback_(callback),
web_contents_(nullptr) { web_contents_(nullptr) {
#if defined(OS_MACOSX)
PlatformCreate();
#endif
} }
OffScreenWebContentsView::~OffScreenWebContentsView() { OffScreenWebContentsView::~OffScreenWebContentsView() {
#if defined(OS_MACOSX)
PlatformDestroy();
#endif
} }
void OffScreenWebContentsView::SetWebContents( void OffScreenWebContentsView::SetWebContents(
@ -19,6 +27,7 @@ void OffScreenWebContentsView::SetWebContents(
web_contents_ = web_contents; web_contents_ = web_contents;
} }
#if !defined(OS_MACOSX)
gfx::NativeView OffScreenWebContentsView::GetNativeView() const { gfx::NativeView OffScreenWebContentsView::GetNativeView() const {
return gfx::NativeView(); return gfx::NativeView();
} }
@ -30,6 +39,7 @@ gfx::NativeView OffScreenWebContentsView::GetContentNativeView() const {
gfx::NativeWindow OffScreenWebContentsView::GetTopLevelNativeWindow() const { gfx::NativeWindow OffScreenWebContentsView::GetTopLevelNativeWindow() const {
return gfx::NativeWindow(); return gfx::NativeWindow();
} }
#endif
void OffScreenWebContentsView::GetContainerBounds(gfx::Rect* out) const { void OffScreenWebContentsView::GetContainerBounds(gfx::Rect* out) const {
*out = GetViewBounds(); *out = GetViewBounds();
@ -66,8 +76,8 @@ content::RenderWidgetHostViewBase*
OffScreenWebContentsView::CreateViewForWidget( OffScreenWebContentsView::CreateViewForWidget(
content::RenderWidgetHost* render_widget_host, bool is_guest_view_hack) { content::RenderWidgetHost* render_widget_host, bool is_guest_view_hack) {
auto relay = NativeWindowRelay::FromWebContents(web_contents_); auto relay = NativeWindowRelay::FromWebContents(web_contents_);
view_ = new OffScreenRenderWidgetHostView(transparent_, render_widget_host, view_ = new OffScreenRenderWidgetHostView(
relay->window.get()); transparent_, callback_, render_widget_host, relay->window.get());
return view_; return view_;
} }
@ -75,8 +85,8 @@ content::RenderWidgetHostViewBase*
OffScreenWebContentsView::CreateViewForPopupWidget( OffScreenWebContentsView::CreateViewForPopupWidget(
content::RenderWidgetHost* render_widget_host) { content::RenderWidgetHost* render_widget_host) {
auto relay = NativeWindowRelay::FromWebContents(web_contents_); auto relay = NativeWindowRelay::FromWebContents(web_contents_);
view_ = new OffScreenRenderWidgetHostView(transparent_, render_widget_host, view_ = new OffScreenRenderWidgetHostView(
relay->window.get()); transparent_, callback_, render_widget_host, relay->window.get());
return view_; return view_;
} }

View file

@ -10,17 +10,25 @@
#include "content/browser/web_contents/web_contents_view.h" #include "content/browser/web_contents/web_contents_view.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#if defined(OS_MACOSX)
#ifdef __OBJC__
@class OffScreenView;
#else
class OffScreenView;
#endif
#endif
namespace atom { namespace atom {
class OffScreenWebContentsView : public content::WebContentsView, class OffScreenWebContentsView : public content::WebContentsView,
public content::RenderViewHostDelegateView { public content::RenderViewHostDelegateView {
public: public:
explicit OffScreenWebContentsView(bool transparent); OffScreenWebContentsView(bool transparent, const OnPaintCallback& callback);
~OffScreenWebContentsView(); ~OffScreenWebContentsView();
void SetWebContents(content::WebContents*); void SetWebContents(content::WebContents*);
// content::WebContentsView // content::WebContentsView:
gfx::NativeView GetNativeView() const override; gfx::NativeView GetNativeView() const override;
gfx::NativeView GetContentNativeView() const override; gfx::NativeView GetContentNativeView() const override;
gfx::NativeWindow GetTopLevelNativeWindow() const override; gfx::NativeWindow GetTopLevelNativeWindow() const override;
@ -61,11 +69,21 @@ class OffScreenWebContentsView : public content::WebContentsView,
void UpdateDragCursor(blink::WebDragOperation operation) override; void UpdateDragCursor(blink::WebDragOperation operation) override;
private: private:
#if defined(OS_MACOSX)
void PlatformCreate();
void PlatformDestroy();
#endif
const bool transparent_; const bool transparent_;
OnPaintCallback callback_;
// Weak refs. // Weak refs.
OffScreenRenderWidgetHostView* view_; OffScreenRenderWidgetHostView* view_;
content::WebContents* web_contents_; content::WebContents* web_contents_;
#if defined(OS_MACOSX)
OffScreenView* offScreenView_;
#endif
}; };
} // namespace atom } // namespace atom

View file

@ -0,0 +1,52 @@
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/osr/osr_web_contents_view.h"
@interface OffScreenView : NSView
@end
@implementation OffScreenView
- (void)drawRect:(NSRect)dirtyRect {
NSString* str = @"No content under offscreen mode";
NSMutableParagraphStyle* paragraphStyle =
[[[NSParagraphStyle defaultParagraphStyle] mutableCopy] autorelease];
[paragraphStyle setAlignment:NSCenterTextAlignment];
NSDictionary* attributes = [NSDictionary
dictionaryWithObject:paragraphStyle
forKey:NSParagraphStyleAttributeName];
NSAttributedString* text =
[[[NSAttributedString alloc] initWithString:str
attributes:attributes] autorelease];
NSRect frame = NSMakeRect(0, (self.frame.size.height - text.size.height) / 2,
self.frame.size.width, text.size.height);
[str drawInRect:frame withAttributes:attributes];
}
@end
namespace atom {
gfx::NativeView OffScreenWebContentsView::GetNativeView() const {
return offScreenView_;
}
gfx::NativeView OffScreenWebContentsView::GetContentNativeView() const {
return offScreenView_;
}
gfx::NativeWindow OffScreenWebContentsView::GetTopLevelNativeWindow() const {
return [offScreenView_ window];
}
void OffScreenWebContentsView::PlatformCreate() {
offScreenView_ = [[OffScreenView alloc] init];
}
void OffScreenWebContentsView::PlatformDestroy() {
[offScreenView_ release];
}
} // namespace atom

View file

@ -471,7 +471,6 @@ Returns:
* `bitmapSize` Object * `bitmapSize` Object
* `width` Number - the width of the whole bitmap * `width` Number - the width of the whole bitmap
* `height` Number - the height of the whole bitmap * `height` Number - the height of the whole bitmap
* `bytesPerPixel` Number - The number of bytes per pixel in the bitmap
Emitted when a new frame is generated. Only the dirty area is passed in the Emitted when a new frame is generated. Only the dirty area is passed in the
buffer. buffer.

View file

@ -206,6 +206,7 @@
'atom/browser/native_window_mac.h', 'atom/browser/native_window_mac.h',
'atom/browser/native_window_mac.mm', 'atom/browser/native_window_mac.mm',
'atom/browser/native_window_observer.h', 'atom/browser/native_window_observer.h',
'atom/browser/osr/osr_web_contents_view_mac.mm',
'atom/browser/osr/osr_web_contents_view.cc', 'atom/browser/osr/osr_web_contents_view.cc',
'atom/browser/osr/osr_web_contents_view.h', 'atom/browser/osr/osr_web_contents_view.h',
'atom/browser/osr/osr_output_device.cc', 'atom/browser/osr/osr_output_device.cc',

2
vendor/brightray vendored

@ -1 +1 @@
Subproject commit 7b5f321cd44f2083c59ab94f2bb23cc3f59a5c2b Subproject commit 4388d4e04d899f342e86808a4f8b36fe10a10919