chromium/chrome/browser/ui/views/overlay/video_overlay_window_views.cc

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/overlay/video_overlay_window_views.h"

#include <memory>
#include <string>

#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "chrome/browser/picture_in_picture/picture_in_picture_occlusion_tracker.h"
#include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/color/chrome_color_id.h"
#include "chrome/browser/ui/views/overlay/back_to_tab_button.h"
#include "chrome/browser/ui/views/overlay/back_to_tab_label_button.h"
#include "chrome/browser/ui/views/overlay/close_image_button.h"
#include "chrome/browser/ui/views/overlay/hang_up_button.h"
#include "chrome/browser/ui/views/overlay/minimize_button.h"
#include "chrome/browser/ui/views/overlay/playback_image_button.h"
#include "chrome/browser/ui/views/overlay/resize_handle_button.h"
#include "chrome/browser/ui/views/overlay/simple_overlay_window_image_button.h"
#include "chrome/browser/ui/views/overlay/skip_ad_label_button.h"
#include "chrome/browser/ui/views/overlay/toggle_camera_button.h"
#include "chrome/browser/ui/views/overlay/toggle_microphone_button.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/ui/base/chromeos_ui_constants.h"
#include "components/vector_icons/vector_icons.h"
#include "content/public/browser/picture_in_picture_window_controller.h"
#include "content/public/browser/web_contents.h"
#include "media/base/media_switches.h"
#include "media/base/video_util.h"
#include "ui/base/hit_test.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/base/mojom/ui_base_types.mojom-shared.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/resize_utils.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/window/non_client_view.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/public/cpp/ash_constants.h"
#include "ash/public/cpp/rounded_corner_utils.h"
#include "ash/public/cpp/window_properties.h"  // nogncheck
#include "chromeos/ui/base/app_types.h"
#include "chromeos/ui/base/window_properties.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#endif

#if BUILDFLAG(IS_WIN)
#include "chrome/browser/shell_integration_win.h"
#include "content/public/browser/render_widget_host_view.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/ime/win/tsf_input_scope.h"
#include "ui/base/win/shell.h"
#endif

#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "ui/aura/window_tree_host.h"
#include "ui/platform_window/extensions/wayland_extension.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_lacros.h"
#endif

namespace {

// Lower bound size of the window is a fixed value to allow for minimal sizes
// on UI affordances, such as buttons.
constexpr gfx::Size kMinWindowSize(260, 146);

constexpr int kOverlayBorderThickness =;

#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
// The opacity of the resize handle control.
constexpr double kResizeHandleOpacity = 0.38;
#endif

// Size of a primary control.
constexpr gfx::Size kPrimaryControlSize(52, 52);

// Margin from the bottom of the window for primary controls.
constexpr int kPrimaryControlBottomMargin =;

// Size of a secondary control.
constexpr gfx::Size kSecondaryControlSize(36, 36);

// Margin from the bottom of the window for secondary controls.
constexpr int kSecondaryControlBottomMargin =;

// Margin between controls.
constexpr int kControlMargin =;

// Minimum padding between the overlay view, if shown, and the window.
constexpr gfx::Size kOverlayViewPadding(64, 46);

// Returns the quadrant the VideoOverlayWindowViews is primarily in on the
// current work area.
VideoOverlayWindowViews::WindowQuadrant GetCurrentWindowQuadrant(
    const gfx::Rect window_bounds,
    content::PictureInPictureWindowController* controller) {}

template <typename T>
T* AddChildView(std::vector<std::unique_ptr<views::View>>* views,
                std::unique_ptr<T> child) {}

class WindowBackgroundView : public views::View {};

BEGIN_METADATA()

class ControlsBackgroundView : public views::View {};

BEGIN_METADATA()

}  // namespace

// OverlayWindow implementation of NonClientFrameView.
class OverlayWindowFrameView : public views::NonClientFrameView {};

BEGIN_METADATA()

// OverlayWindow implementation of WidgetDelegate.
class OverlayWindowWidgetDelegate : public views::WidgetDelegate {};

// static
std::unique_ptr<VideoOverlayWindowViews> VideoOverlayWindowViews::Create(
    content::VideoPictureInPictureWindowController* controller) {}

// static
std::unique_ptr<content::VideoOverlayWindow>
content::VideoOverlayWindow::Create(
    content::VideoPictureInPictureWindowController* controller) {}

VideoOverlayWindowViews::VideoOverlayWindowViews(
    content::VideoPictureInPictureWindowController* controller)
    :{}

VideoOverlayWindowViews::~VideoOverlayWindowViews() {}

gfx::Size& VideoOverlayWindowViews::GetNaturalSize() {}

