1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PICTURE_IN_PICTURE_AUTO_PIP_SETTING_VIEW_H_
#define CHROME_BROWSER_PICTURE_IN_PICTURE_AUTO_PIP_SETTING_VIEW_H_
#include "base/functional/callback.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
// Creates and manages the content setting |BubbleDialogDelegate| for
// autopip. This view contains the setting optioms and text displayed to the
// user.
class AutoPipSettingView : public views::BubbleDialogDelegate {
public:
enum class UiResult {
// User selected 'Allow this time'.
// These values are also used as the AutoPiP setting view button ID's,
// starting from 1 because 0 is the default view ID.
kAllowOnce = 1,
// User selected 'Allow on every visit'.
kAllowOnEveryVisit,
// User selected 'Don't allow'.
kBlock,
};
using ResultCb = base::OnceCallback<void(UiResult result)>;
// This callback is responsible for hiding the AutoPiP overlay view, after
// the AutoPiP setting view is closed.
using HideViewCb = base::OnceCallback<void()>;
// Constructs an |AutoPipSettingView|. The constructor parameters are
// explained below:
// * result_cb: Callback responsible for updating the content setting,
// according to the button pressed.
// * hide_view_cb: Callback responsible for hiding the AutoPiP overlay view.
// Callback is executed after the |AutoPipSettingView| is closed.
// * origin: GURL from which the origin will be extracted and added to the
// bubble title.
// * anchor_view: Anchor view for the bubble.
// * arrow: The arrow position for the bubble.
explicit AutoPipSettingView(ResultCb result_cb,
HideViewCb hide_view_cb,
const GURL& origin,
views::View* anchor_view,
views::BubbleBorder::Arrow arrow);
AutoPipSettingView(const AutoPipSettingView&) = delete;
AutoPipSettingView(AutoPipSettingView&&) = delete;
AutoPipSettingView& operator=(const AutoPipSettingView&) = delete;
~AutoPipSettingView() override;
// Override |GetAnchorRect| to allow overlapping the bubble with the window
// title bar.
gfx::Rect GetAnchorRect() const override;
// views::WidgetDelegate:
std::unique_ptr<views::NonClientFrameView> CreateNonClientFrameView(
views::Widget* widget) override;
void OnWidgetInitialized() override;
const std::u16string& get_origin_text_for_testing() const {
return origin_text_;
}
// Return the center point in screen coordinates of our buttons.
gfx::Point get_allow_once_button_center_in_screen_for_testing() const {
return views::View::ConvertPointToScreen(
allow_once_button_, allow_once_button_->GetLocalBounds().CenterPoint());
}
gfx::Point get_allow_always_button_center_in_screen_for_testing() const {
return views::View::ConvertPointToScreen(
allow_on_every_visit_button_,
allow_on_every_visit_button_->GetLocalBounds().CenterPoint());
}
gfx::Point get_block_button_center_in_screen_for_testing() const {
return views::View::ConvertPointToScreen(
block_button_, block_button_->GetLocalBounds().CenterPoint());
}
// Returns true if `point_in_screen` overlaps a button. We do this outside of
// the normal event targetter because it seems to go very wrong with child
// widgets. The right long-term solution might be to stop being a widget, and
// just be a regular view. That would fix several event / focus issues.
bool WantsEvent(const gfx::Point& point_in_screen);
// Pretend that a button was pressed.
void simulate_button_press_for_testing(UiResult result) {
OnButtonPressed(result);
}
private:
// AnchorViewObserver observes the anchor widget view. When the anchor view is
// removed from from the widget or the view is being deleted, the observer
// will close the bubble widget (if the widget exists and is visible). This
// guarantees that a single bubble widget exists for the cases mentioned
// above.
//
// As a side effect, this also guarantees that a single bubble widgte exists
// for the cases where the PiP browser frame view is re-created.
class AnchorViewObserver : public views::ViewObserver {
public:
explicit AnchorViewObserver(views::View* anchor_view,
AutoPipSettingView* bubble);
AnchorViewObserver(const AnchorViewObserver&) = delete;
AnchorViewObserver& operator=(const AnchorViewObserver&) = delete;
~AnchorViewObserver() override;
private:
// views::ViewObserver:
void OnViewRemovedFromWidget(views::View*) override;
void OnViewIsDeleting(views::View*) override;
void CloseWidget();
const raw_ptr<AutoPipSettingView> bubble_;
base::ScopedObservation<views::View, views::ViewObserver> observation_{
this};
};
ResultCb result_cb_;
raw_ptr<views::Label> autopip_description_ = nullptr;
raw_ptr<views::MdTextButton> allow_once_button_ = nullptr;
raw_ptr<views::MdTextButton> allow_on_every_visit_button_ = nullptr;
raw_ptr<views::MdTextButton> block_button_ = nullptr;
std::unique_ptr<views::View> dialog_title_view_;
std::unique_ptr<AutoPipSettingView::AnchorViewObserver> anchor_view_observer_;
std::u16string origin_text_;
// Initialize bubble with all it's child views. Called at construction time.
void InitBubble();
// Helper method to initialize the bubble views.
raw_ptr<views::MdTextButton> InitControlViewButton(
views::BoxLayoutView* controls_view,
UiResult ui_result,
const std::u16string& label_text);
void OnButtonPressed(UiResult result);
// Initializes the bubble dialog title view.
void InitBubbleTitleView(const GURL& origin);
};
#endif // CHROME_BROWSER_PICTURE_IN_PICTURE_AUTO_PIP_SETTING_VIEW_H_
|