Commit 5a1a9aae authored by estade's avatar estade Committed by Commit bot

Retry c7e292ea - Redirect all mouse input to Alt+Tab window

Redirect all mouse input to Alt+Tab window when it's visible,
effectively disabling the mouse. Capture is reset when the widget is
destroyed.

original review: https://codereview.chromium.org/2284763002/

BUG=641171

Review-Url: https://codereview.chromium.org/2296763002
Cr-Commit-Position: refs/heads/master@{#415761}
parent 516883ac
......@@ -390,6 +390,10 @@ class WindowCycleView : public views::WidgetDelegateView {
}
}
void OnMouseCaptureLost() override {
WmShell::Get()->window_cycle_controller()->StopCycling();
}
View* GetContentsView() override { return this; }
View* GetInitiallyFocusedView() override {
......@@ -464,6 +468,7 @@ WindowCycleList::WindowCycleList(const WindowList& windows)
current_index_(0),
initial_direction_(WindowCycleController::FORWARD),
cycle_view_(nullptr),
cycle_ui_widget_(nullptr),
screen_observer_(this) {
if (!ShouldShowUi())
WmShell::Get()->mru_window_tracker()->SetIgnoreActivations(true);
......@@ -495,6 +500,9 @@ WindowCycleList::~WindowCycleList() {
target_window->Show();
target_window->GetWindowState()->Activate();
}
if (cycle_ui_widget_)
cycle_ui_widget_->Close();
}
void WindowCycleList::Step(WindowCycleController::Direction direction) {
......@@ -598,7 +606,6 @@ void WindowCycleList::InitWindowCycleView() {
views::Widget::InitParams params;
params.delegate = cycle_view_;
params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.accept_events = true;
params.name = "WindowCycleList (Alt+Tab)";
......@@ -616,7 +623,9 @@ void WindowCycleList::InitWindowCycleView() {
widget_rect.set_height(widget_height);
widget->SetBounds(widget_rect);
widget->Show();
cycle_ui_widget_.reset(widget);
widget->SetCapture(cycle_view_);
widget->set_auto_release_capture(false);
cycle_ui_widget_ = widget;
}
} // namespace ash
......@@ -95,7 +95,7 @@ class ASH_EXPORT WindowCycleList : public WmWindowObserver,
WindowCycleView* cycle_view_;
// The widget that hosts the window cycle UI.
std::unique_ptr<views::Widget> cycle_ui_widget_;
views::Widget* cycle_ui_widget_;
// The window list will dismiss if the display metrics change.
ScopedObserver<display::Screen, display::DisplayObserver> screen_observer_;
......
......@@ -39,24 +39,32 @@ namespace ash {
namespace {
class KeyEventCounter : public ui::EventHandler {
class EventCounter : public ui::EventHandler {
public:
KeyEventCounter() : key_events_(0) {}
~KeyEventCounter() override {}
EventCounter() : key_events_(0), mouse_events_(0) {}
~EventCounter() override {}
size_t GetCountAndReset() {
size_t count = key_events_;
int GetKeyEventCountAndReset() {
int count = key_events_;
key_events_ = 0;
return count;
}
int GetMouseEventCountAndReset() {
int count = mouse_events_;
mouse_events_ = 0;
return count;
}
// ui::EventHandler:
void OnKeyEvent(ui::KeyEvent* event) override { key_events_++; }
void OnMouseEvent(ui::MouseEvent* event) override { mouse_events_++; }
private:
size_t key_events_;
int key_events_;
int mouse_events_;
DISALLOW_COPY_AND_ASSIGN(KeyEventCounter);
DISALLOW_COPY_AND_ASSIGN(EventCounter);
};
bool IsWindowMinimized(aura::Window* window) {
......@@ -557,20 +565,71 @@ TEST_F(WindowCycleControllerTest, CycleMruPanelDestroyed) {
TEST_F(WindowCycleControllerTest, TabKeyNotLeaked) {
std::unique_ptr<Window> w0(CreateTestWindowInShellWithId(0));
std::unique_ptr<Window> w1(CreateTestWindowInShellWithId(1));
KeyEventCounter key_count;
w0->AddPreTargetHandler(&key_count);
w1->AddPreTargetHandler(&key_count);
EventCounter event_count;
w0->AddPreTargetHandler(&event_count);
w1->AddPreTargetHandler(&event_count);
ui::test::EventGenerator& generator = GetEventGenerator();
wm::GetWindowState(w0.get())->Activate();
generator.PressKey(ui::VKEY_MENU, ui::EF_NONE);
EXPECT_EQ(1u, key_count.GetCountAndReset());
EXPECT_EQ(1, event_count.GetKeyEventCountAndReset());
generator.PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
EXPECT_EQ(0u, key_count.GetCountAndReset());
EXPECT_EQ(0, event_count.GetKeyEventCountAndReset());
generator.ReleaseKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
EXPECT_EQ(0u, key_count.GetCountAndReset());
EXPECT_EQ(0, event_count.GetKeyEventCountAndReset());
generator.ReleaseKey(ui::VKEY_MENU, ui::EF_NONE);
EXPECT_TRUE(wm::GetWindowState(w1.get())->IsActive());
EXPECT_EQ(0u, key_count.GetCountAndReset());
EXPECT_EQ(0, event_count.GetKeyEventCountAndReset());
}
// While the UI is active, mouse events are captured.
TEST_F(WindowCycleControllerTest, MouseEventsCaptured) {
// This delegate allows the window to receive mouse events.
aura::test::TestWindowDelegate delegate;
std::unique_ptr<Window> w0(CreateTestWindowInShellWithDelegate(
&delegate, 0, gfx::Rect(0, 0, 100, 100)));
std::unique_ptr<Window> w1(CreateTestWindowInShellWithId(1));
EventCounter event_count;
w0->AddPreTargetHandler(&event_count);
w1->SetTargetHandler(&event_count);
ui::test::EventGenerator& generator = GetEventGenerator();
wm::ActivateWindow(w0.get());
// Events get through.
generator.MoveMouseToCenterOf(w0.get());
generator.ClickLeftButton();
EXPECT_LT(0, event_count.GetMouseEventCountAndReset());
// Start cycling.
WindowCycleController* controller = WmShell::Get()->window_cycle_controller();
controller->HandleCycleWindow(WindowCycleController::FORWARD);
// Events don't get through.
generator.ClickLeftButton();
EXPECT_EQ(0, event_count.GetMouseEventCountAndReset());
// Stop cycling: once again, events get through.
controller->StopCycling();
generator.ClickLeftButton();
EXPECT_LT(0, event_count.GetMouseEventCountAndReset());
}
// If mouse capture is lost, the UI closes.
TEST_F(WindowCycleControllerTest, MouseCaptureLost) {
// This delegate allows the window to receive mouse events.
aura::test::TestWindowDelegate delegate;
std::unique_ptr<Window> w0(CreateTestWindowInShellWithDelegate(
&delegate, 0, gfx::Rect(0, 0, 100, 100)));
std::unique_ptr<Window> w1(CreateTestWindowInShellWithId(1));
// Start cycling.
WindowCycleController* controller = WmShell::Get()->window_cycle_controller();
controller->HandleCycleWindow(WindowCycleController::FORWARD);
// Some other widget grabs capture and this causes Alt+Tab to cease.
std::unique_ptr<views::Widget> widget = CreateTestWidget(
nullptr, kShellWindowId_DefaultContainer, gfx::Rect(1, 2, 3, 4));
widget->SetCapture(nullptr);
EXPECT_FALSE(controller->IsCycling());
}
// Tests that we can cycle past fullscreen windows: https://crbug.com/622396.
......@@ -603,11 +662,11 @@ TEST_F(WindowCycleControllerTest, TabPastFullscreenWindow) {
// pass on the alt+tab to continue cycling). To make this test work with or
// without the new alt+tab selector we check for the event on either
// fullscreen window.
KeyEventCounter key_count;
w0->AddPreTargetHandler(&key_count);
w1->AddPreTargetHandler(&key_count);
EventCounter event_count;
w0->AddPreTargetHandler(&event_count);
w1->AddPreTargetHandler(&event_count);
generator.PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
EXPECT_EQ(1u, key_count.GetCountAndReset());
EXPECT_EQ(1, event_count.GetKeyEventCountAndReset());
}
} // 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