gfx::Rect VideoOverlayWindowViews::CalculateAndUpdateWindowBounds() {}

void VideoOverlayWindowViews::OnNativeFocus() {}

void VideoOverlayWindowViews::OnNativeBlur() {}

gfx::Size VideoOverlayWindowViews::GetMinimumSize() const {}

gfx::Size VideoOverlayWindowViews::GetMaximumSize() const {}

void VideoOverlayWindowViews::OnNativeWidgetMove() {}

void VideoOverlayWindowViews::OnNativeWidgetSizeChanged(
    const gfx::Size& new_size) {}

void VideoOverlayWindowViews::OnKeyEvent(ui::KeyEvent* event) {}

void VideoOverlayWindowViews::OnMouseEvent(ui::MouseEvent* event) {}

bool VideoOverlayWindowViews::OnGestureEventHandledOrIgnored(
    ui::GestureEvent* event) {}

void VideoOverlayWindowViews::ReEnableControlsAfterMove() {}

void VideoOverlayWindowViews::ForceControlsVisibleForTesting(bool visible) {}

bool VideoOverlayWindowViews::AreControlsVisible() const {}

void VideoOverlayWindowViews::UpdateControlsVisibility(bool is_visible) {}

void VideoOverlayWindowViews::UpdateControlsBounds() {}

bool VideoOverlayWindowViews::IsLayoutPendingForTesting() const {}

void VideoOverlayWindowViews::OnDisplayMetricsChanged(
    const display::Display& display,
    uint32_t changed_metrics) {}

void VideoOverlayWindowViews::OnViewVisibilityChanged(
    views::View* observed_view,
    views::View* starting_view) {}

void VideoOverlayWindowViews::OnAutoPipSettingOverlayViewHidden() {}

gfx::Rect VideoOverlayWindowViews::GetWorkAreaForWindow() const {}

void VideoOverlayWindowViews::UpdateMaxSize(const gfx::Rect& work_area) {}

bool VideoOverlayWindowViews::ControlsHitTestContainsPoint(
    const gfx::Point& point) {}

content::PictureInPictureWindowController*
VideoOverlayWindowViews::GetController() const {}

views::View* VideoOverlayWindowViews::GetWindowBackgroundView() const {}

views::View* VideoOverlayWindowViews::GetControlsContainerView() const {}

void VideoOverlayWindowViews::SetUpViews() {}

void VideoOverlayWindowViews::OnRootViewReady() {}

void VideoOverlayWindowViews::UpdateLayerBoundsWithLetterboxing(
    gfx::Size window_size) {}

