Enable annotating in capture mode under a feature flag
Always enable annotating in video recording capture mode, if kAnnotatorMode feature is enabled. This means that now the annotation tray will be shown not just in Screencast session, but also in capture mode session. Video: https://drive.google.com/file/d/12sODPcbjrhyXtq5O6cDyDr2Q65pAqmDc/view?usp=sharing&resourcekey=0-t9W626wpnn-E2Nok_mo9JQ Test: AnnotatorCaptureModeIntegrationTests Bug: 342104047 Change-Id: Ie3e830c763fe1bb5952f8ea4d29eebac5b3eefa5 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5695447 Reviewed-by: Sean Kau <skau@chromium.org> Reviewed-by: Xiaoqian Dai <xdai@chromium.org> Commit-Queue: Sanja Perisic <sanjaperisic@chromium.org> Reviewed-by: Michele Fan <michelefan@chromium.org> Cr-Commit-Position: refs/heads/main@{#1328342}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
3016407dba
commit
e840fe256e
ash
@ -5,8 +5,10 @@
|
||||
#include "ash/annotator/annotation_source_watcher.h"
|
||||
|
||||
#include "ash/annotator/annotator_controller.h"
|
||||
#include "ash/constants/ash_features.h"
|
||||
#include "ash/projector/projector_controller_impl.h"
|
||||
#include "ash/shell.h"
|
||||
#include "base/feature_list.h"
|
||||
#include "ui/aura/window.h"
|
||||
#include "ui/gfx/image/image_skia.h"
|
||||
|
||||
@ -17,10 +19,14 @@ AnnotationSourceWatcher::AnnotationSourceWatcher(
|
||||
: annotator_controller_(annotator_controller) {
|
||||
capture_mode_controller_ = CaptureModeController::Get();
|
||||
capture_mode_observation_.Observe(capture_mode_controller_);
|
||||
ProjectorControllerImpl* projector_controller =
|
||||
Shell::Get()->projector_controller();
|
||||
projector_session_observation_.Observe(
|
||||
projector_controller->projector_session());
|
||||
// There is no need to observe projector session if the annotator feature is
|
||||
// always enabled in capture mode. Only observe when the feature is disabled.
|
||||
if (!base::FeatureList::IsEnabled(ash::features::kAnnotatorMode)) {
|
||||
ProjectorControllerImpl* projector_controller =
|
||||
Shell::Get()->projector_controller();
|
||||
projector_session_observation_.Observe(
|
||||
projector_controller->projector_session());
|
||||
}
|
||||
}
|
||||
|
||||
AnnotationSourceWatcher::~AnnotationSourceWatcher() {
|
||||
@ -37,7 +43,8 @@ void AnnotationSourceWatcher::OnRecordingStarted(aura::Window* current_root) {
|
||||
|
||||
// TODO(b/342104047): Remove this check once the annotator is always enabled
|
||||
// in capture mode.
|
||||
if (!is_projector_session_active_) {
|
||||
if (!base::FeatureList::IsEnabled(ash::features::kAnnotatorMode) &&
|
||||
!is_projector_session_active_) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -51,7 +58,8 @@ void AnnotationSourceWatcher::OnRecordingEnded() {
|
||||
|
||||
// TODO(b/342104047): Remove this check once the annotator is always enabled
|
||||
// in capture mode.
|
||||
if (!is_projector_session_active_) {
|
||||
if (!base::FeatureList::IsEnabled(ash::features::kAnnotatorMode) &&
|
||||
!is_projector_session_active_) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -70,7 +78,8 @@ void AnnotationSourceWatcher::OnRecordedWindowChangingRoot(
|
||||
|
||||
// TODO(b/342104047): Remove this check once the annotator is always enabled
|
||||
// in capture mode.
|
||||
if (!is_projector_session_active_) {
|
||||
if (!base::FeatureList::IsEnabled(ash::features::kAnnotatorMode) &&
|
||||
!is_projector_session_active_) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -84,7 +93,8 @@ void AnnotationSourceWatcher::OnRecordingStartAborted() {
|
||||
|
||||
// TODO(b/342104047): Remove this check once the annotator is always enabled
|
||||
// in capture mode.
|
||||
if (!is_projector_session_active_) {
|
||||
if (!base::FeatureList::IsEnabled(ash::features::kAnnotatorMode) &&
|
||||
!is_projector_session_active_) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -17,11 +17,13 @@
|
||||
#include "ash/capture_mode/capture_mode_util.h"
|
||||
#include "ash/capture_mode/game_capture_bar_view.h"
|
||||
#include "ash/capture_mode/normal_capture_bar_view.h"
|
||||
#include "ash/constants/ash_features.h"
|
||||
#include "ash/projector/projector_controller_impl.h"
|
||||
#include "ash/shelf/shelf.h"
|
||||
#include "ash/shelf/shelf_layout_manager.h"
|
||||
#include "ash/shell.h"
|
||||
#include "ash/strings/grit/ash_strings.h"
|
||||
#include "base/feature_list.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback_forward.h"
|
||||
@ -378,6 +380,9 @@ bool CaptureModeBehavior::ShouldSkipVideoRecordingCountDown() const {
|
||||
}
|
||||
|
||||
bool CaptureModeBehavior::ShouldCreateAnnotationsOverlayController() const {
|
||||
if (base::FeatureList::IsEnabled(ash::features::kAnnotatorMode)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -356,6 +356,20 @@ class CaptureModeTest : public AshTestBase {
|
||||
wm::SetModalParent(child.get(), transient_parent);
|
||||
return child;
|
||||
}
|
||||
|
||||
void VerifyOverlayWindow(aura::Window* overlay_window,
|
||||
CaptureModeSource source,
|
||||
const gfx::Rect user_region) {
|
||||
VerifyOverlayWindowForCaptureMode(overlay_window, GetWindowBeingRecorded(),
|
||||
source, user_region);
|
||||
}
|
||||
|
||||
aura::Window* GetWindowBeingRecorded() const {
|
||||
auto* controller = CaptureModeController::Get();
|
||||
DCHECK(controller->is_recording_in_progress());
|
||||
return controller->video_recording_watcher_for_testing()
|
||||
->window_being_recorded();
|
||||
}
|
||||
};
|
||||
|
||||
class CaptureSessionWidgetClosed {
|
||||
@ -5395,21 +5409,6 @@ class ProjectorCaptureModeIntegrationTests
|
||||
EXPECT_TRUE(controller->is_recording_in_progress());
|
||||
}
|
||||
|
||||
void VerifyOverlayWindow(aura::Window* overlay_window,
|
||||
CaptureModeSource source) {
|
||||
auto* window_being_recorded = GetWindowBeingRecorded();
|
||||
|
||||
VerifyOverlayWindowForCaptureMode(overlay_window, window_being_recorded,
|
||||
source, kUserRegion);
|
||||
}
|
||||
|
||||
aura::Window* GetWindowBeingRecorded() const {
|
||||
auto* controller = CaptureModeController::Get();
|
||||
DCHECK(controller->is_recording_in_progress());
|
||||
return controller->video_recording_watcher_for_testing()
|
||||
->window_being_recorded();
|
||||
}
|
||||
|
||||
protected:
|
||||
ProjectorCaptureModeIntegrationHelper projector_helper_;
|
||||
std::unique_ptr<aura::Window> window_;
|
||||
@ -5872,7 +5871,7 @@ TEST_P(ProjectorCaptureModeIntegrationTests, AnnotationsOverlayWidgetBounds) {
|
||||
test_api.GetAnnotationsOverlayController();
|
||||
EXPECT_FALSE(overlay_controller->is_enabled());
|
||||
auto* overlay_window = overlay_controller->GetOverlayNativeWindow();
|
||||
VerifyOverlayWindow(overlay_window, capture_source);
|
||||
VerifyOverlayWindow(overlay_window, capture_source, kUserRegion);
|
||||
}
|
||||
|
||||
// Regression test for https://crbug.com/1322655.
|
||||
@ -5897,7 +5896,7 @@ TEST_P(ProjectorCaptureModeIntegrationTests,
|
||||
test_api.GetAnnotationsOverlayController();
|
||||
EXPECT_FALSE(overlay_controller->is_enabled());
|
||||
auto* overlay_window = overlay_controller->GetOverlayNativeWindow();
|
||||
VerifyOverlayWindow(overlay_window, capture_source);
|
||||
VerifyOverlayWindow(overlay_window, capture_source, kUserRegion);
|
||||
}
|
||||
|
||||
// Tests the projector behavior in the projector-initiated capture mode session
|
||||
@ -5965,163 +5964,6 @@ TEST_P(ProjectorCaptureModeIntegrationTests, ProjectorBehavior) {
|
||||
CaptureModeTestApi().StopVideoRecording();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Defines a class that intercepts the events at the post-target handling phase
|
||||
// and caches the last event target to which the event was routed.
|
||||
class EventTargetCatcher : public ui::EventHandler {
|
||||
public:
|
||||
EventTargetCatcher() {
|
||||
Shell::GetPrimaryRootWindow()->AddPostTargetHandler(this);
|
||||
}
|
||||
EventTargetCatcher(const EventTargetCatcher&) = delete;
|
||||
EventTargetCatcher& operator=(const EventTargetCatcher&) = delete;
|
||||
~EventTargetCatcher() override {
|
||||
Shell::GetPrimaryRootWindow()->RemovePostTargetHandler(this);
|
||||
}
|
||||
|
||||
ui::EventTarget* last_event_target() { return last_event_target_; }
|
||||
|
||||
// ui::EventHandler:
|
||||
void OnEvent(ui::Event* event) override {
|
||||
ui::EventHandler::OnEvent(event);
|
||||
last_event_target_ = event->target();
|
||||
}
|
||||
|
||||
private:
|
||||
raw_ptr<ui::EventTarget> last_event_target_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_F(ProjectorCaptureModeIntegrationTests,
|
||||
AnnotationsOverlayWidgetTargeting) {
|
||||
auto* controller = CaptureModeController::Get();
|
||||
controller->SetSource(CaptureModeSource::kFullscreen);
|
||||
StartProjectorModeSession();
|
||||
EXPECT_TRUE(controller->IsActive());
|
||||
|
||||
PressAndReleaseKey(ui::VKEY_RETURN);
|
||||
WaitForRecordingToStart();
|
||||
CaptureModeTestApi test_api;
|
||||
AnnotationsOverlayController* overlay_controller =
|
||||
test_api.GetAnnotationsOverlayController();
|
||||
|
||||
auto* annotator_controller = Shell::Get()->annotator_controller();
|
||||
annotator_controller->EnableAnnotatorTool();
|
||||
EXPECT_TRUE(overlay_controller->is_enabled());
|
||||
auto* overlay_window = overlay_controller->GetOverlayNativeWindow();
|
||||
VerifyOverlayEnabledState(overlay_window, /*overlay_enabled_state=*/true);
|
||||
|
||||
// Open the annotation tray bubble.
|
||||
auto* root_window = Shell::GetPrimaryRootWindow();
|
||||
auto* status_area_widget =
|
||||
RootWindowController::ForWindow(root_window)->GetStatusAreaWidget();
|
||||
AnnotationTray* annotations_tray = status_area_widget->annotation_tray();
|
||||
annotations_tray->ShowBubble();
|
||||
EXPECT_TRUE(annotations_tray->GetBubbleView());
|
||||
|
||||
// Clicking anywhere outside the projector shelf pod should be targeted to the
|
||||
// overlay widget window and close the annotation tray bubble.
|
||||
EventTargetCatcher event_target_catcher;
|
||||
auto* event_generator = GetEventGenerator();
|
||||
event_generator->set_current_screen_location(gfx::Point(10, 10));
|
||||
event_generator->ClickLeftButton();
|
||||
EXPECT_EQ(overlay_window, event_target_catcher.last_event_target());
|
||||
EXPECT_FALSE(annotations_tray->GetBubbleView());
|
||||
|
||||
// Now move the mouse over the projector shelf pod, the overlay should not
|
||||
// consume the event, and it should instead go through to that pod.
|
||||
EXPECT_TRUE(annotations_tray->visible_preferred());
|
||||
event_generator->MoveMouseTo(
|
||||
annotations_tray->GetBoundsInScreen().CenterPoint());
|
||||
EXPECT_EQ(annotations_tray->GetWidget()->GetNativeWindow(),
|
||||
event_target_catcher.last_event_target());
|
||||
|
||||
// The overlay status hasn't changed.
|
||||
VerifyOverlayEnabledState(overlay_window, /*overlay_enabled_state=*/true);
|
||||
|
||||
// Now move the mouse and then click on the stop recording button, the overlay
|
||||
// should not consume the event. The video recording should be ended.
|
||||
StopRecordingButtonTray* stop_recording_button =
|
||||
status_area_widget->stop_recording_button_tray();
|
||||
const gfx::Point stop_button_center_point =
|
||||
stop_recording_button->GetBoundsInScreen().CenterPoint();
|
||||
event_generator->MoveMouseTo(stop_button_center_point);
|
||||
event_generator->ClickLeftButton();
|
||||
EXPECT_FALSE(controller->is_recording_in_progress());
|
||||
}
|
||||
|
||||
// Tests that auto hidden shelf can be brought back if user moves mouse to the
|
||||
// shelf activation area even while annotation is active.
|
||||
TEST_F(ProjectorCaptureModeIntegrationTests,
|
||||
BringBackAutoHiddenShelfWhileAnnotationIsOn) {
|
||||
auto* root_window = Shell::GetPrimaryRootWindow();
|
||||
// Set `shelf` to always auto-hidden.
|
||||
Shelf* shelf = RootWindowController::ForWindow(root_window)->shelf();
|
||||
shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
|
||||
|
||||
auto* controller = CaptureModeController::Get();
|
||||
controller->SetSource(CaptureModeSource::kFullscreen);
|
||||
StartProjectorModeSession();
|
||||
EXPECT_TRUE(controller->IsActive());
|
||||
|
||||
PressAndReleaseKey(ui::VKEY_RETURN);
|
||||
WaitForRecordingToStart();
|
||||
|
||||
auto* event_generator = GetEventGenerator();
|
||||
auto* annotator_controller = Shell::Get()->annotator_controller();
|
||||
|
||||
const gfx::Rect root_window_bounds_in_screen =
|
||||
root_window->GetBoundsInScreen();
|
||||
const int display_width = root_window_bounds_in_screen.width();
|
||||
const int display_height = root_window_bounds_in_screen.height();
|
||||
const gfx::Point display_center = root_window_bounds_in_screen.CenterPoint();
|
||||
|
||||
struct {
|
||||
const std::string scope_trace;
|
||||
const ShelfAlignment shelf_alignment;
|
||||
} kAlignmentTestCases[] = {
|
||||
{"Shelf has botton alignment", ShelfAlignment::kBottom},
|
||||
{"Shelf has left alignment", ShelfAlignment::kLeft},
|
||||
{"Shelf has right alignment", ShelfAlignment::kRight},
|
||||
};
|
||||
|
||||
for (const auto& test_case : kAlignmentTestCases) {
|
||||
SCOPED_TRACE(test_case.scope_trace);
|
||||
// Enable annotation.
|
||||
annotator_controller->EnableAnnotatorTool();
|
||||
|
||||
// Verify shelf is invisible right now.
|
||||
EXPECT_FALSE(shelf->IsVisible());
|
||||
|
||||
shelf->SetAlignment(test_case.shelf_alignment);
|
||||
switch (test_case.shelf_alignment) {
|
||||
case ShelfAlignment::kBottom:
|
||||
case ShelfAlignment::kBottomLocked:
|
||||
event_generator->MoveMouseTo(0, display_height);
|
||||
break;
|
||||
case ShelfAlignment::kLeft:
|
||||
event_generator->MoveMouseTo(0, display_height);
|
||||
break;
|
||||
case ShelfAlignment::kRight:
|
||||
event_generator->MoveMouseTo(display_width, display_height);
|
||||
break;
|
||||
}
|
||||
// Verify after mouse is moved on top of the shelf activation area, shelf is
|
||||
// brought back and visible once the animation to show shelf is finished.
|
||||
ShellTestApi().WaitForWindowFinishAnimating(shelf->GetWindow());
|
||||
EXPECT_TRUE(shelf->IsVisible());
|
||||
|
||||
// Disable annotation.
|
||||
annotator_controller->ResetTools();
|
||||
// Move mouse to the outside of the shelf activation area, and wait for the
|
||||
// animation to hide shelf to finish.
|
||||
event_generator->MoveMouseTo(display_center);
|
||||
ShellTestApi().WaitForWindowFinishAnimating(shelf->GetWindow());
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that neither preview notification nor recording in tote is shown if in
|
||||
// projector mode.
|
||||
TEST_P(ProjectorCaptureModeIntegrationTests,
|
||||
@ -6284,6 +6126,307 @@ INSTANTIATE_TEST_SUITE_P(All,
|
||||
CaptureModeSource::kRegion,
|
||||
CaptureModeSource::kWindow));
|
||||
|
||||
class AnnotatorCaptureModeIntegrationTests
|
||||
: public CaptureModeTest,
|
||||
public ::testing::WithParamInterface<CaptureModeSource> {
|
||||
public:
|
||||
AnnotatorCaptureModeIntegrationTests() = default;
|
||||
~AnnotatorCaptureModeIntegrationTests() override = default;
|
||||
|
||||
static constexpr gfx::Rect kUserRegion{20, 50, 60, 70};
|
||||
|
||||
aura::Window* window() const { return window_.get(); }
|
||||
|
||||
// CaptureModeTest:
|
||||
void SetUp() override {
|
||||
CaptureModeTest::SetUp();
|
||||
annotator_helper_.SetUp();
|
||||
window_ = CreateTestWindow(gfx::Rect(20, 30, 200, 200));
|
||||
CaptureModeController::Get()->SetUserCaptureRegion(kUserRegion,
|
||||
/*by_user=*/true);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
window_.reset();
|
||||
CaptureModeTest::TearDown();
|
||||
}
|
||||
|
||||
void StartRecordingFromSource(CaptureModeSource source) {
|
||||
ash::CaptureModeTestApi test_api;
|
||||
|
||||
switch (source) {
|
||||
case CaptureModeSource::kFullscreen:
|
||||
test_api.StartForFullscreen(/*for_video=*/true);
|
||||
break;
|
||||
case CaptureModeSource::kRegion:
|
||||
test_api.StartForRegion(/*for_video=*/true);
|
||||
break;
|
||||
case CaptureModeSource::kWindow:
|
||||
test_api.StartForWindow(/*for_video=*/true);
|
||||
auto* generator = GetEventGenerator();
|
||||
generator->MoveMouseTo(window_->GetBoundsInScreen().CenterPoint());
|
||||
break;
|
||||
}
|
||||
CaptureModeTestApi().PerformCapture();
|
||||
WaitForRecordingToStart();
|
||||
EXPECT_TRUE(CaptureModeController::Get()->is_recording_in_progress());
|
||||
}
|
||||
|
||||
protected:
|
||||
AnnotatorIntegrationHelper annotator_helper_;
|
||||
std::unique_ptr<aura::Window> window_;
|
||||
base::HistogramTester histogram_tester_;
|
||||
};
|
||||
|
||||
TEST_F(AnnotatorCaptureModeIntegrationTests, AnnotationsOverlayWidget) {
|
||||
StartRecordingFromSource(CaptureModeSource::kFullscreen);
|
||||
|
||||
PressAndReleaseKey(ui::VKEY_RETURN);
|
||||
WaitForRecordingToStart();
|
||||
CaptureModeTestApi test_api;
|
||||
AnnotationsOverlayController* overlay_controller =
|
||||
test_api.GetAnnotationsOverlayController();
|
||||
EXPECT_FALSE(overlay_controller->is_enabled());
|
||||
auto* overlay_window = overlay_controller->GetOverlayNativeWindow();
|
||||
VerifyOverlayEnabledState(overlay_window, /*overlay_enabled_state=*/false);
|
||||
|
||||
auto* annotator_controller = Shell::Get()->annotator_controller();
|
||||
annotator_controller->EnableAnnotatorTool();
|
||||
EXPECT_TRUE(overlay_controller->is_enabled());
|
||||
VerifyOverlayEnabledState(overlay_window, /*overlay_enabled_state=*/true);
|
||||
|
||||
annotator_controller->ResetTools();
|
||||
EXPECT_FALSE(overlay_controller->is_enabled());
|
||||
VerifyOverlayEnabledState(overlay_window, /*overlay_enabled_state=*/false);
|
||||
}
|
||||
|
||||
TEST_F(AnnotatorCaptureModeIntegrationTests,
|
||||
AnnotationsOverlayDockedMagnifier) {
|
||||
StartRecordingFromSource(CaptureModeSource::kFullscreen);
|
||||
|
||||
PressAndReleaseKey(ui::VKEY_RETURN);
|
||||
WaitForRecordingToStart();
|
||||
CaptureModeTestApi test_api;
|
||||
AnnotationsOverlayController* overlay_controller =
|
||||
test_api.GetAnnotationsOverlayController();
|
||||
|
||||
auto* annotator_controller = Shell::Get()->annotator_controller();
|
||||
annotator_controller->EnableAnnotatorTool();
|
||||
EXPECT_TRUE(overlay_controller->is_enabled());
|
||||
auto* overlay_window = overlay_controller->GetOverlayNativeWindow();
|
||||
|
||||
// Before the docked magnifier gets enabled, the overlay's bounds should match
|
||||
// the root window's bounds.
|
||||
auto* root_window = overlay_window->GetRootWindow();
|
||||
const gfx::Rect root_window_bounds = root_window->bounds();
|
||||
EXPECT_EQ(root_window_bounds, overlay_window->GetBoundsInRootWindow());
|
||||
|
||||
// Once the magnifier is enabled, the overlay should be pushed down so that
|
||||
// it doesn't cover the magnifier viewport.
|
||||
auto* docked_magnifier = Shell::Get()->docked_magnifier_controller();
|
||||
docked_magnifier->SetEnabled(true);
|
||||
const gfx::Rect expected_bounds = gfx::SubtractRects(
|
||||
root_window_bounds,
|
||||
docked_magnifier->GetTotalMagnifierBoundsForRoot(root_window));
|
||||
EXPECT_EQ(expected_bounds, overlay_window->GetBoundsInRootWindow());
|
||||
|
||||
// It should go back to original bounds once the magnifier is disabled.
|
||||
docked_magnifier->SetEnabled(false);
|
||||
EXPECT_EQ(root_window_bounds, overlay_window->GetBoundsInRootWindow());
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Defines a class that intercepts the events at the post-target handling phase
|
||||
// and caches the last event target to which the event was routed.
|
||||
class EventTargetCatcher : public ui::EventHandler {
|
||||
public:
|
||||
EventTargetCatcher() {
|
||||
Shell::GetPrimaryRootWindow()->AddPostTargetHandler(this);
|
||||
}
|
||||
EventTargetCatcher(const EventTargetCatcher&) = delete;
|
||||
EventTargetCatcher& operator=(const EventTargetCatcher&) = delete;
|
||||
~EventTargetCatcher() override {
|
||||
Shell::GetPrimaryRootWindow()->RemovePostTargetHandler(this);
|
||||
}
|
||||
|
||||
ui::EventTarget* last_event_target() { return last_event_target_; }
|
||||
|
||||
// ui::EventHandler:
|
||||
void OnEvent(ui::Event* event) override {
|
||||
ui::EventHandler::OnEvent(event);
|
||||
last_event_target_ = event->target();
|
||||
}
|
||||
|
||||
private:
|
||||
raw_ptr<ui::EventTarget> last_event_target_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_F(AnnotatorCaptureModeIntegrationTests,
|
||||
AnnotationsOverlayWidgetTargeting) {
|
||||
StartRecordingFromSource(CaptureModeSource::kFullscreen);
|
||||
|
||||
PressAndReleaseKey(ui::VKEY_RETURN);
|
||||
WaitForRecordingToStart();
|
||||
CaptureModeTestApi test_api;
|
||||
AnnotationsOverlayController* overlay_controller =
|
||||
test_api.GetAnnotationsOverlayController();
|
||||
|
||||
auto* annotator_controller = Shell::Get()->annotator_controller();
|
||||
annotator_controller->EnableAnnotatorTool();
|
||||
EXPECT_TRUE(overlay_controller->is_enabled());
|
||||
auto* overlay_window = overlay_controller->GetOverlayNativeWindow();
|
||||
VerifyOverlayEnabledState(overlay_window, /*overlay_enabled_state=*/true);
|
||||
|
||||
// Open the annotation tray bubble.
|
||||
auto* root_window = Shell::GetPrimaryRootWindow();
|
||||
auto* status_area_widget =
|
||||
RootWindowController::ForWindow(root_window)->GetStatusAreaWidget();
|
||||
AnnotationTray* annotations_tray = status_area_widget->annotation_tray();
|
||||
annotations_tray->ShowBubble();
|
||||
EXPECT_TRUE(annotations_tray->GetBubbleView());
|
||||
|
||||
// Clicking anywhere outside the projector shelf pod should be targeted to the
|
||||
// overlay widget window and close the annotation tray bubble.
|
||||
EventTargetCatcher event_target_catcher;
|
||||
auto* event_generator = GetEventGenerator();
|
||||
event_generator->set_current_screen_location(gfx::Point(10, 10));
|
||||
event_generator->ClickLeftButton();
|
||||
EXPECT_EQ(overlay_window, event_target_catcher.last_event_target());
|
||||
EXPECT_FALSE(annotations_tray->GetBubbleView());
|
||||
|
||||
// Now move the mouse over the projector shelf pod, the overlay should not
|
||||
// consume the event, and it should instead go through to that pod.
|
||||
EXPECT_TRUE(annotations_tray->visible_preferred());
|
||||
event_generator->MoveMouseTo(
|
||||
annotations_tray->GetBoundsInScreen().CenterPoint());
|
||||
EXPECT_EQ(annotations_tray->GetWidget()->GetNativeWindow(),
|
||||
event_target_catcher.last_event_target());
|
||||
|
||||
// The overlay status hasn't changed.
|
||||
VerifyOverlayEnabledState(overlay_window, /*overlay_enabled_state=*/true);
|
||||
|
||||
// Now move the mouse and then click on the stop recording button, the overlay
|
||||
// should not consume the event. The video recording should be ended.
|
||||
StopRecordingButtonTray* stop_recording_button =
|
||||
status_area_widget->stop_recording_button_tray();
|
||||
const gfx::Point stop_button_center_point =
|
||||
stop_recording_button->GetBoundsInScreen().CenterPoint();
|
||||
event_generator->MoveMouseTo(stop_button_center_point);
|
||||
event_generator->ClickLeftButton();
|
||||
EXPECT_FALSE(CaptureModeController::Get()->is_recording_in_progress());
|
||||
}
|
||||
|
||||
// Tests that auto hidden shelf can be brought back if user moves mouse to the
|
||||
// shelf activation area even while annotation is active.
|
||||
TEST_F(AnnotatorCaptureModeIntegrationTests,
|
||||
BringBackAutoHiddenShelfWhileAnnotationIsOn) {
|
||||
auto* root_window = Shell::GetPrimaryRootWindow();
|
||||
// Set `shelf` to always auto-hidden.
|
||||
Shelf* shelf = RootWindowController::ForWindow(root_window)->shelf();
|
||||
shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
|
||||
|
||||
StartRecordingFromSource(CaptureModeSource::kFullscreen);
|
||||
|
||||
PressAndReleaseKey(ui::VKEY_RETURN);
|
||||
WaitForRecordingToStart();
|
||||
|
||||
auto* event_generator = GetEventGenerator();
|
||||
auto* annotator_controller = Shell::Get()->annotator_controller();
|
||||
|
||||
const gfx::Rect root_window_bounds_in_screen =
|
||||
root_window->GetBoundsInScreen();
|
||||
const int display_width = root_window_bounds_in_screen.width();
|
||||
const int display_height = root_window_bounds_in_screen.height();
|
||||
const gfx::Point display_center = root_window_bounds_in_screen.CenterPoint();
|
||||
|
||||
struct {
|
||||
const std::string scope_trace;
|
||||
const ShelfAlignment shelf_alignment;
|
||||
} kAlignmentTestCases[] = {
|
||||
{"Shelf has botton alignment", ShelfAlignment::kBottom},
|
||||
{"Shelf has left alignment", ShelfAlignment::kLeft},
|
||||
{"Shelf has right alignment", ShelfAlignment::kRight},
|
||||
};
|
||||
|
||||
for (const auto& test_case : kAlignmentTestCases) {
|
||||
SCOPED_TRACE(test_case.scope_trace);
|
||||
// Enable annotation.
|
||||
annotator_controller->EnableAnnotatorTool();
|
||||
|
||||
// Verify shelf is invisible right now.
|
||||
EXPECT_FALSE(shelf->IsVisible());
|
||||
|
||||
shelf->SetAlignment(test_case.shelf_alignment);
|
||||
switch (test_case.shelf_alignment) {
|
||||
case ShelfAlignment::kBottom:
|
||||
case ShelfAlignment::kBottomLocked:
|
||||
event_generator->MoveMouseTo(0, display_height);
|
||||
break;
|
||||
case ShelfAlignment::kLeft:
|
||||
event_generator->MoveMouseTo(0, display_height);
|
||||
break;
|
||||
case ShelfAlignment::kRight:
|
||||
event_generator->MoveMouseTo(display_width, display_height);
|
||||
break;
|
||||
}
|
||||
// Verify after mouse is moved on top of the shelf activation area, shelf is
|
||||
// brought back and visible once the animation to show shelf is finished.
|
||||
ShellTestApi().WaitForWindowFinishAnimating(shelf->GetWindow());
|
||||
EXPECT_TRUE(shelf->IsVisible());
|
||||
|
||||
// Disable annotation.
|
||||
annotator_controller->ResetTools();
|
||||
// Move mouse to the outside of the shelf activation area, and wait for the
|
||||
// animation to hide shelf to finish.
|
||||
event_generator->MoveMouseTo(display_center);
|
||||
ShellTestApi().WaitForWindowFinishAnimating(shelf->GetWindow());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(AnnotatorCaptureModeIntegrationTests, AnnotationsOverlayWidgetBounds) {
|
||||
const auto capture_source = GetParam();
|
||||
StartRecordingFromSource(capture_source);
|
||||
CaptureModeTestApi test_api;
|
||||
AnnotationsOverlayController* overlay_controller =
|
||||
test_api.GetAnnotationsOverlayController();
|
||||
EXPECT_FALSE(overlay_controller->is_enabled());
|
||||
auto* overlay_window = overlay_controller->GetOverlayNativeWindow();
|
||||
VerifyOverlayWindow(overlay_window, capture_source, kUserRegion);
|
||||
}
|
||||
|
||||
TEST_P(AnnotatorCaptureModeIntegrationTests,
|
||||
AnnotationsOverlayWidgetBoundsSecondDisplay) {
|
||||
UpdateDisplay("800x700,801+0-800x700");
|
||||
const gfx::Point point_in_second_display = gfx::Point(1000, 500);
|
||||
auto* event_generator = GetEventGenerator();
|
||||
event_generator->MoveMouseTo(point_in_second_display);
|
||||
window()->SetBoundsInScreen(
|
||||
gfx::Rect(900, 0, 600, 500),
|
||||
display::Screen::GetScreen()->GetDisplayNearestWindow(
|
||||
Shell::GetAllRootWindows()[1]));
|
||||
|
||||
const auto capture_source = GetParam();
|
||||
StartRecordingFromSource(capture_source);
|
||||
const auto roots = Shell::GetAllRootWindows();
|
||||
EXPECT_EQ(roots[1], GetWindowBeingRecorded()->GetRootWindow());
|
||||
|
||||
CaptureModeTestApi test_api;
|
||||
AnnotationsOverlayController* overlay_controller =
|
||||
test_api.GetAnnotationsOverlayController();
|
||||
EXPECT_FALSE(overlay_controller->is_enabled());
|
||||
auto* overlay_window = overlay_controller->GetOverlayNativeWindow();
|
||||
VerifyOverlayWindow(overlay_window, capture_source, kUserRegion);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(All,
|
||||
AnnotatorCaptureModeIntegrationTests,
|
||||
testing::Values(CaptureModeSource::kFullscreen,
|
||||
CaptureModeSource::kRegion,
|
||||
CaptureModeSource::kWindow));
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// CaptureModeSettingsTest:
|
||||
|
||||
|
Reference in New Issue
Block a user