diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 8b7b77f24086..a5360c633975 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -314,7 +314,8 @@ WebContents::WebContents(v8::Isolate* isolate, options.Get("transparent", &transparent); 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.delegate_view = view; @@ -608,15 +609,8 @@ void WebContents::DidChangeThemeColor(SkColor theme_color) { void WebContents::DocumentLoadedInFrame( content::RenderFrameHost* render_frame_host) { - if (!render_frame_host->GetParent()) { - if (IsOffScreen()) { - auto* rwhv = web_contents()->GetRenderWidgetHostView(); - static_cast(rwhv)->SetPaintCallback( - base::Bind(&WebContents::OnPaint, base::Unretained(this))); - } - + if (!render_frame_host->GetParent()) Emit("dom-ready"); - } } void WebContents::DidFinishLoad(content::RenderFrameHost* render_frame_host, @@ -1344,19 +1338,14 @@ bool WebContents::IsOffScreen() const { } void WebContents::OnPaint(const gfx::Rect& dirty_rect, - const gfx::Size& bitmap_size, - int pixel_size, - void* bitmap_pixels) { + const SkBitmap& bitmap) { v8::MaybeLocal buffer = node::Buffer::Copy( - isolate(), reinterpret_cast(bitmap_pixels), - pixel_size * bitmap_size.width() * bitmap_size.height()); - - mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate()); - dict.Set("width", bitmap_size.width()); - dict.Set("height", bitmap_size.height()); - - if (!buffer.IsEmpty()) - Emit("paint", dirty_rect, buffer.ToLocalChecked(), dict); + isolate(), + reinterpret_cast(bitmap.getPixels()), bitmap.getSize()); + if (!buffer.IsEmpty()) { + Emit("paint", dirty_rect, buffer.ToLocalChecked(), + gfx::Size(bitmap.width(), bitmap.height())); + } } void WebContents::StartPainting() { diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 6a5bc8e47c64..4fbe7247e1e8 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -158,10 +158,7 @@ class WebContents : public mate::TrackableObject, // Methods for offscreen rendering bool IsOffScreen() const; - void OnPaint(const gfx::Rect& dirty_rect, - const gfx::Size& bitmap_size, - const int pixel_size, - void* bitmap_pixels); + void OnPaint(const gfx::Rect& dirty_rect, const SkBitmap& bitmap); void StartPainting(); void StopPainting(); bool IsPainting() const; diff --git a/atom/browser/osr/osr_output_device.cc b/atom/browser/osr/osr_output_device.cc index 3b3b9ffe9493..5d1ec3fd2c25 100644 --- a/atom/browser/osr/osr_output_device.cc +++ b/atom/browser/osr/osr_output_device.cc @@ -86,8 +86,7 @@ void OffScreenOutputDevice::OnPaint(const gfx::Rect& damage_rect) { return; SkAutoLockPixels bitmap_pixels_lock(*bitmap_); - callback_.Run(rect, gfx::Size(bitmap_->width(), bitmap_->height()), - bitmap_->bytesPerPixel(), bitmap_->getPixels()); + callback_.Run(rect, *bitmap_); } } // namespace atom diff --git a/atom/browser/osr/osr_output_device.h b/atom/browser/osr/osr_output_device.h index 2cae02733073..7f2d4653740b 100644 --- a/atom/browser/osr/osr_output_device.h +++ b/atom/browser/osr/osr_output_device.h @@ -12,8 +12,7 @@ namespace atom { -typedef base::Callback OnPaintCallback; +typedef base::Callback OnPaintCallback; class OffScreenOutputDevice : public cc::SoftwareOutputDevice { public: diff --git a/atom/browser/osr/osr_render_widget_host_view.cc b/atom/browser/osr/osr_render_widget_host_view.cc index 4ae3a578a8e6..a88d39334e0d 100644 --- a/atom/browser/osr/osr_render_widget_host_view.cc +++ b/atom/browser/osr/osr_render_widget_host_view.cc @@ -260,9 +260,7 @@ class AtomCopyFrameGenerator { const gfx::Rect& damage_rect, const SkBitmap& bitmap, std::unique_ptr bitmap_pixels_lock) { - view_->OnPaint(damage_rect, - gfx::Size(bitmap.width(), bitmap.height()), - bitmap.bytesPerPixel(), bitmap.getPixels()); + view_->OnPaint(damage_rect, bitmap); if (frame_retry_count_ > 0) frame_retry_count_ = 0; @@ -338,15 +336,17 @@ class AtomBeginFrameTimer : public cc::DelayBasedTimeSourceClient { OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView( bool transparent, + const OnPaintCallback& callback, content::RenderWidgetHost* host, NativeWindow* native_window) : render_widget_host_(content::RenderWidgetHostImpl::From(host)), native_window_(native_window), software_output_device_(nullptr), + transparent_(transparent), + callback_(callback), frame_rate_(60), frame_rate_threshold_ms_(0), last_time_(base::Time::Now()), - transparent_(transparent), scale_factor_(kDefaultScaleFactor), is_showing_(!render_widget_host_->is_hidden()), size_(native_window->GetSize()), @@ -754,7 +754,8 @@ std::unique_ptr DCHECK(!copy_frame_generator_); DCHECK(!software_output_device_); - software_output_device_ = new OffScreenOutputDevice(transparent_, + software_output_device_ = new OffScreenOutputDevice( + transparent_, base::Bind(&OffScreenRenderWidgetHostView::OnPaint, weak_ptr_factory_.GetWeakPtr())); 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( - const gfx::Rect& damage_rect, - const gfx::Size& bitmap_size, - const int pixel_size, - void* bitmap_pixels) { + const gfx::Rect& damage_rect, const SkBitmap& bitmap) { TRACE_EVENT0("electron", "OffScreenRenderWidgetHostView::OnPaint"); - - if (!callback_.is_null()) - callback_.Run(damage_rect, bitmap_size, pixel_size, bitmap_pixels); + callback_.Run(damage_rect, bitmap); } void OffScreenRenderWidgetHostView::SetPainting(bool painting) { diff --git a/atom/browser/osr/osr_render_widget_host_view.h b/atom/browser/osr/osr_render_widget_host_view.h index 65e1cec58e05..74da984363ab 100644 --- a/atom/browser/osr/osr_render_widget_host_view.h +++ b/atom/browser/osr/osr_render_widget_host_view.h @@ -63,6 +63,7 @@ class OffScreenRenderWidgetHostView public content::DelegatedFrameHostClient { public: OffScreenRenderWidgetHostView(bool transparent, + const OnPaintCallback& callback, content::RenderWidgetHost* render_widget_host, NativeWindow* native_window); ~OffScreenRenderWidgetHostView() override; @@ -189,11 +190,7 @@ class OffScreenRenderWidgetHostView void DestroyPlatformWidget(); #endif - void SetPaintCallback(const OnPaintCallback& callback); - void OnPaint(const gfx::Rect& damage_rect, - const gfx::Size& bitmap_size, - const int pixel_size, - void* bitmap_pixels); + void OnPaint(const gfx::Rect& damage_rect, const SkBitmap& bitmap); void SetPainting(bool painting); bool IsPainting() const; @@ -214,6 +211,7 @@ class OffScreenRenderWidgetHostView NativeWindow* native_window_; OffScreenOutputDevice* software_output_device_; + const bool transparent_; OnPaintCallback callback_; int frame_rate_; @@ -221,7 +219,6 @@ class OffScreenRenderWidgetHostView base::Time last_time_; - const bool transparent_; float scale_factor_; bool is_showing_; gfx::Vector2dF last_scroll_offset_; diff --git a/atom/browser/osr/osr_web_contents_view.cc b/atom/browser/osr/osr_web_contents_view.cc index 6d315ae9c16e..35aa7dcc3a7a 100644 --- a/atom/browser/osr/osr_web_contents_view.cc +++ b/atom/browser/osr/osr_web_contents_view.cc @@ -6,12 +6,20 @@ namespace atom { -OffScreenWebContentsView::OffScreenWebContentsView(bool transparent) +OffScreenWebContentsView::OffScreenWebContentsView( + bool transparent, const OnPaintCallback& callback) : transparent_(transparent), + callback_(callback), web_contents_(nullptr) { +#if defined(OS_MACOSX) + PlatformCreate(); +#endif } OffScreenWebContentsView::~OffScreenWebContentsView() { +#if defined(OS_MACOSX) + PlatformDestroy(); +#endif } void OffScreenWebContentsView::SetWebContents( @@ -19,6 +27,7 @@ void OffScreenWebContentsView::SetWebContents( web_contents_ = web_contents; } +#if !defined(OS_MACOSX) gfx::NativeView OffScreenWebContentsView::GetNativeView() const { return gfx::NativeView(); } @@ -30,6 +39,7 @@ gfx::NativeView OffScreenWebContentsView::GetContentNativeView() const { gfx::NativeWindow OffScreenWebContentsView::GetTopLevelNativeWindow() const { return gfx::NativeWindow(); } +#endif void OffScreenWebContentsView::GetContainerBounds(gfx::Rect* out) const { *out = GetViewBounds(); @@ -66,8 +76,8 @@ content::RenderWidgetHostViewBase* OffScreenWebContentsView::CreateViewForWidget( content::RenderWidgetHost* render_widget_host, bool is_guest_view_hack) { auto relay = NativeWindowRelay::FromWebContents(web_contents_); - view_ = new OffScreenRenderWidgetHostView(transparent_, render_widget_host, - relay->window.get()); + view_ = new OffScreenRenderWidgetHostView( + transparent_, callback_, render_widget_host, relay->window.get()); return view_; } @@ -75,8 +85,8 @@ content::RenderWidgetHostViewBase* OffScreenWebContentsView::CreateViewForPopupWidget( content::RenderWidgetHost* render_widget_host) { auto relay = NativeWindowRelay::FromWebContents(web_contents_); - view_ = new OffScreenRenderWidgetHostView(transparent_, render_widget_host, - relay->window.get()); + view_ = new OffScreenRenderWidgetHostView( + transparent_, callback_, render_widget_host, relay->window.get()); return view_; } diff --git a/atom/browser/osr/osr_web_contents_view.h b/atom/browser/osr/osr_web_contents_view.h index 919a14cd593d..d47f71b1e90a 100644 --- a/atom/browser/osr/osr_web_contents_view.h +++ b/atom/browser/osr/osr_web_contents_view.h @@ -10,17 +10,25 @@ #include "content/browser/web_contents/web_contents_view.h" #include "content/public/browser/web_contents.h" +#if defined(OS_MACOSX) +#ifdef __OBJC__ +@class OffScreenView; +#else +class OffScreenView; +#endif +#endif + namespace atom { class OffScreenWebContentsView : public content::WebContentsView, public content::RenderViewHostDelegateView { public: - explicit OffScreenWebContentsView(bool transparent); + OffScreenWebContentsView(bool transparent, const OnPaintCallback& callback); ~OffScreenWebContentsView(); void SetWebContents(content::WebContents*); - // content::WebContentsView + // content::WebContentsView: gfx::NativeView GetNativeView() const override; gfx::NativeView GetContentNativeView() const override; gfx::NativeWindow GetTopLevelNativeWindow() const override; @@ -61,11 +69,21 @@ class OffScreenWebContentsView : public content::WebContentsView, void UpdateDragCursor(blink::WebDragOperation operation) override; private: +#if defined(OS_MACOSX) + void PlatformCreate(); + void PlatformDestroy(); +#endif + const bool transparent_; + OnPaintCallback callback_; // Weak refs. OffScreenRenderWidgetHostView* view_; content::WebContents* web_contents_; + +#if defined(OS_MACOSX) + OffScreenView* offScreenView_; +#endif }; } // namespace atom diff --git a/atom/browser/osr/osr_web_contents_view_mac.mm b/atom/browser/osr/osr_web_contents_view_mac.mm new file mode 100644 index 000000000000..ba99c0cb959c --- /dev/null +++ b/atom/browser/osr/osr_web_contents_view_mac.mm @@ -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 diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 4d5d5721d5c9..81e5a14b0745 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -471,7 +471,6 @@ Returns: * `bitmapSize` Object * `width` Number - the width 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 buffer. diff --git a/filenames.gypi b/filenames.gypi index 6d3dd48018b7..7335ae9acc07 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -206,6 +206,7 @@ 'atom/browser/native_window_mac.h', 'atom/browser/native_window_mac.mm', '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.h', 'atom/browser/osr/osr_output_device.cc', diff --git a/vendor/brightray b/vendor/brightray index 7b5f321cd44f..4388d4e04d89 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 7b5f321cd44f2083c59ab94f2bb23cc3f59a5c2b +Subproject commit 4388d4e04d899f342e86808a4f8b36fe10a10919