Commit fd3bbf88 authored by Sammie Quon's avatar Sammie Quon Committed by Commit Bot

capture_mode: Multi-display behavior for capture mode.

Capture bar appears on the display with the mouse cursor. The other
displays are dimmed out. In fullscreen capture mode, users can move the
mouse to the other display to focus that display. In region capture
mode, moving the mouse to the other display does nothing, but pressing
the mouse on the display will focus that display.

Focusing a display will move the widgets and the layer owned by the
session to the display.

See videos in linked bug for demos.

Test: added test
Bug: 1133454
Change-Id: If237ca653736e94549d7005f09ecc9c8e94dc8c1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2440874
Commit-Queue: Sammie Quon <sammiequon@chromium.org>
Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Cr-Commit-Position: refs/heads/master@{#817148}
parent 522d21ad
......@@ -75,8 +75,8 @@ CaptureModeBarView::~CaptureModeBarView() = default;
gfx::Rect CaptureModeBarView::GetBounds(aura::Window* root) {
DCHECK(root);
auto bounds = root->GetBoundsInRootWindow();
const int y = bounds.height() - kDistanceFromScreenBottom - kBarSize.height();
auto bounds = root->GetBoundsInScreen();
const int y = bounds.bottom() - kDistanceFromScreenBottom - kBarSize.height();
bounds.ClampToCenteredSize(kBarSize);
bounds.set_y(y);
return bounds;
......
......@@ -52,7 +52,8 @@ class ASH_EXPORT CaptureModeBarView : public views::View,
}
CaptureModeCloseButton* close_button() const { return close_button_; }
// Gets the ideal bounds of the bar of widget on the given |root| window.
// Gets the ideal bounds in screen coordinates of the bar of widget on the
// given |root| window.
static gfx::Rect GetBounds(aura::Window* root);
// Called when either the capture mode source or type changes.
......
......@@ -256,10 +256,7 @@ void CaptureModeController::Start() {
if (capture_mode_session_)
return;
// TODO(afakhry): Use root window of the mouse cursor or the one for new
// windows.
capture_mode_session_ =
std::make_unique<CaptureModeSession>(this, Shell::GetPrimaryRootWindow());
capture_mode_session_ = std::make_unique<CaptureModeSession>(this);
}
void CaptureModeController::Stop() {
......
......@@ -17,12 +17,16 @@
#include "ash/style/ash_color_provider.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "ash/wm/window_dimmer.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "cc/paint/paint_flags.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_type.h"
#include "ui/compositor/paint_recorder.h"
#include "ui/display/screen.h"
#include "ui/display/types/display_constants.h"
#include "ui/events/types/event_type.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
......@@ -144,16 +148,21 @@ views::Widget::InitParams CreateWidgetParams(aura::Window* parent,
return params;
}
aura::Window* GetPreferredRootWindow() {
// The Display object returned by CursorManager::GetDisplay may be stale, but
// will have the correct id.
int64_t display_id = Shell::Get()->cursor_manager()->GetDisplay().id();
DCHECK_NE(display::kInvalidDisplayId, display_id);
return Shell::GetRootWindowForDisplayId(display_id);
}
} // namespace
CaptureModeSession::CaptureModeSession(CaptureModeController* controller,
aura::Window* root)
CaptureModeSession::CaptureModeSession(CaptureModeController* controller)
: controller_(controller),
current_root_(root),
current_root_(GetPreferredRootWindow()),
capture_mode_bar_view_(new CaptureModeBarView()),
magnifier_glass_(kMagnifierParams),
old_mouse_warp_status_(SetMouseWarpEnabled(controller_->source() !=
CaptureModeSource::kRegion)) {
magnifier_glass_(kMagnifierParams) {
Shell::Get()->AddPreTargetHandler(this);
SetLayer(std::make_unique<ui::Layer>(ui::LAYER_TEXTURED));
......@@ -163,8 +172,9 @@ CaptureModeSession::CaptureModeSession(CaptureModeController* controller,
parent->layer()->Add(layer());
layer()->SetBounds(parent->bounds());
capture_mode_bar_widget_.Init(CreateWidgetParams(
parent, CaptureModeBarView::GetBounds(root), "CaptureModeBarWidget"));
capture_mode_bar_widget_.Init(
CreateWidgetParams(parent, CaptureModeBarView::GetBounds(current_root_),
"CaptureModeBarWidget"));
capture_mode_bar_widget_.SetContentsView(
base::WrapUnique(capture_mode_bar_view_));
capture_mode_bar_widget_.Show();
......@@ -176,13 +186,21 @@ CaptureModeSession::CaptureModeSession(CaptureModeController* controller,
capture_window_observer_ =
std::make_unique<CaptureWindowObserver>(this, controller_->type());
}
UpdateRootWindowDimmers();
TabletModeController::Get()->AddObserver(this);
current_root_->AddObserver(this);
}
CaptureModeSession::~CaptureModeSession() {
Shell::Get()->RemovePreTargetHandler(this);
current_root_->RemoveObserver(this);
TabletModeController::Get()->RemoveObserver(this);
SetMouseWarpEnabled(old_mouse_warp_status_);
Shell::Get()->RemovePreTargetHandler(this);
// This may happen if we hit esc while dragging.
if (old_mouse_warp_status_)
SetMouseWarpEnabled(*old_mouse_warp_status_);
}
aura::Window* CaptureModeSession::GetSelectedWindow() const {
......@@ -199,7 +217,6 @@ void CaptureModeSession::OnCaptureSourceChanged(CaptureModeSource new_source) {
}
capture_mode_bar_view_->OnCaptureSourceChanged(new_source);
SetMouseWarpEnabled(new_source != CaptureModeSource::kRegion);
UpdateDimensionsLabelWidget(/*is_resizing=*/false);
layer()->SchedulePaint(layer()->bounds());
UpdateCaptureLabelWidget();
......@@ -251,6 +268,31 @@ void CaptureModeSession::OnKeyEvent(ui::KeyEvent* event) {
}
void CaptureModeSession::OnMouseEvent(ui::MouseEvent* event) {
// For fullscreen/window mode, change the root window as soon as we detect the
// cursor on a new display. For region mode, wait until the user clicks to try
// to select a new region on the new display.
const CaptureModeSource source = controller_->source();
const bool can_change_root = source != CaptureModeSource::kRegion ||
(source == CaptureModeSource::kRegion &&
event->type() == ui::ET_MOUSE_PRESSED);
if (can_change_root)
MaybeChangeRoot(GetPreferredRootWindow());
// The root may have switched while pressing the mouse down. Move the capture
// bar to the current display if that is the case and make sure it is stacked
// at the top. The dimensions label and capture button have been moved and
// stacked on mouse press so manually stack at top instead of calling
// RefreshStackingOrder.
if (event->type() == ui::ET_MOUSE_RELEASED &&
source == CaptureModeSource::kRegion &&
current_root_ !=
capture_mode_bar_widget_.GetNativeWindow()->GetRootWindow()) {
capture_mode_bar_widget_.SetBounds(
CaptureModeBarView::GetBounds(current_root_));
auto* parent = GetParentContainer(current_root_);
parent->StackChildAtTop(capture_mode_bar_widget_.GetNativeWindow());
}
OnLocatedEvent(event, /*is_touch=*/false);
}
......@@ -266,6 +308,11 @@ void CaptureModeSession::OnTabletModeEnded() {
UpdateCaptureLabelWidget();
}
void CaptureModeSession::OnWindowDestroying(aura::Window* window) {
DCHECK_EQ(current_root_, window);
MaybeChangeRoot(Shell::GetPrimaryRootWindow());
}
gfx::Rect CaptureModeSession::GetSelectedWindowBounds() const {
auto* window = GetSelectedWindow();
return window ? window->bounds() : gfx::Rect();
......@@ -361,10 +408,14 @@ void CaptureModeSession::OnLocatedEvent(ui::LocatedEvent* event,
return;
gfx::Point location = event->location();
gfx::Point screen_location = event->location();
aura::Window* event_target = static_cast<aura::Window*>(event->target());
aura::Window::ConvertPointToTarget(event_target, current_root_, &location);
wm::ConvertPointToScreen(event_target, &screen_location);
const bool is_event_on_capture_bar =
CaptureModeBarView::GetBounds(current_root_).Contains(location);
capture_mode_bar_widget_.GetWindowBoundsInScreen().Contains(
screen_location);
if (capture_source == CaptureModeSource::kWindow) {
// Do not handle any event located on the capture mode bar.
......@@ -378,8 +429,6 @@ void CaptureModeSession::OnLocatedEvent(ui::LocatedEvent* event,
case ui::ET_MOUSE_MOVED:
case ui::ET_TOUCH_PRESSED:
case ui::ET_TOUCH_MOVED: {
gfx::Point screen_location(event->location());
::wm::ConvertPointToScreen(event_target, &screen_location);
capture_window_observer_->UpdateSelectedWindowAtPosition(
screen_location);
break;
......@@ -395,6 +444,8 @@ void CaptureModeSession::OnLocatedEvent(ui::LocatedEvent* event,
return;
}
DCHECK_EQ(CaptureModeSource::kRegion, capture_source);
// Let the capture button handle any events it can handle first.
if (ShouldCaptureLabelHandleEvent(event_target))
return;
......@@ -409,7 +460,8 @@ void CaptureModeSession::OnLocatedEvent(ui::LocatedEvent* event,
switch (event->type()) {
case ui::ET_MOUSE_PRESSED:
case ui::ET_TOUCH_PRESSED:
OnLocatedEventPressed(location, is_touch);
old_mouse_warp_status_ = SetMouseWarpEnabled(false);
OnLocatedEventPressed(location, is_touch, is_event_on_capture_bar);
break;
case ui::ET_MOUSE_DRAGGED:
case ui::ET_TOUCH_MOVED:
......@@ -417,6 +469,11 @@ void CaptureModeSession::OnLocatedEvent(ui::LocatedEvent* event,
break;
case ui::ET_MOUSE_RELEASED:
case ui::ET_TOUCH_RELEASED:
// Reenable mouse warping.
if (old_mouse_warp_status_)
SetMouseWarpEnabled(*old_mouse_warp_status_);
old_mouse_warp_status_.reset();
OnLocatedEventReleased(location);
break;
default:
......@@ -426,7 +483,8 @@ void CaptureModeSession::OnLocatedEvent(ui::LocatedEvent* event,
void CaptureModeSession::OnLocatedEventPressed(
const gfx::Point& location_in_root,
bool is_touch) {
bool is_touch,
bool is_event_on_capture_bar) {
initial_location_in_root_ = location_in_root;
previous_location_in_root_ = location_in_root;
......@@ -465,11 +523,14 @@ void CaptureModeSession::OnLocatedEventPressed(
// restart to the select phase.
if (controller_->user_capture_region().Contains(location_in_root)) {
fine_tune_position_ = FineTunePosition::kCenter;
} else if (!CaptureModeBarView::GetBounds(current_root_)
.Contains(location_in_root)) {
} else {
gfx::Point location_in_screen = location_in_root;
wm::ConvertPointToScreen(current_root_, &location_in_screen);
if (!is_event_on_capture_bar) {
is_selecting_region_ = true;
UpdateCaptureRegion(gfx::Rect(), /*is_resizing=*/true);
}
}
return;
}
......@@ -584,9 +645,15 @@ void CaptureModeSession::UpdateDimensionsLabelWidget(bool is_resizing) {
dimensions_label_widget_->SetContentsView(std::move(size_label));
dimensions_label_widget_->Show();
// When moving to a new display, the dimensions label gets created/moved
// onto the new display on press, while the capture bar gets moved on
// release. In this case, we do not have to stack the dimensions label.
if (parent == capture_mode_bar_widget_.GetNativeWindow()->parent()) {
parent->StackChildBelow(dimensions_label_widget_->GetNativeWindow(),
capture_mode_bar_widget_.GetNativeWindow());
}
}
views::Label* size_label =
static_cast<views::Label*>(dimensions_label_widget_->GetContentsView());
......@@ -617,6 +684,7 @@ void CaptureModeSession::UpdateDimensionsLabelBounds() {
screen_region.Inset(0, 0, 0, kSizeLabelYDistanceFromRegionDp);
bounds.AdjustToFit(screen_region);
wm::ConvertRectToScreen(current_root_, &bounds);
dimensions_label_widget_->SetBounds(bounds);
}
......@@ -747,6 +815,9 @@ void CaptureModeSession::UpdateCaptureLabelWidgetBounds() {
bounds.ClampToCenteredSize(preferred_size);
}
// User capture region bounds are in root window coordinates so convert them
// here.
wm::ConvertRectToScreen(current_root_, &bounds);
capture_label_widget_->SetBounds(bounds);
}
......@@ -762,4 +833,54 @@ bool CaptureModeSession::ShouldCaptureLabelHandleEvent(
return label_view->ShouldHandleEvent();
}
void CaptureModeSession::MaybeChangeRoot(aura::Window* new_root) {
DCHECK(new_root->IsRootWindow());
if (new_root == current_root_)
return;
current_root_->RemoveObserver(this);
new_root->AddObserver(this);
auto* new_parent = GetParentContainer(new_root);
new_parent->layer()->Add(layer());
layer()->SetBounds(new_parent->bounds());
current_root_ = new_root;
// Update the bounds of the widgets after setting the new root. For region
// capture, the capture bar will move at a later time, when the mouse is
// released.
if (controller_->source() != CaptureModeSource::kRegion) {
capture_mode_bar_widget_.SetBounds(
CaptureModeBarView::GetBounds(current_root_));
}
// The following call to UpdateCaptureRegion will update the capture label
// bounds, moving it onto the correct display, but will early return if the
// region is already empty.
if (controller_->user_capture_region().IsEmpty())
UpdateCaptureLabelWidgetBounds();
// Start with a new region when we switch displays.
is_selecting_region_ = true;
UpdateCaptureRegion(gfx::Rect(), /*is_resizing=*/false);
UpdateRootWindowDimmers();
}
void CaptureModeSession::UpdateRootWindowDimmers() {
root_window_dimmers_.clear();
// Add dimmers for all root windows except |current_root_| if needed.
for (aura::Window* root_window : Shell::GetAllRootWindows()) {
if (root_window == current_root_)
continue;
auto dimmer = std::make_unique<WindowDimmer>(root_window);
dimmer->window()->Show();
root_window_dimmers_.emplace(std::move(dimmer));
}
}
} // namespace ash
......@@ -11,6 +11,9 @@
#include "ash/capture_mode/capture_mode_types.h"
#include "ash/magnifier/magnifier_glass.h"
#include "ash/public/cpp/tablet_mode_observer.h"
#include "base/containers/flat_set.h"
#include "base/optional.h"
#include "ui/aura/window_observer.h"
#include "ui/compositor/layer_delegate.h"
#include "ui/compositor/layer_owner.h"
#include "ui/events/event.h"
......@@ -27,6 +30,7 @@ namespace ash {
class CaptureModeBarView;
class CaptureModeController;
class CaptureWindowObserver;
class WindowDimmer;
// Encapsulates an active capture mode session (i.e. an instance of this class
// lives as long as capture mode is active). It creates and owns the capture
......@@ -38,10 +42,11 @@ class CaptureWindowObserver;
class ASH_EXPORT CaptureModeSession : public ui::LayerOwner,
public ui::LayerDelegate,
public ui::EventHandler,
public TabletModeObserver {
public TabletModeObserver,
public aura::WindowObserver {
public:
// Creates the bar widget on the given |root| window.
CaptureModeSession(CaptureModeController* controller, aura::Window* root);
// Creates the bar widget on a calculated root window.
explicit CaptureModeSession(CaptureModeController* controller);
CaptureModeSession(const CaptureModeSession&) = delete;
CaptureModeSession& operator=(const CaptureModeSession&) = delete;
~CaptureModeSession() override;
......@@ -84,6 +89,9 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner,
void OnTabletModeStarted() override;
void OnTabletModeEnded() override;
// aura::WindowObserver:
void OnWindowDestroying(aura::Window* window) override;
views::Widget* capture_label_widget_for_testing() const {
return capture_label_widget_.get();
}
......@@ -114,7 +122,9 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner,
void OnLocatedEvent(ui::LocatedEvent* event, bool is_touch);
// Handles updating the select region UI.
void OnLocatedEventPressed(const gfx::Point& location_in_root, bool is_touch);
void OnLocatedEventPressed(const gfx::Point& location_in_root,
bool is_touch,
bool is_event_on_capture_bar);
void OnLocatedEventDragged(const gfx::Point& location_in_root);
void OnLocatedEventReleased(const gfx::Point& location_in_root);
......@@ -159,6 +169,15 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner,
// child is visible.
bool ShouldCaptureLabelHandleEvent(aura::Window* event_target);
// Handles changing |root_window_| when the mouse cursor changes to another
// display, or if a display was removed. Moves the capture mode widgets to
// |new_root| depending on the capture mode source an whether it was a display
// removal.
void MaybeChangeRoot(aura::Window* new_root);
// Updates |root_window_dimmers_| to dim the correct root windows.
void UpdateRootWindowDimmers();
CaptureModeController* const controller_;
// The current root window on which the capture session is active, which may
......@@ -202,12 +221,16 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner,
// underway.
std::vector<gfx::Point> anchor_points_;
// Caches the old status of mouse warping before the session started to be
// restored at the end.
bool old_mouse_warp_status_;
// Caches the old status of mouse warping while dragging or resizing a
// captured region.
base::Optional<bool> old_mouse_warp_status_;
// Observer to observe the current selected to-be-captured window.
std::unique_ptr<CaptureWindowObserver> capture_window_observer_;
// Contains the window dimmers which dim all the root windows except
// |current_root_|.
base::flat_set<std::unique_ptr<WindowDimmer>> root_window_dimmers_;
};
} // namespace ash
......
......@@ -24,8 +24,10 @@
#include "ash/system/status_area_widget.h"
#include "ash/test/ash_test_base.h"
#include "ash/wm/window_state.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "ui/events/keycodes/keyboard_codes_posix.h"
#include "ui/events/test/event_generator.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/vector2d.h"
......@@ -59,6 +61,16 @@ void SendKey(ui::KeyboardCode key_code,
event_generator->ReleaseKey(key_code, /*flags=*/0);
}
// Moves the mouse and updates the cursor's display manually to imitate what a
// real mouse move event does in shell.
void MoveMouseToAndUpdateCursorDisplay(
const gfx::Point& point,
ui::test::EventGenerator* event_generator) {
Shell::Get()->cursor_manager()->SetDisplay(
display::Screen::GetScreen()->GetDisplayNearestPoint(point));
event_generator->MoveMouseTo(point);
}
} // namespace
class CaptureModeTest : public AshTestBase {
......@@ -148,16 +160,22 @@ class CaptureModeTest : public AshTestBase {
return base::nullopt;
}
// Start Capture Mode with source region and type image.
CaptureModeController* StartImageRegionCapture() {
CaptureModeController* StartCaptureSession(CaptureModeSource source,
CaptureModeType type) {
auto* controller = CaptureModeController::Get();
controller->SetSource(CaptureModeSource::kRegion);
controller->SetType(CaptureModeType::kImage);
controller->SetSource(source);
controller->SetType(type);
controller->Start();
DCHECK(controller->IsActive());
return controller;
}
// Start Capture Mode with source region and type image.
CaptureModeController* StartImageRegionCapture() {
return StartCaptureSession(CaptureModeSource::kRegion,
CaptureModeType::kImage);
}
// Select a region by pressing and dragging the mouse.
void SelectRegion(const gfx::Rect& region, bool release_mouse = true) {
auto* controller = CaptureModeController::Get();
......@@ -698,4 +716,120 @@ TEST_F(CaptureModeTest, WindowCapture) {
controller->Stop();
}
// Tests that the capture bar is located on the root with the cursor when
// starting capture mode.
TEST_F(CaptureModeTest, MultiDisplayCaptureBarInitialLocation) {
UpdateDisplay("800x800,801+0-800x800");
auto* event_generator = GetEventGenerator();
MoveMouseToAndUpdateCursorDisplay(gfx::Point(1000, 500), event_generator);
auto* controller = StartImageRegionCapture();
EXPECT_TRUE(gfx::Rect(801, 0, 800, 800)
.Contains(controller->capture_mode_session()
->capture_mode_bar_view()
->GetBoundsInScreen()));
controller->Stop();
MoveMouseToAndUpdateCursorDisplay(gfx::Point(100, 500), event_generator);
StartImageRegionCapture();
EXPECT_TRUE(gfx::Rect(800, 800).Contains(controller->capture_mode_session()
->capture_mode_bar_view()
->GetBoundsInScreen()));
}
// Tests behavior of a capture mode session if the active display is removed.
TEST_F(CaptureModeTest, DisplayRemoval) {
UpdateDisplay("800x800,801+0-800x800");
// Start capture mode on the secondary display.
MoveMouseToAndUpdateCursorDisplay(gfx::Point(1000, 500), GetEventGenerator());
auto* controller = StartImageRegionCapture();
auto* session = controller->capture_mode_session();
EXPECT_TRUE(
gfx::Rect(801, 0, 800, 800)
.Contains(session->capture_mode_bar_view()->GetBoundsInScreen()));
ASSERT_EQ(Shell::GetAllRootWindows()[1], session->current_root());
// Remove secondary display.
const int64_t primary_id = WindowTreeHostManager::GetPrimaryDisplayId();
display::ManagedDisplayInfo primary_info =
display_manager()->GetDisplayInfo(primary_id);
std::vector<display::ManagedDisplayInfo> display_info_list;
display_info_list.push_back(primary_info);
display_manager()->OnNativeDisplaysChanged(display_info_list);
// Spin the run loop so that we get a signal that the associated root window
// of the removed display is destroyed.
base::RunLoop().RunUntilIdle();
// Tests that the capture mode bar is now on the primary display.
EXPECT_TRUE(gfx::Rect(800, 800).Contains(
session->capture_mode_bar_view()->GetBoundsInScreen()));
ASSERT_EQ(Shell::GetAllRootWindows()[0], session->current_root());
}
// Tests that using fullscreen or window source, moving the mouse across
// displays will change the root window of the capture session.
TEST_F(CaptureModeTest, MultiDisplayFullscreenOrWindowSourceRootWindow) {
UpdateDisplay("800x800,801+0-800x800");
ASSERT_EQ(2u, Shell::GetAllRootWindows().size());
auto* event_generator = GetEventGenerator();
MoveMouseToAndUpdateCursorDisplay(gfx::Point(100, 500), event_generator);
for (auto source :
{CaptureModeSource::kFullscreen, CaptureModeSource::kWindow}) {
SCOPED_TRACE(source == CaptureModeSource::kFullscreen ? "Fullscreen source"
: "Window source");
auto* controller = StartCaptureSession(CaptureModeSource::kFullscreen,
CaptureModeType::kImage);
auto* session = controller->capture_mode_session();
EXPECT_EQ(Shell::GetAllRootWindows()[0], session->current_root());
MoveMouseToAndUpdateCursorDisplay(gfx::Point(1000, 500), event_generator);
EXPECT_EQ(Shell::GetAllRootWindows()[1], session->current_root());
MoveMouseToAndUpdateCursorDisplay(gfx::Point(100, 500), event_generator);
EXPECT_EQ(Shell::GetAllRootWindows()[0], session->current_root());
controller->Stop();
}
}
// Tests that in region mode, moving the mouse across displays will not change
// the root window of the capture session, but clicking on a new display will.
TEST_F(CaptureModeTest, MultiDisplayRegionSourceRootWindow) {
UpdateDisplay("800x800,801+0-800x800");
ASSERT_EQ(2u, Shell::GetAllRootWindows().size());
auto* event_generator = GetEventGenerator();
MoveMouseToAndUpdateCursorDisplay(gfx::Point(100, 500), event_generator);
auto* controller = StartImageRegionCapture();
auto* session = controller->capture_mode_session();
EXPECT_EQ(Shell::GetAllRootWindows()[0], session->current_root());
// Tests that moving the mouse to the secondary display does not change the
// root.
MoveMouseToAndUpdateCursorDisplay(gfx::Point(1000, 500), event_generator);
EXPECT_EQ(Shell::GetAllRootWindows()[0], session->current_root());
// Tests that pressing the mouse changes the root. The capture bar stays on
// the primary display until the mouse is released.
event_generator->PressLeftButton();
EXPECT_EQ(Shell::GetAllRootWindows()[1], session->current_root());
EXPECT_TRUE(gfx::Rect(800, 800).Contains(controller->capture_mode_session()
->capture_mode_bar_view()
->GetBoundsInScreen()));
event_generator->ReleaseLeftButton();
EXPECT_EQ(Shell::GetAllRootWindows()[1], session->current_root());
EXPECT_TRUE(gfx::Rect(801, 0, 800, 800)
.Contains(controller->capture_mode_session()
->capture_mode_bar_view()
->GetBoundsInScreen()));
}
} // namespace ash
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