diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index c19cf6f7d945..df14e2317620 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -440,6 +440,10 @@ void Window::CapturePage(mate::Arguments* args) { rect, base::Bind(&OnCapturePageDone, args->isolate(), callback)); } +void Window::SetOffscreenRender(bool isOffscreen) { + window_->SetOffscreenRender(isOffscreen); +} + void Window::SetProgressBar(double progress) { window_->SetProgressBar(progress); } @@ -602,6 +606,7 @@ void Window::BuildPrototype(v8::Isolate* isolate, #if defined(OS_MACOSX) .SetMethod("showDefinitionForSelection", &Window::ShowDefinitionForSelection) + .SetMethod("setOffscreenRender", &Window::SetOffscreenRender) #endif .SetProperty("id", &Window::ID, true) .SetProperty("webContents", &Window::WebContents, true) diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 925aa6749714..8163ecbdd975 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -138,6 +138,7 @@ class Window : public mate::TrackableObject, void SetMenuBarVisibility(bool visible); bool IsMenuBarVisible(); void SetAspectRatio(double aspect_ratio, mate::Arguments* args); + void SetOffscreenRender(bool isOffscreen); #if defined(OS_MACOSX) void ShowDefinitionForSelection(); diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index b21d04aa2389..fc911d00a079 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -330,6 +330,29 @@ void NativeWindow::CapturePage(const gfx::Rect& rect, kBGRA_8888_SkColorType); } +void NativeWindow::SetOffscreenRender(bool isOffscreen) { + if (!isOffscreen && !offscreen_) return; + + const auto view = web_contents()->GetRenderWidgetHostView(); + + if (view) { + if (isOffscreen) { + scoped_ptr subscriber( + new RenderSubscriber( + view->GetVisibleViewportSize(), + base::Bind(&NativeWindow::OnFrameReceived, base::Unretained(this)) + ) + ); + + view->BeginFrameSubscription(subscriber.Pass()); + } else { + view->EndFrameSubscription(); + } + + offscreen_ = isOffscreen; + } +} + void NativeWindow::RequestToClosePage() { bool prevent_default = false; FOR_EACH_OBSERVER(NativeWindowObserver, @@ -548,15 +571,7 @@ void NativeWindow::DevToolsClosed() { } void NativeWindow::RenderViewReady(){ - if(offscreen_){ - const auto view = web_contents()->GetRenderWidgetHostView(); - - scoped_ptr subscriber(new RenderSubscriber( - view->GetVisibleViewportSize(), base::Bind(&NativeWindow::OnFrameReceived, base::Unretained(this)) - )); - - view->BeginFrameSubscription(subscriber.Pass()); - } + SetOffscreenRender(offscreen_); } void NativeWindow::RenderViewCreated( @@ -636,11 +651,12 @@ void NativeWindow::OnCapturePageDone(const CapturePageCallback& callback, callback.Run(bitmap); } -void NativeWindow::OnFrameReceived(bool result, scoped_refptr frame) { - if(result){ +void NativeWindow::OnFrameReceived(bool result, + scoped_refptr frame) { + if (result) { gfx::Rect rect = frame->visible_rect(); - const int rgb_arr_size = rect.width()*rect.height()*4; + const int rgb_arr_size = rect.width() * rect.height() * 4; scoped_ptr rgb_bytes(new uint8[rgb_arr_size]); // Convert a frame of YUV to 32 bit ARGB. @@ -651,7 +667,7 @@ void NativeWindow::OnFrameReceived(bool result, scoped_refptr rect.width(), rect.height(), frame->stride(media::VideoFrame::kYPlane), frame->stride(media::VideoFrame::kUVPlane), - rect.width()*4, + rect.width() * 4, media::YV12); FOR_EACH_OBSERVER(NativeWindowObserver, @@ -660,7 +676,8 @@ void NativeWindow::OnFrameReceived(bool result, scoped_refptr } } -bool RenderSubscriber::ShouldCaptureFrame(const gfx::Rect& damage_rect, +bool RenderSubscriber::ShouldCaptureFrame( + const gfx::Rect& damage_rect, base::TimeTicks present_time, scoped_refptr* storage, DeliverFrameCallback* callback) { diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index 793bd614c8d8..a07e7d641ba7 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -162,6 +162,9 @@ class NativeWindow : public content::WebContentsObserver, virtual void CapturePage(const gfx::Rect& rect, const CapturePageCallback& callback); + // Offscreen render + virtual void SetOffscreenRender(bool isOffscreen); + // Show popup dictionary. virtual void ShowDefinitionForSelection(); @@ -326,7 +329,10 @@ class NativeWindow : public content::WebContentsObserver, class RenderSubscriber : public content::RenderWidgetHostViewFrameSubscriber { public: - RenderSubscriber(gfx::Size size, base::Callback)> callback) : size_(size), callback_(callback) {} + RenderSubscriber( + gfx::Size size, + base::Callback)> callback) + : size_(size), callback_(callback) { } bool ShouldCaptureFrame(const gfx::Rect& damage_rect, base::TimeTicks present_time, @@ -335,10 +341,11 @@ class RenderSubscriber : public content::RenderWidgetHostViewFrameSubscriber { base::TimeTicks last_present_time() const { return last_present_time_; } - static void CallbackMethod(base::Callback)> callback, - scoped_refptr frame, - base::TimeTicks present_time, - bool success) { + static void CallbackMethod( + base::Callback)> callback, + scoped_refptr frame, + base::TimeTicks present_time, + bool success) { callback.Run(success, frame); } diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 612b3ce4f3f0..f0b8abc2792f 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -74,6 +74,8 @@ You can also create a window without chrome by using Linux. * `standard-window` Boolean - Uses the OS X's standard window instead of the textured window. Defaults to `true`. + * `offscreen-render` Boolean - The frame of the window will be accessible + through the `frame-rendered` event in a buffer. Defaults to `false`. * `web-preferences` Object - Settings of web page's features * `javascript` Boolean * `web-security` Boolean - When setting `false`, it will disable the same-origin @@ -226,6 +228,15 @@ Emitted when devtools is closed. Emitted when devtools is focused / opened. +### Event: 'frame-rendered' + +* `event` Event +* `frame` Buffer +* `size` Number + +Emitted when *offscreen render* is enabled, the current frame's pixel data +and size are available. + ### Event: 'app-command': Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx) is invoked. These are typically related to keyboard media keys or browser commands, as well as the "Back" button built into some mice on Windows. @@ -721,6 +732,11 @@ Returns whether the window is visible on all workspaces. **Note:** This API always returns false on Windows. +### BrowserWindow.setOffscreenRender(isOffscreen) + +Sets the offscreen rendering, if `true` the `frame-rendered` event will fire, +when the frame changes. + ## Class: WebContents A `WebContents` is responsible for rendering and controlling a web page.