| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chromecast/browser/cast_content_window_aura.h" |
| |
| #include <memory> |
| |
| #include "base/logging.h" |
| #include "base/memory/ptr_util.h" |
| #include "chromecast/chromecast_buildflags.h" |
| #include "chromecast/graphics/cast_window_manager.h" |
| #include "content/public/browser/web_contents.h" |
| #include "ui/aura/window.h" |
| #include "ui/display/display.h" |
| #include "ui/display/screen.h" |
| |
| namespace chromecast { |
| |
| namespace { |
| |
| CastGestureHandler::Priority ToGestureHandlerPriority( |
| mojom::GesturePriority priority) { |
| switch (priority) { |
| case mojom::GesturePriority::NONE: |
| return CastGestureHandler::Priority::NONE; |
| case mojom::GesturePriority::ROOT_UI: |
| return CastGestureHandler::Priority::ROOT_UI; |
| case mojom::GesturePriority::MAIN_ACTIVITY: |
| return CastGestureHandler::Priority::MAIN_ACTIVITY; |
| case mojom::GesturePriority::SETTINGS_UI: |
| return CastGestureHandler::Priority::SETTINGS_UI; |
| } |
| } |
| |
| } // namespace |
| class TouchBlocker : public ui::EventHandler, public aura::WindowObserver { |
| public: |
| TouchBlocker(aura::Window* window, bool activated) |
| : window_(window), activated_(activated) { |
| DCHECK(window_); |
| window_->AddObserver(this); |
| if (activated_) { |
| window_->AddPreTargetHandler(this); |
| } |
| } |
| |
| TouchBlocker(const TouchBlocker&) = delete; |
| TouchBlocker& operator=(const TouchBlocker&) = delete; |
| |
| ~TouchBlocker() override { |
| if (window_) { |
| window_->RemoveObserver(this); |
| if (activated_) { |
| window_->RemovePreTargetHandler(this); |
| } |
| } |
| } |
| |
| void Activate(bool activate) { |
| if (!window_ || activate == activated_) { |
| return; |
| } |
| |
| if (activate) { |
| window_->AddPreTargetHandler(this); |
| } else { |
| window_->RemovePreTargetHandler(this); |
| } |
| |
| activated_ = activate; |
| } |
| |
| private: |
| // Overriden from ui::EventHandler. |
| void OnTouchEvent(ui::TouchEvent* touch) override { |
| if (activated_) { |
| touch->SetHandled(); |
| } |
| } |
| |
| // Overriden from aura::WindowObserver. |
| void OnWindowDestroyed(aura::Window* window) override { window_ = nullptr; } |
| |
| aura::Window* window_; |
| bool activated_; |
| }; |
| |
| CastContentWindowAura::CastContentWindowAura(mojom::CastWebViewParamsPtr params, |
| CastWindowManager* window_manager) |
| : CastContentWindow(std::move(params)), |
| window_manager_(window_manager), |
| gesture_dispatcher_( |
| std::make_unique<CastContentGestureHandler>(gesture_router())), |
| window_(nullptr), |
| has_screen_access_(false), |
| resize_window_when_navigation_starts_(true) {} |
| |
| CastContentWindowAura::~CastContentWindowAura() { |
| content::WebContentsObserver::Observe(nullptr); |
| CastWebContentsObserver::Observe(nullptr); |
| if (window_manager_) { |
| window_manager_->RemoveGestureHandler(gesture_dispatcher_.get()); |
| } |
| if (window_) { |
| window_->RemoveObserver(this); |
| } |
| } |
| |
| void CastContentWindowAura::CreateWindow( |
| mojom::ZOrder z_order, |
| VisibilityPriority visibility_priority) { |
| DCHECK(window_manager_) << "A CastWindowManager must be provided before " |
| << "creating a window for WebContents."; |
| CastWebContentsObserver::Observe(cast_web_contents()); |
| content::WebContentsObserver::Observe(WebContents()); |
| window_ = WebContents()->GetNativeView(); |
| if (!window_->HasObserver(this)) { |
| window_->AddObserver(this); |
| } |
| window_manager_->SetZOrder(window_, z_order); |
| window_manager_->AddWindow(window_); |
| window_manager_->AddGestureHandler(gesture_dispatcher_.get()); |
| |
| touch_blocker_ = |
| std::make_unique<TouchBlocker>(window_, !params_->enable_touch_input); |
| |
| if (has_screen_access_) { |
| window_->Show(); |
| } else { |
| window_->Hide(); |
| } |
| |
| cast_web_contents()->web_contents()->Focus(); |
| } |
| |
| void CastContentWindowAura::GrantScreenAccess() { |
| has_screen_access_ = true; |
| if (window_) { |
| SetFullWindowBounds(); |
| window_->Show(); |
| } |
| } |
| |
| void CastContentWindowAura::RevokeScreenAccess() { |
| has_screen_access_ = false; |
| resize_window_when_navigation_starts_ = false; |
| if (window_) { |
| window_->Hide(); |
| SetHiddenWindowBounds(); |
| } |
| } |
| |
| void CastContentWindowAura::EnableTouchInput(bool enabled) { |
| if (touch_blocker_) { |
| touch_blocker_->Activate(!enabled); |
| } |
| } |
| |
| void CastContentWindowAura::RequestVisibility( |
| VisibilityPriority visibility_priority) {} |
| |
| void CastContentWindowAura::OnWindowVisibilityChanged(aura::Window* window, |
| bool visible) { |
| if (visible) { |
| gesture_dispatcher_->SetPriority( |
| ToGestureHandlerPriority(params_->gesture_priority)); |
| } else { |
| gesture_dispatcher_->SetPriority(CastGestureHandler::Priority::NONE); |
| } |
| } |
| |
| void CastContentWindowAura::OnWindowDestroyed(aura::Window* window) { |
| window_ = nullptr; |
| } |
| |
| void CastContentWindowAura::DidStartNavigation( |
| content::NavigationHandle* navigation_handle) { |
| if (!resize_window_when_navigation_starts_ || !window_) { |
| return; |
| } |
| resize_window_when_navigation_starts_ = false; |
| SetFullWindowBounds(); |
| } |
| |
| void CastContentWindowAura::SetFullWindowBounds() { |
| #if !BUILDFLAG(IS_CAST_AUDIO_ONLY) |
| gfx::Size display_size = |
| display::Screen::GetScreen()->GetPrimaryDisplay().size(); |
| window_->SetBounds(gfx::Rect(display_size.width(), display_size.height())); |
| #endif |
| } |
| |
| void CastContentWindowAura::SetHiddenWindowBounds() { |
| // Because rendering a larger window may require more system resources, |
| // resize the window to one pixel while hidden. |
| LOG(INFO) << "Resizing window to 1x1 pixel while hidden"; |
| window_->SetBounds(gfx::Rect(1, 1)); |
| } |
| |
| } // namespace chromecast |