void VideoOverlayWindowViews::OnUpdateControlsBounds() {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
void VideoOverlayWindowViews::UpdateResizeHandleBounds(
    WindowQuadrant quadrant) {
  resize_handle_view_->SetPosition(GetBounds().size(), quadrant);
  GetNativeWindow()->SetProperty(
      ash::kWindowPipResizeHandleBoundsKey,
      new gfx::Rect(GetResizeHandleControlsBounds()));
}
#endif

bool VideoOverlayWindowViews::IsActive() const {}

void VideoOverlayWindowViews::Close() {}

void VideoOverlayWindowViews::ShowInactive() {}

void VideoOverlayWindowViews::Hide() {}

bool VideoOverlayWindowViews::IsVisible() const {}

gfx::Rect VideoOverlayWindowViews::GetBounds() {}

void VideoOverlayWindowViews::UpdateNaturalSize(const gfx::Size& natural_size) {}

void VideoOverlayWindowViews::SetPlaybackState(PlaybackState playback_state) {}

void VideoOverlayWindowViews::SetPlayPauseButtonVisibility(bool is_visible) {}

void VideoOverlayWindowViews::SetSkipAdButtonVisibility(bool is_visible) {}

void VideoOverlayWindowViews::SetPreviousSlideButtonVisibility(
    bool is_visible) {}

void VideoOverlayWindowViews::SetNextSlideButtonVisibility(bool is_visible) {}

void VideoOverlayWindowViews::SetNextTrackButtonVisibility(bool is_visible) {}

void VideoOverlayWindowViews::SetPreviousTrackButtonVisibility(
    bool is_visible) {}

void VideoOverlayWindowViews::SetMicrophoneMuted(bool muted) {}

void VideoOverlayWindowViews::SetCameraState(bool turned_on) {}

void VideoOverlayWindowViews::SetToggleMicrophoneButtonVisibility(
    bool is_visible) {}

void VideoOverlayWindowViews::SetToggleCameraButtonVisibility(bool is_visible) {}

void VideoOverlayWindowViews::SetHangUpButtonVisibility(bool is_visible) {}

void VideoOverlayWindowViews::SetSurfaceId(const viz::SurfaceId& surface_id) {}

void VideoOverlayWindowViews::OnNativeWidgetDestroying() {}

void VideoOverlayWindowViews::OnNativeWidgetDestroyed() {}

// When the PiP window is moved to different displays on Chrome OS, we need to
// re-parent the frame sink since the compositor will change. After
// OnNativeWidgetRemovingFromCompositor() is called, the window layer containing
// the compositor will be removed in Window::RemoveChildImpl(), and
// OnNativeWidgetAddedToCompositor() is called once another compositor is added.
void VideoOverlayWindowViews::OnNativeWidgetAddedToCompositor() {}

void VideoOverlayWindowViews::OnNativeWidgetRemovingFromCompositor() {}

void VideoOverlayWindowViews::OnGestureEvent(ui::GestureEvent* event) {}

gfx::Rect VideoOverlayWindowViews::GetBackToTabControlsBounds() {}

gfx::Rect VideoOverlayWindowViews::GetSkipAdControlsBounds() {}

gfx::Rect VideoOverlayWindowViews::GetCloseControlsBounds() {}

gfx::Rect VideoOverlayWindowViews::GetMinimizeControlsBounds() {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
gfx::Rect VideoOverlayWindowViews::GetResizeHandleControlsBounds() {
  return resize_handle_view_->GetMirroredBounds();
}
#endif

gfx::Rect VideoOverlayWindowViews::GetPlayPauseControlsBounds() {}

gfx::Rect VideoOverlayWindowViews::GetNextTrackControlsBounds() {}

gfx::Rect VideoOverlayWindowViews::GetPreviousTrackControlsBounds() {}

gfx::Rect VideoOverlayWindowViews::GetToggleMicrophoneButtonBounds() {}

gfx::Rect VideoOverlayWindowViews::GetToggleCameraButtonBounds() {}

gfx::Rect VideoOverlayWindowViews::GetHangUpButtonBounds() {}

gfx::Rect VideoOverlayWindowViews::GetPreviousSlideControlsBounds() {}

gfx::Rect VideoOverlayWindowViews::GetNextSlideControlsBounds() {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
int VideoOverlayWindowViews::GetResizeHTComponent() const {
  return resize_handle_view_->GetHTComponent();
}
#endif

void VideoOverlayWindowViews::TogglePlayPause() {}

void VideoOverlayWindowViews::CloseAndPauseIfAvailable() {}

PlaybackImageButton*
VideoOverlayWindowViews::play_pause_controls_view_for_testing() const {}

SimpleOverlayWindowImageButton*
VideoOverlayWindowViews::next_track_controls_view_for_testing() const {}

SimpleOverlayWindowImageButton*
VideoOverlayWindowViews::previous_track_controls_view_for_testing() const {}

SkipAdLabelButton* VideoOverlayWindowViews::skip_ad_controls_view_for_testing()
    const {}

ToggleMicrophoneButton*
VideoOverlayWindowViews::toggle_microphone_button_for_testing() const {}

ToggleCameraButton* VideoOverlayWindowViews::toggle_camera_button_for_testing()
    const {}

HangUpButton* VideoOverlayWindowViews::hang_up_button_for_testing() const {}

SimpleOverlayWindowImageButton*
VideoOverlayWindowViews::next_slide_controls_view_for_testing() const {}

SimpleOverlayWindowImageButton*
VideoOverlayWindowViews::previous_slide_controls_view_for_testing() const {}

CloseImageButton* VideoOverlayWindowViews::close_button_for_testing() const {}

OverlayWindowMinimizeButton*
VideoOverlayWindowViews::minimize_button_for_testing() const {}

OverlayWindowBackToTabButton*
VideoOverlayWindowViews::back_to_tab_button_for_testing() const {}

gfx::Point VideoOverlayWindowViews::close_image_position_for_testing() const {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
gfx::Point VideoOverlayWindowViews::resize_handle_position_for_testing() const {
  return resize_handle_view_->origin();
}
#endif

VideoOverlayWindowViews::PlaybackState
VideoOverlayWindowViews::playback_state_for_testing() const {}

ui::Layer* VideoOverlayWindowViews::video_layer_for_testing() const {}

const viz::FrameSinkId* VideoOverlayWindowViews::GetCurrentFrameSinkId() const {}

void VideoOverlayWindowViews::MaybeUnregisterFrameSinkHierarchy() {}

bool VideoOverlayWindowViews::IsOverlayViewShown() const {}

void VideoOverlayWindowViews::RemoveOverlayViewIfExists() {}