diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 01893bb13f..dd8987f5e0 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -52,7 +52,6 @@ class FrameSubscriber; #if BUILDFLAG(ENABLE_OSR) class OffScreenWebContentsView; -class OffScreenRenderWidgetHostView; #endif namespace api { @@ -425,7 +424,8 @@ class WebContents : public mate::TrackableObject, #if BUILDFLAG(ENABLE_OSR) OffScreenWebContentsView* GetOffScreenWebContentsView() const; - OffScreenRenderWidgetHostView* GetOffScreenRenderWidgetHostView() const; + OffScreenRenderWidgetHostView* GetOffScreenRenderWidgetHostView() + const override; #endif // Called when we receive a CursorChange message from chromium. diff --git a/atom/browser/api/atom_api_web_contents_osr.cc b/atom/browser/api/atom_api_web_contents_osr.cc index 83120bafdc..7c2aadacfd 100644 --- a/atom/browser/api/atom_api_web_contents_osr.cc +++ b/atom/browser/api/atom_api_web_contents_osr.cc @@ -17,15 +17,23 @@ namespace atom { namespace api { OffScreenWebContentsView* WebContents::GetOffScreenWebContentsView() const { - const auto* impl = - static_cast(web_contents()); - return static_cast(impl->GetView()); + if (IsOffScreen()) { + const auto* impl = + static_cast(web_contents()); + return static_cast(impl->GetView()); + } else { + return nullptr; + } } OffScreenRenderWidgetHostView* WebContents::GetOffScreenRenderWidgetHostView() const { - return static_cast( - web_contents()->GetRenderWidgetHostView()); + if (IsOffScreen()) { + return static_cast( + web_contents()->GetRenderWidgetHostView()); + } else { + return nullptr; + } } } // namespace api diff --git a/atom/browser/common_web_contents_delegate.cc b/atom/browser/common_web_contents_delegate.cc index cb15a17e1d..3408429633 100644 --- a/atom/browser/common_web_contents_delegate.cc +++ b/atom/browser/common_web_contents_delegate.cc @@ -30,6 +30,7 @@ #include "components/prefs/scoped_user_pref_update.h" #include "components/security_state/content/content_utils.h" #include "components/security_state/core/security_state.h" +#include "content/browser/renderer_host/render_widget_host_view_base.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/render_process_host.h" @@ -39,6 +40,10 @@ #include "content/public/browser/security_style_explanations.h" #include "storage/browser/fileapi/isolated_context.h" +#if BUILDFLAG(ENABLE_OSR) +#include "atom/browser/osr/osr_render_widget_host_view.h" +#endif + using content::BrowserThread; namespace atom { @@ -201,6 +206,11 @@ void CommonWebContentsDelegate::SetOwnerWindow( web_contents->RemoveUserData( NativeWindowRelay::kNativeWindowRelayUserDataKey); } +#if BUILDFLAG(ENABLE_OSR) + auto* osr_rwhv = GetOffScreenRenderWidgetHostView(); + if (osr_rwhv) + osr_rwhv->SetNativeWindow(owner_window); +#endif } void CommonWebContentsDelegate::ResetManagedWebContents(bool async) { @@ -236,6 +246,13 @@ content::WebContents* CommonWebContentsDelegate::GetDevToolsWebContents() return web_contents_->GetDevToolsWebContents(); } +#if BUILDFLAG(ENABLE_OSR) +OffScreenRenderWidgetHostView* +CommonWebContentsDelegate::GetOffScreenRenderWidgetHostView() const { + return nullptr; +} +#endif + content::WebContents* CommonWebContentsDelegate::OpenURLFromTab( content::WebContents* source, const content::OpenURLParams& params) { diff --git a/atom/browser/common_web_contents_delegate.h b/atom/browser/common_web_contents_delegate.h index 31062e6dec..22643131c4 100644 --- a/atom/browser/common_web_contents_delegate.h +++ b/atom/browser/common_web_contents_delegate.h @@ -16,6 +16,7 @@ #include "brightray/browser/inspectable_web_contents_view_delegate.h" #include "chrome/browser/devtools/devtools_file_system_indexer.h" #include "content/public/browser/web_contents_delegate.h" +#include "electron/buildflags/buildflags.h" #if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX) #include "atom/browser/ui/autofill_popup.h" @@ -31,6 +32,10 @@ class AtomBrowserContext; class NativeWindow; class WebDialogHelper; +#if BUILDFLAG(ENABLE_OSR) +class OffScreenRenderWidgetHostView; +#endif + class CommonWebContentsDelegate : public content::WebContentsDelegate, public brightray::InspectableWebContentsDelegate, @@ -65,6 +70,11 @@ class CommonWebContentsDelegate bool is_html_fullscreen() const { return html_fullscreen_; } protected: +#if BUILDFLAG(ENABLE_OSR) + virtual OffScreenRenderWidgetHostView* GetOffScreenRenderWidgetHostView() + const; +#endif + // content::WebContentsDelegate: content::WebContents* OpenURLFromTab( content::WebContents* source, diff --git a/atom/browser/osr/osr_render_widget_host_view.cc b/atom/browser/osr/osr_render_widget_host_view.cc index c7f1b90dc1..3e4339a1bb 100644 --- a/atom/browser/osr/osr_render_widget_host_view.cc +++ b/atom/browser/osr/osr_render_widget_host_view.cc @@ -19,6 +19,7 @@ #include "components/viz/common/frame_sinks/delay_based_time_source.h" #include "components/viz/common/gl_helper.h" #include "components/viz/common/quads/render_pass.h" +#include "content/browser/renderer_host/cursor_manager.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/common/view_messages.h" @@ -264,9 +265,10 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView( callback_(callback), frame_rate_(frame_rate), scale_factor_(kDefaultScaleFactor), - size_(native_window->GetSize()), + size_(native_window ? native_window->GetSize() : gfx::Size()), painting_(painting), is_showing_(!render_widget_host_->is_hidden()), + cursor_manager_(new content::CursorManager(this)), mouse_wheel_phase_handler_(this), weak_ptr_factory_(this) { DCHECK(render_widget_host_); @@ -280,6 +282,8 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView( root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR)); #endif + current_device_scale_factor_ = 1; + local_surface_id_ = local_surface_id_allocator_.GenerateId(); #if defined(OS_MACOSX) @@ -308,7 +312,8 @@ OffScreenRenderWidgetHostView::OffScreenRenderWidgetHostView( #endif GetCompositor()->SetDelegate(this); - native_window_->AddObserver(this); + if (native_window_) + native_window_->AddObserver(this); ResizeRootLayer(false); render_widget_host_->SetView(this); @@ -351,13 +356,15 @@ OffScreenRenderWidgetHostView::CreateBrowserAccessibilityManager( void OffScreenRenderWidgetHostView::OnWindowResize() { // In offscreen mode call RenderWidgetHostView's SetSize explicitly - auto size = native_window_->GetSize(); + auto size = native_window_ ? native_window_->GetSize() : gfx::Size(); SetSize(size); } void OffScreenRenderWidgetHostView::OnWindowClosed() { - native_window_->RemoveObserver(this); - native_window_ = nullptr; + if (native_window_) { + native_window_->RemoveObserver(this); + native_window_ = nullptr; + } } void OffScreenRenderWidgetHostView::OnBeginFrameTimerTick() { @@ -445,12 +452,12 @@ void OffScreenRenderWidgetHostView::Show() { browser_compositor_->SetRenderWidgetHostIsHidden(false); #else delegated_frame_host_->SetCompositor(compositor_.get()); - delegated_frame_host_->WasShown( - GetLocalSurfaceId(), GetRootLayer()->bounds().size(), ui::LatencyInfo()); + delegated_frame_host_->WasShown(GetLocalSurfaceId(), + GetRootLayer()->bounds().size(), false); #endif if (render_widget_host_) - render_widget_host_->WasShown(ui::LatencyInfo()); + render_widget_host_->WasShown(false); } void OffScreenRenderWidgetHostView::Hide() { @@ -628,6 +635,10 @@ void OffScreenRenderWidgetHostView::InitAsFullscreen( void OffScreenRenderWidgetHostView::UpdateCursor(const content::WebCursor&) {} +content::CursorManager* OffScreenRenderWidgetHostView::GetCursorManager() { + return cursor_manager_.get(); +} + void OffScreenRenderWidgetHostView::SetIsLoading(bool loading) {} void OffScreenRenderWidgetHostView::TextInputStateChanged( @@ -727,10 +738,6 @@ gfx::Size OffScreenRenderWidgetHostView::GetCompositorViewportPixelSize() return gfx::ScaleToCeiledSize(GetRequestedRendererSize(), scale_factor_); } -gfx::Size OffScreenRenderWidgetHostView::GetRequestedRendererSize() const { - return GetDelegatedFrameHost()->GetRequestedRendererSize(); -} - content::RenderWidgetHostViewBase* OffScreenRenderWidgetHostView::CreateViewForWidget( content::RenderWidgetHost* render_widget_host, @@ -783,13 +790,14 @@ void OffScreenRenderWidgetHostView::DidReceiveFirstFrameAfterNavigation() { render_widget_host_->DidReceiveFirstFrameAfterNavigation(); } -viz::LocalSurfaceId OffScreenRenderWidgetHostView::GetLocalSurfaceId() const { +const viz::LocalSurfaceId& OffScreenRenderWidgetHostView::GetLocalSurfaceId() + const { return local_surface_id_; } #endif // !defined(OS_MACOSX) -viz::FrameSinkId OffScreenRenderWidgetHostView::GetFrameSinkId() { +const viz::FrameSinkId& OffScreenRenderWidgetHostView::GetFrameSinkId() const { return GetDelegatedFrameHost()->frame_sink_id(); } @@ -1029,7 +1037,7 @@ void OffScreenRenderWidgetHostView::SynchronizeVisualProperties() { ResizeRootLayer(false); if (render_widget_host_) render_widget_host_->SynchronizeVisualProperties(); - GetDelegatedFrameHost()->SynchronizeVisualProperties( + GetDelegatedFrameHost()->EmbedSurface( local_surface_id_, size_, cc::DeadlinePolicy::UseDefaultDeadline()); } @@ -1240,6 +1248,18 @@ void OffScreenRenderWidgetHostView::InvalidateBounds(const gfx::Rect& bounds) { } } +void OffScreenRenderWidgetHostView::SetNativeWindow(NativeWindow* window) { + if (native_window_) + native_window_->RemoveObserver(this); + + native_window_ = window; + + if (native_window_) + native_window_->AddObserver(this); + + OnWindowResize(); +} + void OffScreenRenderWidgetHostView::ResizeRootLayer(bool force) { SetupFrameRate(false); @@ -1269,7 +1289,7 @@ void OffScreenRenderWidgetHostView::ResizeRootLayer(bool force) { bool resized = UpdateNSViewAndDisplay(); #else bool resized = true; - GetDelegatedFrameHost()->SynchronizeVisualProperties( + GetDelegatedFrameHost()->EmbedSurface( local_surface_id_, size, cc::DeadlinePolicy::UseDefaultDeadline()); #endif diff --git a/atom/browser/osr/osr_render_widget_host_view.h b/atom/browser/osr/osr_render_widget_host_view.h index 9564032846..178aa17293 100644 --- a/atom/browser/osr/osr_render_widget_host_view.h +++ b/atom/browser/osr/osr_render_widget_host_view.h @@ -57,6 +57,10 @@ class NSWindow; #endif #endif +namespace content { +class CursorManager; +} // namespace content + namespace atom { class AtomCopyFrameGenerator; @@ -141,6 +145,7 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase, void RenderProcessGone(base::TerminationStatus, int) override; void Destroy(void) override; void SetTooltipText(const base::string16&) override; + content::CursorManager* GetCursorManager() override; void SelectionBoundsChanged( const ViewHostMsg_SelectionBounds_Params&) override; void CopyFromSurface( @@ -156,7 +161,11 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase, void ImeCompositionRangeChanged(const gfx::Range&, const std::vector&) override; gfx::Size GetCompositorViewportPixelSize() const override; - gfx::Size GetRequestedRendererSize() const override; + +#if defined(OS_MACOSX) + viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties( + const cc::RenderFrameMetadata& metadata) override; +#endif content::RenderWidgetHostViewBase* CreateViewForWidget( content::RenderWidgetHost*, @@ -175,8 +184,8 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase, void DidReceiveFirstFrameAfterNavigation() override; #endif // !defined(OS_MACOSX) - viz::LocalSurfaceId GetLocalSurfaceId() const override; - viz::FrameSinkId GetFrameSinkId() override; + const viz::LocalSurfaceId& GetLocalSurfaceId() const override; + const viz::FrameSinkId& GetFrameSinkId() const override; void DidNavigate() override; @@ -259,6 +268,7 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase, content::RenderWidgetHostImpl* render_widget_host() const { return render_widget_host_; } + void SetNativeWindow(NativeWindow* window); NativeWindow* window() const { return native_window_; } gfx::Size size() const { return size_; } float scale_factor() const { return scale_factor_; } @@ -272,6 +282,12 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase, } private: +#if defined(OS_MACOSX) + display::Display GetDisplay(); + void OnDidUpdateVisualPropertiesComplete( + const cc::RenderFrameMetadata& metadata); +#endif + void SetupFrameRate(bool force); void ResizeRootLayer(bool force); @@ -324,6 +340,8 @@ class OffScreenRenderWidgetHostView : public content::RenderWidgetHostViewBase, std::unique_ptr compositor_; std::unique_ptr delegated_frame_host_; + std::unique_ptr cursor_manager_; + std::unique_ptr copy_frame_generator_; std::unique_ptr begin_frame_timer_; diff --git a/atom/browser/osr/osr_render_widget_host_view_mac.mm b/atom/browser/osr/osr_render_widget_host_view_mac.mm index 0994cacc32..361bb904ea 100644 --- a/atom/browser/osr/osr_render_widget_host_view_mac.mm +++ b/atom/browser/osr/osr_render_widget_host_view_mac.mm @@ -11,21 +11,13 @@ #include "ui/accelerated_widget_mac/accelerated_widget_mac.h" #include "ui/display/screen.h" -namespace { - -display::Display GetDisplay() { - return display::Screen::GetScreen()->GetDisplayNearestView(nullptr); -} - -} // namespace - namespace atom { class MacHelper : public content::BrowserCompositorMacClient, public ui::AcceleratedWidgetMacNSView { public: explicit MacHelper(OffScreenRenderWidgetHostView* view) : view_(view) { - [this->AcceleratedWidgetGetNSView() setWantsLayer:YES]; + [view_->GetNativeView() setWantsLayer:YES]; } virtual ~MacHelper() {} @@ -48,11 +40,6 @@ class MacHelper : public content::BrowserCompositorMacClient, view_->render_widget_host()->DidProcessFrame(frame_token); } - // ui::AcceleratedWidgetMacNSView: - NSView* AcceleratedWidgetGetNSView() const override { - return [view_->window()->GetNativeWindow() contentView]; - } - void AcceleratedWidgetCALayerParamsUpdated() override {} void DidReceiveFirstFrameAfterNavigation() override { @@ -61,7 +48,22 @@ class MacHelper : public content::BrowserCompositorMacClient, void DestroyCompositorForShutdown() override {} - bool SynchronizeVisualProperties() override { + bool SynchronizeVisualProperties( + const base::Optional& + child_allocated_local_surface_id) override { + auto* browser_compositor = view_->browser_compositor(); + if (child_allocated_local_surface_id) { + browser_compositor->UpdateRendererLocalSurfaceIdFromChild( + *child_allocated_local_surface_id); + } else { + browser_compositor->AllocateNewRendererLocalSurfaceId(); + } + + if (auto* host = browser_compositor->GetDelegatedFrameHost()) { + host->EmbedSurface(browser_compositor->GetRendererLocalSurfaceId(), + browser_compositor->GetRendererSize(), + cc::DeadlinePolicy::UseDefaultDeadline()); + } return view_->render_widget_host()->SynchronizeVisualProperties(); } @@ -90,8 +92,8 @@ void OffScreenRenderWidgetHostView::CreatePlatformWidget( bool is_guest_view_hack) { mac_helper_ = new MacHelper(this); browser_compositor_.reset(new content::BrowserCompositorMac( - mac_helper_, mac_helper_, render_widget_host_->is_hidden(), true, - GetDisplay(), AllocateFrameSinkId(is_guest_view_hack))); + mac_helper_, mac_helper_, render_widget_host_->is_hidden(), GetDisplay(), + AllocateFrameSinkId(is_guest_view_hack))); } void OffScreenRenderWidgetHostView::DestroyPlatformWidget() { @@ -99,7 +101,48 @@ void OffScreenRenderWidgetHostView::DestroyPlatformWidget() { delete mac_helper_; } -viz::LocalSurfaceId OffScreenRenderWidgetHostView::GetLocalSurfaceId() const { +viz::ScopedSurfaceIdAllocator +OffScreenRenderWidgetHostView::DidUpdateVisualProperties( + const cc::RenderFrameMetadata& metadata) { + base::OnceCallback allocation_task = base::BindOnce( + base::IgnoreResult( + &OffScreenRenderWidgetHostView::OnDidUpdateVisualPropertiesComplete), + weak_ptr_factory_.GetWeakPtr(), metadata); + return browser_compositor_->GetScopedRendererSurfaceIdAllocator( + std::move(allocation_task)); +} + +display::Display OffScreenRenderWidgetHostView::GetDisplay() { + content::ScreenInfo screen_info; + GetScreenInfo(&screen_info); + + // Start with a reasonable display representation. + display::Display display = + display::Screen::GetScreen()->GetDisplayNearestView(nullptr); + + // Populate attributes based on |screen_info|. + display.set_bounds(screen_info.rect); + display.set_work_area(screen_info.available_rect); + display.set_device_scale_factor(screen_info.device_scale_factor); + display.set_color_space(screen_info.color_space); + display.set_color_depth(screen_info.depth); + display.set_depth_per_component(screen_info.depth_per_component); + display.set_is_monochrome(screen_info.is_monochrome); + display.SetRotationAsDegree(screen_info.orientation_angle); + + return display; +} + +void OffScreenRenderWidgetHostView::OnDidUpdateVisualPropertiesComplete( + const cc::RenderFrameMetadata& metadata) { + DCHECK_EQ(current_device_scale_factor_, metadata.device_scale_factor); + browser_compositor_->SynchronizeVisualProperties( + metadata.device_scale_factor, metadata.viewport_size_in_pixels, + metadata.local_surface_id.value_or(viz::LocalSurfaceId())); +} + +const viz::LocalSurfaceId& OffScreenRenderWidgetHostView::GetLocalSurfaceId() + const { return browser_compositor_->GetRendererLocalSurfaceId(); } diff --git a/atom/browser/osr/osr_web_contents_view.cc b/atom/browser/osr/osr_web_contents_view.cc index e621d99aaf..a528f1098b 100644 --- a/atom/browser/osr/osr_web_contents_view.cc +++ b/atom/browser/osr/osr_web_contents_view.cc @@ -42,7 +42,7 @@ gfx::NativeView OffScreenWebContentsView::GetNativeView() const { auto* relay = NativeWindowRelay::FromWebContents(web_contents_); if (!relay) return gfx::NativeView(); - return relay->window->GetNativeView(); + return relay->GetNativeWindow()->GetNativeView(); } gfx::NativeView OffScreenWebContentsView::GetContentNativeView() const { @@ -52,7 +52,7 @@ gfx::NativeView OffScreenWebContentsView::GetContentNativeView() const { auto* relay = NativeWindowRelay::FromWebContents(web_contents_); if (!relay) return gfx::NativeView(); - return relay->window->GetNativeView(); + return relay->GetNativeWindow()->GetNativeView(); } gfx::NativeWindow OffScreenWebContentsView::GetTopLevelNativeWindow() const { @@ -62,7 +62,7 @@ gfx::NativeWindow OffScreenWebContentsView::GetTopLevelNativeWindow() const { auto* relay = NativeWindowRelay::FromWebContents(web_contents_); if (!relay) return gfx::NativeWindow(); - return relay->window->GetNativeWindow(); + return relay->GetNativeWindow()->GetNativeWindow(); } #endif @@ -102,17 +102,14 @@ OffScreenWebContentsView::CreateViewForWidget( render_widget_host->GetView()); } - auto* relay = NativeWindowRelay::FromWebContents(web_contents_); return new OffScreenRenderWidgetHostView( transparent_, painting_, GetFrameRate(), callback_, render_widget_host, - nullptr, relay->window.get()); + nullptr, nullptr); } content::RenderWidgetHostViewBase* OffScreenWebContentsView::CreateViewForPopupWidget( content::RenderWidgetHost* render_widget_host) { - auto* relay = NativeWindowRelay::FromWebContents(web_contents_); - content::WebContentsImpl* web_contents_impl = static_cast(web_contents_); @@ -123,9 +120,9 @@ OffScreenWebContentsView::CreateViewForPopupWidget( ->GetRenderWidgetHostView() : web_contents_impl->GetRenderWidgetHostView()); - return new OffScreenRenderWidgetHostView( - transparent_, true, view->GetFrameRate(), callback_, render_widget_host, - view, relay->window.get()); + return new OffScreenRenderWidgetHostView(transparent_, true, + view->GetFrameRate(), callback_, + render_widget_host, view, nullptr); } void OffScreenWebContentsView::SetPageTitle(const base::string16& title) {} @@ -140,8 +137,11 @@ void OffScreenWebContentsView::RenderViewCreated( #endif } -void OffScreenWebContentsView::RenderViewSwappedIn( - content::RenderViewHost* host) {} +void OffScreenWebContentsView::RenderViewReady() {} + +void OffScreenWebContentsView::RenderViewHostChanged( + content::RenderViewHost* old_host, + content::RenderViewHost* new_host) {} void OffScreenWebContentsView::SetOverscrollControllerEnabled(bool enabled) {} diff --git a/atom/browser/osr/osr_web_contents_view.h b/atom/browser/osr/osr_web_contents_view.h index 206ab9dd34..0f32c575a0 100644 --- a/atom/browser/osr/osr_web_contents_view.h +++ b/atom/browser/osr/osr_web_contents_view.h @@ -50,7 +50,9 @@ class OffScreenWebContentsView : public content::WebContentsView, content::RenderWidgetHost* render_widget_host) override; void SetPageTitle(const base::string16& title) override; void RenderViewCreated(content::RenderViewHost* host) override; - void RenderViewSwappedIn(content::RenderViewHost* host) override; + void RenderViewReady() override; + void RenderViewHostChanged(content::RenderViewHost* old_host, + content::RenderViewHost* new_host) override; void SetOverscrollControllerEnabled(bool enabled) override; #if defined(OS_MACOSX) diff --git a/buildflags/buildflags.gni b/buildflags/buildflags.gni index 0c01e424b0..2603b7088b 100644 --- a/buildflags/buildflags.gni +++ b/buildflags/buildflags.gni @@ -8,7 +8,7 @@ declare_args() { # Allow running Electron as a node binary. enable_run_as_node = true - enable_osr = false + enable_osr = true enable_view_api = false