Commit 10778c6f authored by Richard Chui's avatar Richard Chui Committed by Chromium LUCI CQ

Capture Mode: Add settings bar and microphone control

Add in a new settings button on the capture bar that is used to toggle a
settings bar. This bar will start off only holding one setting, to
toggle audio recording in video capture. Settings for the audio
recording flag will persist between sessions.

Bug: 1145273
Test: manual, added test
Change-Id: I2ffbd3ac2971254c9c2227a42c64f511793ce795
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2606118
Commit-Queue: Richard Chui <richui@chromium.org>
Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Reviewed-by: default avatarSammie Quon <sammiequon@chromium.org>
Cr-Commit-Position: refs/heads/master@{#843943}
parent 299a4daf
...@@ -281,6 +281,10 @@ component("ash") { ...@@ -281,6 +281,10 @@ component("ash") {
"capture_mode/capture_mode_metrics.h", "capture_mode/capture_mode_metrics.h",
"capture_mode/capture_mode_session.cc", "capture_mode/capture_mode_session.cc",
"capture_mode/capture_mode_session.h", "capture_mode/capture_mode_session.h",
"capture_mode/capture_mode_settings_entry_view.cc",
"capture_mode/capture_mode_settings_entry_view.h",
"capture_mode/capture_mode_settings_view.cc",
"capture_mode/capture_mode_settings_view.h",
"capture_mode/capture_mode_source_view.cc", "capture_mode/capture_mode_source_view.cc",
"capture_mode/capture_mode_source_view.h", "capture_mode/capture_mode_source_view.h",
"capture_mode/capture_mode_test_api.cc", "capture_mode/capture_mode_test_api.cc",
......
...@@ -3368,6 +3368,12 @@ Here are some things you can try to get started. ...@@ -3368,6 +3368,12 @@ Here are some things you can try to get started.
<message name="IDS_ASH_SCREEN_CAPTURE_ALERT_RECORDING_STOPPED" desc="Alert spoken by screen readers when recording stops."> <message name="IDS_ASH_SCREEN_CAPTURE_ALERT_RECORDING_STOPPED" desc="Alert spoken by screen readers when recording stops.">
Screen recording completed Screen recording completed
</message> </message>
<message name="IDS_ASH_SCREEN_CAPTURE_TOOLTIP_SETTINGS" desc="Tooltip of the settings button.">
Settings
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_LABEL_MICROPHONE" desc="The capture label message for toggling microphone recording, found in the settings menu.">
Record microphone
</message>
<!-- Switch Between TABLET/LAPTOP MODE--> <!-- Switch Between TABLET/LAPTOP MODE-->
<message name="IDS_ASH_SWITCH_TO_TABLET_MODE" desc="Alert of switching to tablet mode."> <message name="IDS_ASH_SWITCH_TO_TABLET_MODE" desc="Alert of switching to tablet mode.">
......
9044c8c2ccb94b90adc0db97b3305dc3e87ccbc3
\ No newline at end of file
2a5dd865378db7f0772d3fe2cb0e3ae1a42f8d3f
\ No newline at end of file
...@@ -10,14 +10,18 @@ ...@@ -10,14 +10,18 @@
#include "ash/capture_mode/capture_mode_constants.h" #include "ash/capture_mode/capture_mode_constants.h"
#include "ash/capture_mode/capture_mode_controller.h" #include "ash/capture_mode/capture_mode_controller.h"
#include "ash/capture_mode/capture_mode_metrics.h" #include "ash/capture_mode/capture_mode_metrics.h"
#include "ash/capture_mode/capture_mode_session.h"
#include "ash/capture_mode/capture_mode_source_view.h" #include "ash/capture_mode/capture_mode_source_view.h"
#include "ash/capture_mode/capture_mode_toggle_button.h"
#include "ash/capture_mode/capture_mode_type_view.h" #include "ash/capture_mode/capture_mode_type_view.h"
#include "ash/resources/vector_icons/vector_icons.h" #include "ash/resources/vector_icons/vector_icons.h"
#include "ash/shelf/shelf.h" #include "ash/shelf/shelf.h"
#include "ash/shelf/shelf_layout_manager.h" #include "ash/shelf/shelf_layout_manager.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_provider.h" #include "ash/style/ash_color_provider.h"
#include "base/bind.h" #include "base/bind.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/background.h" #include "ui/views/background.h"
#include "ui/views/controls/separator.h" #include "ui/views/controls/separator.h"
#include "ui/views/layout/box_layout.h" #include "ui/views/layout/box_layout.h"
...@@ -28,7 +32,7 @@ namespace ash { ...@@ -28,7 +32,7 @@ namespace ash {
namespace { namespace {
constexpr gfx::Size kBarSize{328, 64}; constexpr gfx::Size kBarSize{376, 64};
constexpr gfx::Insets kBarPadding{/*vertical=*/14, /*horizontal=*/16}; constexpr gfx::Insets kBarPadding{/*vertical=*/14, /*horizontal=*/16};
...@@ -51,6 +55,10 @@ CaptureModeBarView::CaptureModeBarView() ...@@ -51,6 +55,10 @@ CaptureModeBarView::CaptureModeBarView()
capture_source_view_( capture_source_view_(
AddChildView(std::make_unique<CaptureModeSourceView>())), AddChildView(std::make_unique<CaptureModeSourceView>())),
separator_2_(AddChildView(std::make_unique<views::Separator>())), separator_2_(AddChildView(std::make_unique<views::Separator>())),
settings_button_(AddChildView(std::make_unique<CaptureModeToggleButton>(
base::BindRepeating(&CaptureModeBarView::OnSettingsButtonPressed,
base::Unretained(this)),
kCaptureModeSettingsIcon))),
close_button_(AddChildView(std::make_unique<CaptureModeButton>( close_button_(AddChildView(std::make_unique<CaptureModeButton>(
base::BindRepeating(&CaptureModeBarView::OnCloseButtonPressed, base::BindRepeating(&CaptureModeBarView::OnCloseButtonPressed,
base::Unretained(this)), base::Unretained(this)),
...@@ -71,6 +79,9 @@ CaptureModeBarView::CaptureModeBarView() ...@@ -71,6 +79,9 @@ CaptureModeBarView::CaptureModeBarView()
box_layout->set_cross_axis_alignment( box_layout->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kCenter); views::BoxLayout::CrossAxisAlignment::kCenter);
settings_button_->SetTooltipText(
l10n_util::GetStringUTF16(IDS_ASH_SCREEN_CAPTURE_TOOLTIP_SETTINGS));
const SkColor separator_color = color_provider->GetContentLayerColor( const SkColor separator_color = color_provider->GetContentLayerColor(
AshColorProvider::ContentLayerType::kSeparatorColor); AshColorProvider::ContentLayerType::kSeparatorColor);
separator_1_->SetColor(separator_color); separator_1_->SetColor(separator_color);
...@@ -115,6 +126,15 @@ void CaptureModeBarView::OnCaptureTypeChanged(CaptureModeType new_type) { ...@@ -115,6 +126,15 @@ void CaptureModeBarView::OnCaptureTypeChanged(CaptureModeType new_type) {
capture_source_view_->OnCaptureTypeChanged(new_type); capture_source_view_->OnCaptureTypeChanged(new_type);
} }
void CaptureModeBarView::SetSettingsMenuShown(bool shown) {
settings_button_->SetToggled(shown);
}
void CaptureModeBarView::OnSettingsButtonPressed() {
CaptureModeController::Get()->capture_mode_session()->SetSettingsMenuShown(
!settings_button_->GetToggled());
}
void CaptureModeBarView::OnCloseButtonPressed() { void CaptureModeBarView::OnCloseButtonPressed() {
RecordCaptureModeBarButtonType(CaptureModeBarButtonType::kExit); RecordCaptureModeBarButtonType(CaptureModeBarButtonType::kExit);
CaptureModeController::Get()->Stop(); CaptureModeController::Get()->Stop();
......
...@@ -18,22 +18,26 @@ namespace ash { ...@@ -18,22 +18,26 @@ namespace ash {
class CaptureModeButton; class CaptureModeButton;
class CaptureModeSourceView; class CaptureModeSourceView;
class CaptureModeToggleButton;
class CaptureModeTypeView; class CaptureModeTypeView;
// A view that acts as the content view of the capture mode bar widget. // A view that acts as the content view of the capture mode bar widget.
// It has a set of buttons to toggle between image and video capture, and // It has a set of buttons to toggle between image and video capture, and
// another set of buttons to toggle between fullscreen, region, and window // another set of buttons to toggle between fullscreen, region, and window
// capture sources. The structure looks like this: // capture sources. It also contains a settings button. The structure looks like
// this:
// //
// +--------------------------------------------------------+ // +---------------------------------------------------------------+
// | +----------------+ | | | // | +----------------+ | | |
// | | +---+ +---+ | | +---+ +---+ +---+ | +---+ | // | | +---+ +---+ | | +---+ +---+ +---+ | +---+ +---+ |
// | | | | | | | | | | | | | | | | | | // | | | | | | | | | | | | | | | | | | | |
// | | +---+ +---+ | | +---+ +---+ +---+ | +---+ | // | | +---+ +---+ | | +---+ +---+ +---+ | +---+ +---+ |
// | +----------------+ | ^ ^ | ^ | // | +----------------+ | ^ ^ | ^ ^ |
// +--^----------------------|-----------------|-----|------+ // +--^----------------------|-----------------|-----|------|------+
// ^ | +-----------------+ | // ^ | +-----------------+ | |
// | | | CaptureModeButton // | | | | CaptureModeButton
// | | | |
// | | | CaptureModeToggleButton
// | | CaptureModeSourceView // | | CaptureModeSourceView
// | CaptureModeTypeView // | CaptureModeTypeView
// | // |
...@@ -52,6 +56,7 @@ class ASH_EXPORT CaptureModeBarView : public views::View { ...@@ -52,6 +56,7 @@ class ASH_EXPORT CaptureModeBarView : public views::View {
CaptureModeSourceView* capture_source_view() const { CaptureModeSourceView* capture_source_view() const {
return capture_source_view_; return capture_source_view_;
} }
CaptureModeToggleButton* settings_button() const { return settings_button_; }
// Gets the ideal bounds in screen coordinates of the bar of widget on the // Gets the ideal bounds in screen coordinates of the bar of widget on the
// given |root| window. // given |root| window.
...@@ -61,9 +66,13 @@ class ASH_EXPORT CaptureModeBarView : public views::View { ...@@ -61,9 +66,13 @@ class ASH_EXPORT CaptureModeBarView : public views::View {
void OnCaptureSourceChanged(CaptureModeSource new_source); void OnCaptureSourceChanged(CaptureModeSource new_source);
void OnCaptureTypeChanged(CaptureModeType new_type); void OnCaptureTypeChanged(CaptureModeType new_type);
// Called when settings is toggled on or off.
void SetSettingsMenuShown(bool shown);
CaptureModeButton* close_button_for_testing() const { return close_button_; } CaptureModeButton* close_button_for_testing() const { return close_button_; }
private: private:
void OnSettingsButtonPressed();
void OnCloseButtonPressed(); void OnCloseButtonPressed();
// Owned by the views hierarchy. // Owned by the views hierarchy.
...@@ -71,6 +80,7 @@ class ASH_EXPORT CaptureModeBarView : public views::View { ...@@ -71,6 +80,7 @@ class ASH_EXPORT CaptureModeBarView : public views::View {
views::Separator* separator_1_; views::Separator* separator_1_;
CaptureModeSourceView* capture_source_view_; CaptureModeSourceView* capture_source_view_;
views::Separator* separator_2_; views::Separator* separator_2_;
CaptureModeToggleButton* settings_button_;
CaptureModeButton* close_button_; CaptureModeButton* close_button_;
}; };
......
...@@ -31,6 +31,9 @@ constexpr int kBetweenChildSpacing = 16; ...@@ -31,6 +31,9 @@ constexpr int kBetweenChildSpacing = 16;
constexpr int kArrowKeyboardRegionChangeDp = 1; constexpr int kArrowKeyboardRegionChangeDp = 1;
constexpr int kShiftArrowKeyboardRegionChangeDp = 10; constexpr int kShiftArrowKeyboardRegionChangeDp = 10;
// Blur quality applied to the capture bar and settings menu backdrop.
constexpr float kBlurQuality = 0.33f;
} // namespace capture_mode } // namespace capture_mode
} // namespace ash } // namespace ash
......
...@@ -338,6 +338,15 @@ void CaptureModeController::SetType(CaptureModeType type) { ...@@ -338,6 +338,15 @@ void CaptureModeController::SetType(CaptureModeType type) {
capture_mode_session_->OnCaptureTypeChanged(type_); capture_mode_session_->OnCaptureTypeChanged(type_);
} }
void CaptureModeController::EnableAudioRecording(bool enable_audio_recording) {
if (enable_audio_recording_ == enable_audio_recording)
return;
enable_audio_recording_ = enable_audio_recording;
DCHECK(capture_mode_session_);
capture_mode_session_->OnMicrophoneChanged(enable_audio_recording_);
}
void CaptureModeController::Start(CaptureModeEntryType entry_type) { void CaptureModeController::Start(CaptureModeEntryType entry_type) {
if (capture_mode_session_) if (capture_mode_session_)
return; return;
......
...@@ -59,6 +59,7 @@ class ASH_EXPORT CaptureModeController ...@@ -59,6 +59,7 @@ class ASH_EXPORT CaptureModeController
return capture_mode_session_.get(); return capture_mode_session_.get();
} }
gfx::Rect user_capture_region() const { return user_capture_region_; } gfx::Rect user_capture_region() const { return user_capture_region_; }
bool enable_audio_recording() const { return enable_audio_recording_; }
bool is_recording_in_progress() const { return is_recording_in_progress_; } bool is_recording_in_progress() const { return is_recording_in_progress_; }
// Returns true if a capture mode session is currently active. // Returns true if a capture mode session is currently active.
...@@ -69,6 +70,11 @@ class ASH_EXPORT CaptureModeController ...@@ -69,6 +70,11 @@ class ASH_EXPORT CaptureModeController
void SetSource(CaptureModeSource source); void SetSource(CaptureModeSource source);
void SetType(CaptureModeType type); void SetType(CaptureModeType type);
// Sets the audio recording flag, which will be applied to any future
// recordings (cannot be set mid recording), or to a future capture mode
// session when Start() is called.
void EnableAudioRecording(bool enable_audio_recording);
// Starts a new capture session with the most-recently used |type_| and // Starts a new capture session with the most-recently used |type_| and
// |source_|. Also records what |entry_type| that started capture mode. // |source_|. Also records what |entry_type| that started capture mode.
void Start(CaptureModeEntryType entry_type); void Start(CaptureModeEntryType entry_type);
...@@ -285,8 +291,10 @@ class ASH_EXPORT CaptureModeController ...@@ -285,8 +291,10 @@ class ASH_EXPORT CaptureModeController
std::unique_ptr<CaptureModeSession> capture_mode_session_; std::unique_ptr<CaptureModeSession> capture_mode_session_;
// Whether the service should record audio. // Remember the user selected audio preference of whether to record audio or
bool enable_audio_recording_ = true; // not for a video, between sessions. Initially, this value is set to false,
// ensuring that this is an opt-in feature.
bool enable_audio_recording_ = false;
// True when video recording is in progress. // True when video recording is in progress.
bool is_recording_in_progress_ = false; bool is_recording_in_progress_ = false;
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include "ash/capture_mode/capture_mode_bar_view.h" #include "ash/capture_mode/capture_mode_bar_view.h"
#include "ash/capture_mode/capture_mode_constants.h" #include "ash/capture_mode/capture_mode_constants.h"
#include "ash/capture_mode/capture_mode_controller.h" #include "ash/capture_mode/capture_mode_controller.h"
#include "ash/capture_mode/capture_mode_settings_view.h"
#include "ash/capture_mode/capture_mode_toggle_button.h"
#include "ash/capture_mode/capture_mode_util.h" #include "ash/capture_mode/capture_mode_util.h"
#include "ash/capture_mode/capture_window_observer.h" #include "ash/capture_mode/capture_window_observer.h"
#include "ash/display/mouse_cursor_event_filter.h" #include "ash/display/mouse_cursor_event_filter.h"
...@@ -515,6 +517,8 @@ CaptureModeSession::~CaptureModeSession() { ...@@ -515,6 +517,8 @@ CaptureModeSession::~CaptureModeSession() {
capture_label_widget_->CloseNow(); capture_label_widget_->CloseNow();
if (dimensions_label_widget_) if (dimensions_label_widget_)
dimensions_label_widget_->CloseNow(); dimensions_label_widget_->CloseNow();
if (capture_mode_settings_widget_)
capture_mode_settings_widget_->CloseNow();
DCHECK(capture_mode_bar_widget_); DCHECK(capture_mode_bar_widget_);
capture_mode_bar_widget_->CloseNow(); capture_mode_bar_widget_->CloseNow();
...@@ -563,6 +567,34 @@ void CaptureModeSession::OnCaptureTypeChanged(CaptureModeType new_type) { ...@@ -563,6 +567,34 @@ void CaptureModeSession::OnCaptureTypeChanged(CaptureModeType new_type) {
: IDS_ASH_SCREEN_CAPTURE_ALERT_SELECT_TYPE_VIDEO); : IDS_ASH_SCREEN_CAPTURE_ALERT_SELECT_TYPE_VIDEO);
} }
void CaptureModeSession::SetSettingsMenuShown(bool shown) {
capture_mode_bar_view_->SetSettingsMenuShown(shown);
if (!shown) {
capture_mode_settings_widget_.reset();
capture_mode_settings_view_ = nullptr;
return;
}
if (!capture_mode_settings_widget_) {
auto* parent = GetParentContainer(current_root_);
capture_mode_settings_widget_ = std::make_unique<views::Widget>();
capture_mode_settings_widget_->Init(CreateWidgetParams(
parent, CaptureModeSettingsView::GetBounds(capture_mode_bar_view_),
"CaptureModeSettingsWidget"));
capture_mode_settings_view_ =
capture_mode_settings_widget_->SetContentsView(
std::make_unique<CaptureModeSettingsView>());
parent->layer()->StackAtTop(capture_mode_settings_widget_->GetLayer());
capture_mode_settings_widget_->Show();
}
}
void CaptureModeSession::OnMicrophoneChanged(bool microphone_enabled) {
DCHECK(capture_mode_settings_view_);
capture_mode_settings_view_->OnMicrophoneChanged(microphone_enabled);
}
void CaptureModeSession::ReportSessionHistograms() { void CaptureModeSession::ReportSessionHistograms() {
if (controller_->source() == CaptureModeSource::kRegion) if (controller_->source() == CaptureModeSource::kRegion)
RecordNumberOfCaptureRegionAdjustments(num_capture_region_adjusted_); RecordNumberOfCaptureRegionAdjustments(num_capture_region_adjusted_);
...@@ -734,7 +766,7 @@ void CaptureModeSession::OnDisplayMetricsChanged( ...@@ -734,7 +766,7 @@ void CaptureModeSession::OnDisplayMetricsChanged(
return; return;
} }
EndSelection(/*is_event_on_capture_bar=*/false, EndSelection(/*is_event_on_capture_bar_or_menu=*/false,
/*region_intersects_capture_bar=*/false); /*region_intersects_capture_bar=*/false);
UpdateCursor(display::Screen::GetScreen()->GetCursorScreenPoint(), UpdateCursor(display::Screen::GetScreen()->GetCursorScreenPoint(),
...@@ -918,23 +950,36 @@ void CaptureModeSession::OnLocatedEvent(ui::LocatedEvent* event, ...@@ -918,23 +950,36 @@ void CaptureModeSession::OnLocatedEvent(ui::LocatedEvent* event,
parent->StackChildAtTop(capture_mode_bar_widget_->GetNativeWindow()); parent->StackChildAtTop(capture_mode_bar_widget_->GetNativeWindow());
} }
const bool is_event_on_settings_menu =
IsEventOnSettingsWidget(screen_location);
// Hide the settings menu if the user presses anywhere outside of the menu.
// Skip if the event is on the settings button, since the button will handle
// toggling the menu separately.
if (is_press_event && !is_event_on_settings_menu &&
!capture_mode_bar_view_->settings_button()->GetBoundsInScreen().Contains(
screen_location)) {
SetSettingsMenuShown(/*shown=*/false);
}
// Let the capture button handle any events it can handle first. // Let the capture button handle any events it can handle first.
if (ShouldCaptureLabelHandleEvent(event_target)) { if (ShouldCaptureLabelHandleEvent(event_target)) {
UpdateCursor(screen_location, is_touch); UpdateCursor(screen_location, is_touch);
return; return;
} }
const bool is_event_on_capture_bar = const bool is_event_on_capture_bar_or_menu =
capture_mode_bar_widget_->GetWindowBoundsInScreen().Contains( capture_mode_bar_widget_->GetWindowBoundsInScreen().Contains(
screen_location); screen_location) ||
is_event_on_settings_menu;
const CaptureModeSource capture_source = controller_->source(); const CaptureModeSource capture_source = controller_->source();
const bool is_capture_fullscreen = const bool is_capture_fullscreen =
capture_source == CaptureModeSource::kFullscreen; capture_source == CaptureModeSource::kFullscreen;
const bool is_capture_window = capture_source == CaptureModeSource::kWindow; const bool is_capture_window = capture_source == CaptureModeSource::kWindow;
if (is_capture_fullscreen || is_capture_window) { if (is_capture_fullscreen || is_capture_window) {
// Do not handle any event located on the capture mode bar. // Do not handle any event located on the capture mode bar or settings menu.
if (is_event_on_capture_bar) { if (is_event_on_capture_bar_or_menu) {
UpdateCursor(screen_location, is_touch); UpdateCursor(screen_location, is_touch);
return; return;
} }
...@@ -973,9 +1018,9 @@ void CaptureModeSession::OnLocatedEvent(ui::LocatedEvent* event, ...@@ -973,9 +1018,9 @@ void CaptureModeSession::OnLocatedEvent(ui::LocatedEvent* event,
DCHECK_EQ(CaptureModeSource::kRegion, capture_source); DCHECK_EQ(CaptureModeSource::kRegion, capture_source);
DCHECK(cursor_setter_); DCHECK(cursor_setter_);
// Allow events that are located on the capture mode bar to pass through so we // Allow events that are located on the capture mode bar or settings menu to
// can click the buttons. // pass through so we can click the buttons.
if (!is_event_on_capture_bar) { if (!is_event_on_capture_bar_or_menu) {
event->SetHandled(); event->SetHandled();
event->StopPropagation(); event->StopPropagation();
} }
...@@ -998,7 +1043,7 @@ void CaptureModeSession::OnLocatedEvent(ui::LocatedEvent* event, ...@@ -998,7 +1043,7 @@ void CaptureModeSession::OnLocatedEvent(ui::LocatedEvent* event,
case ui::ET_TOUCH_PRESSED: case ui::ET_TOUCH_PRESSED:
old_mouse_warp_status_ = SetMouseWarpEnabled(false); old_mouse_warp_status_ = SetMouseWarpEnabled(false);
OnLocatedEventPressed(location_in_root, is_touch, OnLocatedEventPressed(location_in_root, is_touch,
is_event_on_capture_bar); is_event_on_capture_bar_or_menu);
break; break;
case ui::ET_MOUSE_DRAGGED: case ui::ET_MOUSE_DRAGGED:
case ui::ET_TOUCH_MOVED: case ui::ET_TOUCH_MOVED:
...@@ -1010,14 +1055,13 @@ void CaptureModeSession::OnLocatedEvent(ui::LocatedEvent* event, ...@@ -1010,14 +1055,13 @@ void CaptureModeSession::OnLocatedEvent(ui::LocatedEvent* event,
if (old_mouse_warp_status_) if (old_mouse_warp_status_)
SetMouseWarpEnabled(*old_mouse_warp_status_); SetMouseWarpEnabled(*old_mouse_warp_status_);
old_mouse_warp_status_.reset(); old_mouse_warp_status_.reset();
OnLocatedEventReleased(is_event_on_capture_bar_or_menu,
OnLocatedEventReleased(is_event_on_capture_bar,
region_intersects_capture_bar); region_intersects_capture_bar);
break; break;
case ui::ET_MOUSE_MOVED: case ui::ET_MOUSE_MOVED:
if (region_intersects_capture_bar) { if (!capture_mode_settings_widget_ && region_intersects_capture_bar) {
UpdateCaptureBarWidgetOpacity( UpdateCaptureBarWidgetOpacity(
is_event_on_capture_bar ? 1.f : kCaptureBarOverlapOpacity, is_event_on_capture_bar_or_menu ? 1.f : kCaptureBarOverlapOpacity,
/*on_release=*/false); /*on_release=*/false);
} }
break; break;
...@@ -1062,7 +1106,7 @@ FineTunePosition CaptureModeSession::GetFineTunePosition( ...@@ -1062,7 +1106,7 @@ FineTunePosition CaptureModeSession::GetFineTunePosition(
void CaptureModeSession::OnLocatedEventPressed( void CaptureModeSession::OnLocatedEventPressed(
const gfx::Point& location_in_root, const gfx::Point& location_in_root,
bool is_touch, bool is_touch,
bool is_event_on_capture_bar) { bool is_event_on_capture_bar_or_menu) {
initial_location_in_root_ = location_in_root; initial_location_in_root_ = location_in_root;
previous_location_in_root_ = location_in_root; previous_location_in_root_ = location_in_root;
...@@ -1071,7 +1115,7 @@ void CaptureModeSession::OnLocatedEventPressed( ...@@ -1071,7 +1115,7 @@ void CaptureModeSession::OnLocatedEventPressed(
is_drag_in_progress_ = true; is_drag_in_progress_ = true;
Shell::Get()->UpdateCursorCompositingEnabled(); Shell::Get()->UpdateCursorCompositingEnabled();
if (!is_event_on_capture_bar) if (!is_event_on_capture_bar_or_menu)
UpdateCaptureBarWidgetOpacity(0.f, /*on_release=*/false); UpdateCaptureBarWidgetOpacity(0.f, /*on_release=*/false);
if (is_selecting_region_) if (is_selecting_region_)
...@@ -1080,9 +1124,9 @@ void CaptureModeSession::OnLocatedEventPressed( ...@@ -1080,9 +1124,9 @@ void CaptureModeSession::OnLocatedEventPressed(
fine_tune_position_ = GetFineTunePosition(location_in_root, is_touch); fine_tune_position_ = GetFineTunePosition(location_in_root, is_touch);
if (fine_tune_position_ == FineTunePosition::kNone && if (fine_tune_position_ == FineTunePosition::kNone &&
!is_event_on_capture_bar) { !is_event_on_capture_bar_or_menu) {
// If the point is outside the capture region and not on the capture bar, // If the point is outside the capture region and not on the capture bar or
// restart to the select phase. // settings menu, restart to the select phase.
is_selecting_region_ = true; is_selecting_region_ = true;
UpdateCaptureRegion(gfx::Rect(), /*is_resizing=*/true, /*by_user=*/true); UpdateCaptureRegion(gfx::Rect(), /*is_resizing=*/true, /*by_user=*/true);
num_capture_region_adjusted_ = 0; num_capture_region_adjusted_ = 0;
...@@ -1162,9 +1206,9 @@ void CaptureModeSession::OnLocatedEventDragged( ...@@ -1162,9 +1206,9 @@ void CaptureModeSession::OnLocatedEventDragged(
} }
void CaptureModeSession::OnLocatedEventReleased( void CaptureModeSession::OnLocatedEventReleased(
bool is_event_on_capture_bar, bool is_event_on_capture_bar_or_menu,
bool region_intersects_capture_bar) { bool region_intersects_capture_bar) {
EndSelection(is_event_on_capture_bar, region_intersects_capture_bar); EndSelection(is_event_on_capture_bar_or_menu, region_intersects_capture_bar);
// Do a repaint to show the affordance circles. // Do a repaint to show the affordance circles.
RepaintRegion(); RepaintRegion();
...@@ -1535,11 +1579,13 @@ void CaptureModeSession::UpdateCursor(const gfx::Point& location_in_screen, ...@@ -1535,11 +1579,13 @@ void CaptureModeSession::UpdateCursor(const gfx::Point& location_in_screen,
return; return;
} }
// If the current mouse is on capture bar, use the pointer mouse cursor. // If the current mouse is on capture bar or settings menu, use the pointer
const bool is_event_on_capture_bar = // mouse cursor.
const bool is_event_on_capture_bar_or_menu =
capture_mode_bar_widget_->GetWindowBoundsInScreen().Contains( capture_mode_bar_widget_->GetWindowBoundsInScreen().Contains(
location_in_screen); location_in_screen) ||
if (is_event_on_capture_bar) { IsEventOnSettingsWidget(location_in_screen);
if (is_event_on_capture_bar_or_menu) {
cursor_setter_->UpdateCursor(ui::mojom::CursorType::kPointer); cursor_setter_->UpdateCursor(ui::mojom::CursorType::kPointer);
return; return;
} }
...@@ -1621,7 +1667,7 @@ void CaptureModeSession::ClampCaptureRegionToRootWindowSize() { ...@@ -1621,7 +1667,7 @@ void CaptureModeSession::ClampCaptureRegionToRootWindowSize() {
controller_->SetUserCaptureRegion(new_capture_region, /*by_user=*/false); controller_->SetUserCaptureRegion(new_capture_region, /*by_user=*/false);
} }
void CaptureModeSession::EndSelection(bool is_event_on_capture_bar, void CaptureModeSession::EndSelection(bool is_event_on_capture_bar_or_menu,
bool region_intersects_capture_bar) { bool region_intersects_capture_bar) {
fine_tune_position_ = FineTunePosition::kNone; fine_tune_position_ = FineTunePosition::kNone;
anchor_points_.clear(); anchor_points_.clear();
...@@ -1631,7 +1677,7 @@ void CaptureModeSession::EndSelection(bool is_event_on_capture_bar, ...@@ -1631,7 +1677,7 @@ void CaptureModeSession::EndSelection(bool is_event_on_capture_bar,
// TODO(richui): Update this for tablet mode. // TODO(richui): Update this for tablet mode.
UpdateCaptureBarWidgetOpacity( UpdateCaptureBarWidgetOpacity(
region_intersects_capture_bar && !is_event_on_capture_bar region_intersects_capture_bar && !is_event_on_capture_bar_or_menu
? kCaptureBarOverlapOpacity ? kCaptureBarOverlapOpacity
: 1.f, : 1.f,
/*on_release=*/true); /*on_release=*/true);
...@@ -1738,4 +1784,11 @@ void CaptureModeSession::UpdateRegionVertically(bool up, bool is_shift_down) { ...@@ -1738,4 +1784,11 @@ void CaptureModeSession::UpdateRegionVertically(bool up, bool is_shift_down) {
/*by_user=*/true); /*by_user=*/true);
} }
bool CaptureModeSession::IsEventOnSettingsWidget(
const gfx::Point& location_in_screen) {
return capture_mode_settings_widget_ &&
capture_mode_settings_widget_->GetWindowBoundsInScreen().Contains(
location_in_screen);
}
} // namespace ash } // namespace ash
...@@ -31,6 +31,7 @@ namespace ash { ...@@ -31,6 +31,7 @@ namespace ash {
class CaptureModeBarView; class CaptureModeBarView;
class CaptureModeController; class CaptureModeController;
class CaptureModeSettingsView;
class CaptureWindowObserver; class CaptureWindowObserver;
class WindowDimmer; class WindowDimmer;
...@@ -76,6 +77,12 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner, ...@@ -76,6 +77,12 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner,
void OnCaptureSourceChanged(CaptureModeSource new_source); void OnCaptureSourceChanged(CaptureModeSource new_source);
void OnCaptureTypeChanged(CaptureModeType new_type); void OnCaptureTypeChanged(CaptureModeType new_type);
// Called when the settings menu is toggled.
void SetSettingsMenuShown(bool shown);
// Called when the record microphone setting is toggled.
void OnMicrophoneChanged(bool microphone_enabled);
// Called when the user performs a capture. Records histograms related to this // Called when the user performs a capture. Records histograms related to this
// session. // session.
void ReportSessionHistograms(); void ReportSessionHistograms();
...@@ -134,9 +141,9 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner, ...@@ -134,9 +141,9 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner,
// Handles updating the select region UI. // Handles updating the select region UI.
void OnLocatedEventPressed(const gfx::Point& location_in_root, void OnLocatedEventPressed(const gfx::Point& location_in_root,
bool is_touch, bool is_touch,
bool is_event_on_capture_bar); bool is_event_on_capture_bar_or_menu);
void OnLocatedEventDragged(const gfx::Point& location_in_root); void OnLocatedEventDragged(const gfx::Point& location_in_root);
void OnLocatedEventReleased(bool is_event_on_capture_bar, void OnLocatedEventReleased(bool is_event_on_capture_bar_or_menu,
bool region_intersects_capture_bar); bool region_intersects_capture_bar);
// Updates the capture region and the capture region widgets depending on the // Updates the capture region and the capture region widgets depending on the
...@@ -219,7 +226,7 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner, ...@@ -219,7 +226,7 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner,
// Ends a region selection. Cleans up internal state and updates the cursor, // Ends a region selection. Cleans up internal state and updates the cursor,
// capture bar opacity and magnifier glass. // capture bar opacity and magnifier glass.
void EndSelection(bool is_event_on_capture_bar, void EndSelection(bool is_event_on_capture_bar_or_menu,
bool region_intersects_capture_bar); bool region_intersects_capture_bar);
// Schedules a paint on the region and enough inset around it so that the // Schedules a paint on the region and enough inset around it so that the
...@@ -235,6 +242,9 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner, ...@@ -235,6 +242,9 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner,
void UpdateRegionHorizontally(bool left, bool is_shift_down); void UpdateRegionHorizontally(bool left, bool is_shift_down);
void UpdateRegionVertically(bool up, bool is_shift_down); void UpdateRegionVertically(bool up, bool is_shift_down);
// Returns true if the event is on a visible settings menu.
bool IsEventOnSettingsWidget(const gfx::Point& location_in_screen);
CaptureModeController* const controller_; CaptureModeController* const controller_;
// The current root window on which the capture session is active, which may // The current root window on which the capture session is active, which may
...@@ -247,6 +257,11 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner, ...@@ -247,6 +257,11 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner,
// The content view of the above widget and owned by its views hierarchy. // The content view of the above widget and owned by its views hierarchy.
CaptureModeBarView* capture_mode_bar_view_ = nullptr; CaptureModeBarView* capture_mode_bar_view_ = nullptr;
views::UniqueWidgetPtr capture_mode_settings_widget_;
// The content view of the above widget and owned by its views hierarchy.
CaptureModeSettingsView* capture_mode_settings_view_ = nullptr;
// Widget which displays capture region size during a region capture session. // Widget which displays capture region size during a region capture session.
views::UniqueWidgetPtr dimensions_label_widget_; views::UniqueWidgetPtr dimensions_label_widget_;
......
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/capture_mode/capture_mode_settings_entry_view.h"
#include "ash/capture_mode/capture_mode_constants.h"
#include "ash/style/ash_color_provider.h"
#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/views/controls/button/toggle_button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/metadata/metadata_impl_macros.h"
namespace ash {
namespace {
constexpr gfx::Size kIconSize{20, 20};
} // namespace
CaptureModeSettingsEntryView::CaptureModeSettingsEntryView(
views::Button::PressedCallback callback,
const gfx::VectorIcon& icon,
int string_id)
: icon_view_(AddChildView(std::make_unique<views::ImageView>())),
text_view_(AddChildView(std::make_unique<views::Label>(
l10n_util::GetStringUTF16(string_id)))),
toggle_button_view_(
AddChildView(std::make_unique<views::ToggleButton>(callback))) {
icon_view_->SetImageSize(kIconSize);
icon_view_->SetPreferredSize(kIconSize);
SetIcon(icon);
auto* color_provider = AshColorProvider::Get();
SkColor text_color = color_provider->GetContentLayerColor(
AshColorProvider::ContentLayerType::kTextColorPrimary);
text_view_->SetEnabledColor(text_color);
text_view_->SetBackgroundColor(SK_ColorTRANSPARENT);
text_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
toggle_button_view_->SetTooltipText(l10n_util::GetStringUTF16(string_id));
toggle_button_view_->SetThumbOnColor(color_provider->GetContentLayerColor(
AshColorProvider::ContentLayerType::kSwitchKnobColorActive));
toggle_button_view_->SetThumbOffColor(color_provider->GetContentLayerColor(
AshColorProvider::ContentLayerType::kButtonIconColor));
toggle_button_view_->SetTrackOnColor(color_provider->GetContentLayerColor(
AshColorProvider::ContentLayerType::kSwitchTrackColorActive));
toggle_button_view_->SetTrackOffColor(color_provider->GetContentLayerColor(
AshColorProvider::ContentLayerType::kSwitchTrackColorInactive));
auto* box_layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, gfx::Insets(),
capture_mode::kBetweenChildSpacing));
box_layout->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kCenter);
box_layout->SetFlexForView(text_view_, 1);
}
CaptureModeSettingsEntryView::~CaptureModeSettingsEntryView() = default;
void CaptureModeSettingsEntryView::SetIcon(const gfx::VectorIcon& icon) {
icon_view_->SetImage(gfx::CreateVectorIcon(
icon, AshColorProvider::Get()->GetContentLayerColor(
AshColorProvider::ContentLayerType::kButtonIconColor)));
}
BEGIN_METADATA(CaptureModeSettingsEntryView, views::View)
END_METADATA
} // namespace ash
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_CAPTURE_MODE_CAPTURE_MODE_SETTINGS_ENTRY_VIEW_H_
#define ASH_CAPTURE_MODE_CAPTURE_MODE_SETTINGS_ENTRY_VIEW_H_
#include "ash/ash_export.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/view.h"
namespace gfx {
struct VectorIcon;
} // namespace gfx
namespace views {
class ImageView;
class Label;
class ToggleButton;
} // namespace views
namespace ash {
// A view that is part of the Settings Bar view, from which the user can toggle
// each of the settings on/off.
class ASH_EXPORT CaptureModeSettingsEntryView : public views::View {
public:
METADATA_HEADER(CaptureModeSettingsEntryView);
CaptureModeSettingsEntryView(views::Button::PressedCallback callback,
const gfx::VectorIcon& icon,
int string_id);
CaptureModeSettingsEntryView(const CaptureModeSettingsEntryView&) = delete;
CaptureModeSettingsEntryView& operator=(const CaptureModeSettingsEntryView&) =
delete;
~CaptureModeSettingsEntryView() override;
views::ToggleButton* toggle_button_view() const {
return toggle_button_view_;
}
void SetIcon(const gfx::VectorIcon& icon);
private:
// Owned by the views hierarchy.
views::ImageView* icon_view_ = nullptr;
views::Label* text_view_ = nullptr;
views::ToggleButton* toggle_button_view_ = nullptr;
};
} // namespace ash
#endif // ASH_CAPTURE_MODE_CAPTURE_MODE_SETTINGS_ENTRY_VIEW_H_
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/capture_mode/capture_mode_settings_view.h"
#include "ash/capture_mode/capture_mode_bar_view.h"
#include "ash/capture_mode/capture_mode_constants.h"
#include "ash/capture_mode/capture_mode_controller.h"
#include "ash/capture_mode/capture_mode_settings_entry_view.h"
#include "ash/capture_mode/capture_mode_toggle_button.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_provider.h"
#include "base/bind.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/background.h"
#include "ui/views/controls/button/toggle_button.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/style/platform_style.h"
namespace ash {
namespace {
constexpr gfx::Size kSettingsSize{256, 52};
constexpr gfx::Insets kSettingsPadding{/*vertical=*/16, /*horizontal=*/16};
constexpr gfx::RoundedCornersF kBorderRadius{10.f};
// Distance between bottom of the settings menu to the top of the capture bar.
constexpr int kDistanceFromCaptureBarTop = 8;
} // namespace
CaptureModeSettingsView::CaptureModeSettingsView()
: microphone_view_(
AddChildView(std::make_unique<CaptureModeSettingsEntryView>(
base::BindRepeating(&CaptureModeSettingsView::OnMicrophoneToggled,
base::Unretained(this)),
kCaptureModeMicOffIcon,
IDS_ASH_SCREEN_CAPTURE_LABEL_MICROPHONE))) {
SetPaintToLayer();
auto* color_provider = AshColorProvider::Get();
SkColor background_color = color_provider->GetBaseLayerColor(
AshColorProvider::BaseLayerType::kTransparent80);
SetBackground(views::CreateSolidBackground(background_color));
layer()->SetFillsBoundsOpaquely(false);
layer()->SetRoundedCornerRadius(kBorderRadius);
layer()->SetBackgroundBlur(
static_cast<float>(AshColorProvider::LayerBlurSigma::kBlurDefault));
layer()->SetBackdropFilterQuality(capture_mode::kBlurQuality);
SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical, kSettingsPadding,
capture_mode::kBetweenChildSpacing));
OnMicrophoneChanged(CaptureModeController::Get()->enable_audio_recording());
}
CaptureModeSettingsView::~CaptureModeSettingsView() = default;
// static
gfx::Rect CaptureModeSettingsView::GetBounds(
CaptureModeBarView* capture_mode_bar_view) {
DCHECK(capture_mode_bar_view);
return gfx::Rect(
capture_mode_bar_view->settings_button()->GetBoundsInScreen().right() -
kSettingsSize.width(),
capture_mode_bar_view->GetBoundsInScreen().y() -
kDistanceFromCaptureBarTop - kSettingsSize.height(),
kSettingsSize.width(), kSettingsSize.height());
}
void CaptureModeSettingsView::OnMicrophoneChanged(bool microphone_enabled) {
microphone_view_->toggle_button_view()->SetIsOn(microphone_enabled);
microphone_view_->SetIcon(microphone_enabled ? kCaptureModeMicIcon
: kCaptureModeMicOffIcon);
}
void CaptureModeSettingsView::OnMicrophoneToggled() {
CaptureModeController::Get()->EnableAudioRecording(
microphone_view_->toggle_button_view()->GetIsOn());
}
BEGIN_METADATA(CaptureModeSettingsView, views::View)
END_METADATA
} // namespace ash
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_CAPTURE_MODE_CAPTURE_MODE_SETTINGS_VIEW_H_
#define ASH_CAPTURE_MODE_CAPTURE_MODE_SETTINGS_VIEW_H_
#include "ash/ash_export.h"
#include "ui/views/controls/button/toggle_button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/view.h"
namespace ash {
class CaptureModeBarView;
class CaptureModeSettingsEntryView;
// A view that acts as the content view of the capture mode settings menu
// widget. It has settings entries, starting with a microphone toggle. The
// structure looks like this:
//
// +-----------------------------------------------------------+
// | +-----------------------------------------------------+ |
// | | +---+ +------------------------------+ +------+ | |
// | | | | | | | | | |
// | | +---+ +------------------------------+ +------+ | |
// | +-----------------------------------------------------+ |
// +--^--------------------------------------------------------+
// ^ |
// | CaptureModeSettingsEntryView
// |
// CaptureModeSettingsView
//
class ASH_EXPORT CaptureModeSettingsView : public views::View {
public:
METADATA_HEADER(CaptureModeSettingsView);
CaptureModeSettingsView();
CaptureModeSettingsView(const CaptureModeSettingsView&) = delete;
CaptureModeSettingsView& operator=(const CaptureModeSettingsView&) = delete;
~CaptureModeSettingsView() override;
// Gets the ideal bounds in screen coordinates of the settings widget on
// the given |capture_mode_bar_view|.
static gfx::Rect GetBounds(CaptureModeBarView* capture_mode_bar_view);
// Called when the settings change.
void OnMicrophoneChanged(bool microphone_enabled);
CaptureModeSettingsEntryView* microphone_view_for_testing() const {
return microphone_view_;
}
private:
void OnMicrophoneToggled();
CaptureModeSettingsEntryView* microphone_view_;
};
} // namespace ash
#endif // ASH_CAPTURE_MODE_CAPTURE_MODE_SETTINGS_VIEW_H_
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include "ash/capture_mode/capture_mode_controller.h" #include "ash/capture_mode/capture_mode_controller.h"
#include "ash/capture_mode/capture_mode_metrics.h" #include "ash/capture_mode/capture_mode_metrics.h"
#include "ash/capture_mode/capture_mode_session.h" #include "ash/capture_mode/capture_mode_session.h"
#include "ash/capture_mode/capture_mode_settings_entry_view.h"
#include "ash/capture_mode/capture_mode_settings_view.h"
#include "ash/capture_mode/capture_mode_source_view.h" #include "ash/capture_mode/capture_mode_source_view.h"
#include "ash/capture_mode/capture_mode_toggle_button.h" #include "ash/capture_mode/capture_mode_toggle_button.h"
#include "ash/capture_mode/capture_mode_type_view.h" #include "ash/capture_mode/capture_mode_type_view.h"
...@@ -137,6 +139,14 @@ class CaptureModeSessionTestApi { ...@@ -137,6 +139,14 @@ class CaptureModeSessionTestApi {
return session_->capture_mode_bar_widget_.get(); return session_->capture_mode_bar_widget_.get();
} }
CaptureModeSettingsView* capture_mode_settings_view() const {
return session_->capture_mode_settings_view_;
}
views::Widget* capture_mode_settings_widget() const {
return session_->capture_mode_settings_widget_.get();
}
views::Widget* capture_label_widget() const { views::Widget* capture_label_widget() const {
return session_->capture_label_widget_.get(); return session_->capture_label_widget_.get();
} }
...@@ -184,6 +194,18 @@ class CaptureModeTest : public AshTestBase { ...@@ -184,6 +194,18 @@ class CaptureModeTest : public AshTestBase {
return CaptureModeSessionTestApi(session).capture_mode_bar_widget(); return CaptureModeSessionTestApi(session).capture_mode_bar_widget();
} }
CaptureModeSettingsView* GetCaptureModeSettingsView() const {
auto* session = CaptureModeController::Get()->capture_mode_session();
DCHECK(session);
return CaptureModeSessionTestApi(session).capture_mode_settings_view();
}
views::Widget* GetCaptureModeSettingsWidget() const {
auto* session = CaptureModeController::Get()->capture_mode_session();
DCHECK(session);
return CaptureModeSessionTestApi(session).capture_mode_settings_widget();
}
CaptureModeToggleButton* GetImageToggleButton() const { CaptureModeToggleButton* GetImageToggleButton() const {
auto* controller = CaptureModeController::Get(); auto* controller = CaptureModeController::Get();
DCHECK(controller->IsActive()); DCHECK(controller->IsActive());
...@@ -220,12 +242,27 @@ class CaptureModeTest : public AshTestBase { ...@@ -220,12 +242,27 @@ class CaptureModeTest : public AshTestBase {
->window_toggle_button(); ->window_toggle_button();
} }
CaptureModeToggleButton* GetSettingsButton() const {
auto* controller = CaptureModeController::Get();
DCHECK(controller->IsActive());
return GetCaptureModeBarView()->settings_button();
}
CaptureModeButton* GetCloseButton() const { CaptureModeButton* GetCloseButton() const {
auto* controller = CaptureModeController::Get(); auto* controller = CaptureModeController::Get();
DCHECK(controller->IsActive()); DCHECK(controller->IsActive());
return GetCaptureModeBarView()->close_button_for_testing(); return GetCaptureModeBarView()->close_button_for_testing();
} }
views::ToggleButton* GetMicrophoneToggle() const {
auto* controller = CaptureModeController::Get();
DCHECK(controller->IsActive());
DCHECK(GetCaptureModeSettingsView());
return GetCaptureModeSettingsView()
->microphone_view_for_testing()
->toggle_button_view();
}
aura::Window* GetDimensionsLabelWindow() const { aura::Window* GetDimensionsLabelWindow() const {
auto* controller = CaptureModeController::Get(); auto* controller = CaptureModeController::Get();
DCHECK(controller->IsActive()); DCHECK(controller->IsActive());
...@@ -2522,4 +2559,157 @@ TEST_F(CaptureModeTest, CannotDoMultipleRecordings) { ...@@ -2522,4 +2559,157 @@ TEST_F(CaptureModeTest, CannotDoMultipleRecordings) {
EXPECT_TRUE(GetVideoToggleButton()->GetEnabled()); EXPECT_TRUE(GetVideoToggleButton()->GetEnabled());
} }
// Tests the basic settings menu functionality.
TEST_F(CaptureModeTest, SettingsMenuVisibilityBasic) {
auto* event_generator = GetEventGenerator();
auto* controller = StartImageRegionCapture();
EXPECT_TRUE(controller->IsActive());
// Session starts with settings menu not initialized.
EXPECT_FALSE(GetCaptureModeSettingsWidget());
// Test clicking the settings button toggles the button as well as
// opens/closes the settings menu.
ClickOnView(GetSettingsButton(), event_generator);
EXPECT_TRUE(GetCaptureModeSettingsWidget());
EXPECT_TRUE(GetSettingsButton()->GetToggled());
ClickOnView(GetSettingsButton(), event_generator);
EXPECT_FALSE(GetCaptureModeSettingsWidget());
EXPECT_FALSE(GetSettingsButton()->GetToggled());
}
// Tests how interacting with the rest of the screen (i.e. clicking outside of
// the bar/menu, on other buttons) affects whether the settings menu should
// close or not.
TEST_F(CaptureModeTest, SettingsMenuVisibilityClicking) {
UpdateDisplay("800x800");
auto* event_generator = GetEventGenerator();
auto* controller = StartImageRegionCapture();
EXPECT_TRUE(controller->IsActive());
// Test clicking on the settings menu and toggling settings doesn't close the
// settings menu.
ClickOnView(GetSettingsButton(), event_generator);
ClickOnView(GetCaptureModeSettingsView(), event_generator);
EXPECT_TRUE(GetCaptureModeSettingsWidget());
EXPECT_TRUE(GetSettingsButton()->GetToggled());
ClickOnView(GetMicrophoneToggle(), event_generator);
EXPECT_TRUE(GetCaptureModeSettingsWidget());
EXPECT_TRUE(GetSettingsButton()->GetToggled());
// Test clicking on the capture bar closes the settings menu.
event_generator->MoveMouseTo(
GetCaptureModeBarView()->GetBoundsInScreen().top_center() +
gfx::Vector2d(0, 2));
event_generator->ClickLeftButton();
EXPECT_FALSE(GetCaptureModeSettingsWidget());
EXPECT_FALSE(GetSettingsButton()->GetToggled());
// Test clicking on a different source closes the settings menu.
ClickOnView(GetSettingsButton(), event_generator);
ClickOnView(GetFullscreenToggleButton(), event_generator);
EXPECT_FALSE(GetCaptureModeSettingsWidget());
// Test clicking on a different type closes the settings menu.
ClickOnView(GetSettingsButton(), event_generator);
ClickOnView(GetVideoToggleButton(), event_generator);
EXPECT_FALSE(GetCaptureModeSettingsWidget());
// Exit the capture session with the settings menu open, and test to make sure
// the new session starts with the settings menu hidden.
ClickOnView(GetSettingsButton(), event_generator);
SendKey(ui::VKEY_ESCAPE, event_generator);
StartCaptureSession(CaptureModeSource::kFullscreen, CaptureModeType::kImage);
EXPECT_FALSE(GetCaptureModeSettingsWidget());
// Take a screenshot with the settings menu open, and test to make sure the
// new session starts with the settings menu hidden.
ClickOnView(GetSettingsButton(), event_generator);
// Take screenshot.
SendKey(ui::VKEY_RETURN, event_generator);
StartImageRegionCapture();
EXPECT_FALSE(GetCaptureModeSettingsWidget());
}
// Tests the settings menu functionality when in region mode.
TEST_F(CaptureModeTest, SettingsMenuVisibilityDrawingRegion) {
UpdateDisplay("800x800");
auto* event_generator = GetEventGenerator();
auto* controller = StartImageRegionCapture();
EXPECT_TRUE(controller->IsActive());
// Test the settings menu is hidden when the user clicks to start selecting a
// region.
ClickOnView(GetSettingsButton(), event_generator);
EXPECT_TRUE(GetCaptureModeSettingsWidget());
const gfx::Rect target_region(gfx::BoundingRect(
gfx::Point(0, 0),
GetCaptureModeBarView()->GetBoundsInScreen().top_right() +
gfx::Vector2d(0, -50)));
event_generator->MoveMouseTo(target_region.origin());
event_generator->PressLeftButton();
EXPECT_FALSE(GetCaptureModeSettingsWidget());
event_generator->MoveMouseTo(target_region.bottom_right());
event_generator->ReleaseLeftButton();
EXPECT_FALSE(GetCaptureModeSettingsWidget());
// Test that the settings menu is hidden when we drag a region. This drags a
// region that overlapps the capture bar for later steps of testing.
ClickOnView(GetSettingsButton(), event_generator);
event_generator->MoveMouseTo(target_region.origin() + gfx::Vector2d(50, 50));
event_generator->PressLeftButton();
EXPECT_FALSE(GetCaptureModeSettingsWidget());
event_generator->MoveMouseTo(target_region.bottom_center());
event_generator->ReleaseLeftButton();
// With an overlapping region (as dragged to above), the capture bar opacity
// is changed based on hover. If the settings menu is open/visible, we close
// it when we hide the capture bar. Capture bar starts off opaque.
ui::Layer* capture_bar_layer = GetCaptureModeBarWidget()->GetLayer();
event_generator->MoveMouseTo(target_region.origin());
EXPECT_EQ(0.1f, capture_bar_layer->GetTargetOpacity());
ClickOnView(GetSettingsButton(), event_generator);
EXPECT_EQ(1.f, capture_bar_layer->GetTargetOpacity());
// Move mouse onto the settings menu, confirm the capture bar is still
// visible.
event_generator->MoveMouseTo(
GetCaptureModeSettingsView()->GetBoundsInScreen().CenterPoint());
EXPECT_EQ(1.f, capture_bar_layer->GetTargetOpacity());
// Move the mouse off both the capture bar and the settings menu, and confirm
// that both bars are visible.
event_generator->MoveMouseTo(
GetCaptureModeSettingsView()->GetBoundsInScreen().top_center() +
gfx::Vector2d(0, -50));
EXPECT_EQ(1.f, capture_bar_layer->GetTargetOpacity());
EXPECT_TRUE(GetCaptureModeSettingsWidget());
}
// Tests that toggling the microphone setting updates the state in the
// controller, and persists between sessions.
TEST_F(CaptureModeTest, AudioRecordingSetting) {
auto* controller = StartImageRegionCapture();
auto* event_generator = GetEventGenerator();
// Test that the audio recording preference is defaulted to false, so the
// toggle should start in the off position.
EXPECT_FALSE(controller->enable_audio_recording());
// Test that toggling on the micophone updates the preference in the
// controller, as well as displaying the toggle as on.
ClickOnView(GetSettingsButton(), event_generator);
EXPECT_FALSE(GetMicrophoneToggle()->GetIsOn());
ClickOnView(GetMicrophoneToggle(), event_generator);
EXPECT_TRUE(controller->enable_audio_recording());
EXPECT_TRUE(GetMicrophoneToggle()->GetIsOn());
// Test that the user selected audio preference for audio recording is
// remembered between sessions.
SendKey(ui::VKEY_ESCAPE, event_generator);
EXPECT_TRUE(controller->enable_audio_recording());
StartImageRegionCapture();
EXPECT_TRUE(controller->enable_audio_recording());
}
} // namespace ash } // namespace ash
...@@ -33,7 +33,10 @@ aggregate_vector_icons("ash_vector_icons") { ...@@ -33,7 +33,10 @@ aggregate_vector_icons("ash_vector_icons") {
"capture_mode_copied_to_clipboard.icon", "capture_mode_copied_to_clipboard.icon",
"capture_mode_fullscreen.icon", "capture_mode_fullscreen.icon",
"capture_mode_image.icon", "capture_mode_image.icon",
"capture_mode_mic.icon",
"capture_mode_mic_off.icon",
"capture_mode_region.icon", "capture_mode_region.icon",
"capture_mode_settings.icon",
"capture_mode_video.icon", "capture_mode_video.icon",
"capture_mode_window.icon", "capture_mode_window.icon",
"check_circle.icon", "check_circle.icon",
......
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
CANVAS_DIMENSIONS, 20,
MOVE_TO, 10, 12.11f,
R_CUBIC_TO, 1.42f, 0, 2.56f, -1.13f, 2.56f, -2.53f,
R_LINE_TO, 0.01f, -5.05f,
CUBIC_TO, 12.57f, 3.13f, 11.42f, 2, 10, 2,
CUBIC_TO, 8.58f, 2, 7.43f, 3.13f, 7.43f, 4.53f,
V_LINE_TO, 9.58f,
R_CUBIC_TO, 0, 1.4f, 1.15f, 2.53f, 2.57f, 2.53f,
CLOSE,
R_MOVE_TO, 4.54f, -2.53f,
R_CUBIC_TO, 0, 2.53f, -2.18f, 4.3f, -4.54f, 4.3f,
R_CUBIC_TO, -2.36f, 0, -4.54f, -1.77f, -4.54f, -4.29f,
H_LINE_TO, 4,
R_CUBIC_TO, 0, 2.88f, 2.33f, 5.25f, 5.14f, 5.66f,
V_LINE_TO, 18,
R_H_LINE_TO, 1.71f,
R_V_LINE_TO, -2.76f,
CUBIC_TO, 13.67f, 14.83f, 16, 12.46f, 16, 9.58f,
R_H_LINE_TO, -1.46f,
CLOSE
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
CANVAS_DIMENSIONS, 20,
MOVE_TO, 12.57f, 4.5f,
R_LINE_TO, -0.01f, 5,
R_CUBIC_TO, 0, 0.46f, -0.12f, 0.88f, -0.34f, 1.25f,
R_LINE_TO, -1.22f, -1.22f,
R_V_LINE_TO, -0.02f,
R_LINE_TO, 0.04f, -5,
R_ARC_TO, 1, 1, 0, 1, 0, -2, -0.02f,
R_LINE_TO, -0.02f, 3.06f,
LINE_TO, 7.43f, 5.95f,
V_LINE_TO, 4.5f,
CUBIC_TO, 7.43f, 3.12f, 8.58f, 2, 10, 2,
R_CUBIC_TO, 1.42f, 0, 2.57f, 1.12f, 2.57f, 2.5f,
CLOSE,
MOVE_TO, 2.24f, 3.24f,
LINE_TO, 1, 4.47f,
R_LINE_TO, 9.38f, 9.38f,
R_CUBIC_TO, -0.13f, 0.01f, -0.25f, 0.02f, -0.38f, 0.02f,
R_CUBIC_TO, -2.37f, 0, -4.54f, -1.77f, -4.54f, -4.29f,
H_LINE_TO, 4,
R_CUBIC_TO, 0, 2.88f, 2.33f, 5.25f, 5.14f, 5.66f,
V_LINE_TO, 18,
R_H_LINE_TO, 1.71f,
R_V_LINE_TO, -2.76f,
R_CUBIC_TO, 0.25f, -0.04f, 0.5f, -0.09f, 0.75f, -0.16f,
LINE_TO, 15.52f, 19,
R_LINE_TO, 1.24f, -1.24f,
LINE_TO, 2.24f, 3.24f,
CLOSE,
MOVE_TO, 13.64f, 12.17f,
R_LINE_TO, 1, 1,
CUBIC_TO, 15.48f, 12.18f, 16, 10.94f, 16, 9.58f,
R_H_LINE_TO, -1.46f,
R_ARC_TO, 4.09f, 4.09f, 0, 0, 1, -0.9f, 2.59f,
CLOSE
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
CANVAS_DIMENSIONS, 20,
MOVE_TO, 11.48f, 18,
H_LINE_TO, 8.52f,
R_CUBIC_TO, -0.59f, 0, -1.09f, -0.42f, -1.16f, -0.99f,
R_LINE_TO, -0.22f, -1.47f,
R_ARC_TO, 7.28f, 7.28f, 0, 0, 1, -0.63f, -0.36f,
R_LINE_TO, -1.44f, 0.56f,
R_CUBIC_TO, -0.56f, 0.2f, -1.18f, -0.02f, -1.45f, -0.51f,
R_LINE_TO, -1.46f, -2.47f,
R_CUBIC_TO, -0.28f, -0.52f, -0.16f, -1.12f, 0.29f, -1.47f,
R_LINE_TO, 1.22f, -0.93f,
R_ARC_TO, 5.17f, 5.17f, 0, 0, 1, -0.02f, -0.36f,
R_CUBIC_TO, 0, -0.12f, 0.01f, -0.24f, 0.02f, -0.36f,
R_LINE_TO, -1.22f, -0.93f,
ARC_TO, 1.11f, 1.11f, 0, 0, 1, 2.16f, 7.24f,
R_LINE_TO, 1.48f, -2.49f,
R_CUBIC_TO, 0.27f, -0.48f, 0.89f, -0.7f, 1.43f, -0.49f,
R_LINE_TO, 1.45f, 0.57f,
R_ARC_TO, 8.51f, 8.51f, 0, 0, 1, 0.62f, -0.36f,
R_LINE_TO, 0.22f, -1.49f,
CUBIC_TO, 7.43f, 2.43f, 7.93f, 2, 8.51f, 2,
R_H_LINE_TO, 2.96f,
R_CUBIC_TO, 0.59f, 0, 1.09f, 0.42f, 1.16f, 0.99f,
R_LINE_TO, 0.22f, 1.48f,
R_CUBIC_TO, 0.22f, 0.11f, 0.42f, 0.23f, 0.63f, 0.36f,
R_LINE_TO, 1.44f, -0.56f,
R_CUBIC_TO, 0.57f, -0.2f, 1.18f, 0.02f, 1.46f, 0.51f,
R_LINE_TO, 1.47f, 2.48f,
R_ARC_TO, 1.13f, 1.13f, 0, 0, 1, -0.29f, 1.47f,
R_LINE_TO, -1.22f, 0.93f,
R_CUBIC_TO, 0.01f, 0.12f, 0.02f, 0.23f, 0.02f, 0.36f,
R_CUBIC_TO, 0, 0.13f, -0.01f, 0.24f, -0.02f, 0.36f,
R_LINE_TO, 1.22f, 0.93f,
R_CUBIC_TO, 0.45f, 0.35f, 0.58f, 0.96f, 0.3f, 1.45f,
R_LINE_TO, -1.49f, 2.51f,
R_CUBIC_TO, -0.27f, 0.48f, -0.89f, 0.7f, -1.44f, 0.49f,
R_LINE_TO, -1.44f, -0.56f,
R_ARC_TO, 8.54f, 8.54f, 0, 0, 1, -0.62f, 0.36f,
R_LINE_TO, -0.22f, 1.49f,
R_CUBIC_TO, -0.08f, 0.53f, -0.58f, 0.95f, -1.17f, 0.95f,
CLOSE,
R_MOVE_TO, -2.53f, -2,
R_H_LINE_TO, 2.11f,
R_LINE_TO, 0.28f, -1.85f,
R_LINE_TO, 0.41f, -0.16f,
R_CUBIC_TO, 0.34f, -0.13f, 0.67f, -0.32f, 1.03f, -0.57f,
R_LINE_TO, 0.35f, -0.25f,
R_LINE_TO, 1.82f, 0.7f,
LINE_TO, 16, 12.12f,
R_LINE_TO, -1.55f, -1.15f,
R_LINE_TO, 0.05f, -0.41f,
R_CUBIC_TO, 0.02f, -0.19f, 0.05f, -0.37f, 0.05f, -0.57f,
R_CUBIC_TO, 0, -0.2f, -0.02f, -0.38f, -0.05f, -0.57f,
R_LINE_TO, -0.05f, -0.41f,
LINE_TO, 16, 7.88f,
R_LINE_TO, -1.06f, -1.74f,
R_LINE_TO, -1.83f, 0.7f,
R_LINE_TO, -0.34f, -0.25f,
R_ARC_TO, 4.63f, 4.63f, 0, 0, 0, -1.02f, -0.56f,
R_LINE_TO, -0.4f, -0.16f,
LINE_TO, 11.06f, 4,
H_LINE_TO, 8.95f,
R_LINE_TO, -0.28f, 1.86f,
R_LINE_TO, -0.41f, 0.15f,
R_ARC_TO, 4.91f, 4.91f, 0, 0, 0, -1.03f, 0.57f,
R_LINE_TO, -0.34f, 0.24f,
R_LINE_TO, -1.82f, -0.69f,
LINE_TO, 4, 7.87f,
R_LINE_TO, 1.56f, 1.15f,
R_LINE_TO, -0.05f, 0.41f,
R_CUBIC_TO, -0.02f, 0.19f, -0.05f, 0.39f, -0.05f, 0.57f,
R_CUBIC_TO, 0, 0.19f, 0.02f, 0.39f, 0.05f, 0.57f,
R_LINE_TO, 0.05f, 0.41f,
LINE_TO, 4, 12.12f,
R_LINE_TO, 1.06f, 1.75f,
R_LINE_TO, 1.83f, -0.7f,
R_LINE_TO, 0.35f, 0.26f,
R_CUBIC_TO, 0.33f, 0.24f, 0.66f, 0.42f, 1.02f, 0.56f,
R_LINE_TO, 0.41f, 0.16f,
LINE_TO, 8.95f, 16,
CLOSE,
MOVE_TO, 10, 12.5f,
R_ARC_TO, 2.5f, 2.5f, 0, 1, 0, 0, -5,
R_ARC_TO, 2.5f, 2.5f, 0, 0, 0, 0, 5,
CLOSE
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment