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 { ...@@ -390,6 +390,10 @@ class WindowCycleView : public views::WidgetDelegateView {
} }
} }
void OnMouseCaptureLost() override {
WmShell::Get()->window_cycle_controller()->StopCycling();
}
View* GetContentsView() override { return this; } View* GetContentsView() override { return this; }
View* GetInitiallyFocusedView() override { View* GetInitiallyFocusedView() override {
...@@ -464,6 +468,7 @@ WindowCycleList::WindowCycleList(const WindowList& windows) ...@@ -464,6 +468,7 @@ WindowCycleList::WindowCycleList(const WindowList& windows)
current_index_(0), current_index_(0),
initial_direction_(WindowCycleController::FORWARD), initial_direction_(WindowCycleController::FORWARD),
cycle_view_(nullptr), cycle_view_(nullptr),
cycle_ui_widget_(nullptr),
screen_observer_(this) { screen_observer_(this) {
if (!ShouldShowUi()) if (!ShouldShowUi())
WmShell::Get()->mru_window_tracker()->SetIgnoreActivations(true); WmShell::Get()->mru_window_tracker()->SetIgnoreActivations(true);
...@@ -495,6 +500,9 @@ WindowCycleList::~WindowCycleList() { ...@@ -495,6 +500,9 @@ WindowCycleList::~WindowCycleList() {
target_window->Show(); target_window->Show();
target_window->GetWindowState()->Activate(); target_window->GetWindowState()->Activate();
} }
if (cycle_ui_widget_)
cycle_ui_widget_->Close();
} }
void WindowCycleList::Step(WindowCycleController::Direction direction) { void WindowCycleList::Step(WindowCycleController::Direction direction) {
...@@ -598,7 +606,6 @@ void WindowCycleList::InitWindowCycleView() { ...@@ -598,7 +606,6 @@ void WindowCycleList::InitWindowCycleView() {
views::Widget::InitParams params; views::Widget::InitParams params;
params.delegate = cycle_view_; params.delegate = cycle_view_;
params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS; 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.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.accept_events = true; params.accept_events = true;
params.name = "WindowCycleList (Alt+Tab)"; params.name = "WindowCycleList (Alt+Tab)";
...@@ -616,7 +623,9 @@ void WindowCycleList::InitWindowCycleView() { ...@@ -616,7 +623,9 @@ void WindowCycleList::InitWindowCycleView() {
widget_rect.set_height(widget_height); widget_rect.set_height(widget_height);
widget->SetBounds(widget_rect); widget->SetBounds(widget_rect);
widget->Show(); widget->Show();
cycle_ui_widget_.reset(widget); widget->SetCapture(cycle_view_);
widget->set_auto_release_capture(false);
cycle_ui_widget_ = widget;
} }
} // namespace ash } // namespace ash
...@@ -95,7 +95,7 @@ class ASH_EXPORT WindowCycleList : public WmWindowObserver, ...@@ -95,7 +95,7 @@ class ASH_EXPORT WindowCycleList : public WmWindowObserver,
WindowCycleView* cycle_view_; WindowCycleView* cycle_view_;
// The widget that hosts the window cycle UI. // 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. // The window list will dismiss if the display metrics change.
ScopedObserver<display::Screen, display::DisplayObserver> screen_observer_; ScopedObserver<display::Screen, display::DisplayObserver> screen_observer_;
......
...@@ -39,24 +39,32 @@ namespace ash { ...@@ -39,24 +39,32 @@ namespace ash {
namespace { namespace {
class KeyEventCounter : public ui::EventHandler { class EventCounter : public ui::EventHandler {
public: public:
KeyEventCounter() : key_events_(0) {} EventCounter() : key_events_(0), mouse_events_(0) {}
~KeyEventCounter() override {} ~EventCounter() override {}
size_t GetCountAndReset() { int GetKeyEventCountAndReset() {
size_t count = key_events_; int count = key_events_;
key_events_ = 0; key_events_ = 0;
return count; return count;
} }
int GetMouseEventCountAndReset() {
int count = mouse_events_;
mouse_events_ = 0;
return count;
}
// ui::EventHandler: // ui::EventHandler:
void OnKeyEvent(ui::KeyEvent* event) override { key_events_++; } void OnKeyEvent(ui::KeyEvent* event) override { key_events_++; }
void OnMouseEvent(ui::MouseEvent* event) override { mouse_events_++; }
private: 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) { bool IsWindowMinimized(aura::Window* window) {
...@@ -557,20 +565,71 @@ TEST_F(WindowCycleControllerTest, CycleMruPanelDestroyed) { ...@@ -557,20 +565,71 @@ TEST_F(WindowCycleControllerTest, CycleMruPanelDestroyed) {
TEST_F(WindowCycleControllerTest, TabKeyNotLeaked) { TEST_F(WindowCycleControllerTest, TabKeyNotLeaked) {
std::unique_ptr<Window> w0(CreateTestWindowInShellWithId(0)); std::unique_ptr<Window> w0(CreateTestWindowInShellWithId(0));
std::unique_ptr<Window> w1(CreateTestWindowInShellWithId(1)); std::unique_ptr<Window> w1(CreateTestWindowInShellWithId(1));
KeyEventCounter key_count; EventCounter event_count;
w0->AddPreTargetHandler(&key_count); w0->AddPreTargetHandler(&event_count);
w1->AddPreTargetHandler(&key_count); w1->AddPreTargetHandler(&event_count);
ui::test::EventGenerator& generator = GetEventGenerator(); ui::test::EventGenerator& generator = GetEventGenerator();
wm::GetWindowState(w0.get())->Activate(); wm::GetWindowState(w0.get())->Activate();
generator.PressKey(ui::VKEY_MENU, ui::EF_NONE); 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); 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); 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); generator.ReleaseKey(ui::VKEY_MENU, ui::EF_NONE);
EXPECT_TRUE(wm::GetWindowState(w1.get())->IsActive()); 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. // Tests that we can cycle past fullscreen windows: https://crbug.com/622396.
...@@ -603,11 +662,11 @@ TEST_F(WindowCycleControllerTest, TabPastFullscreenWindow) { ...@@ -603,11 +662,11 @@ TEST_F(WindowCycleControllerTest, TabPastFullscreenWindow) {
// pass on the alt+tab to continue cycling). To make this test work with or // 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 // without the new alt+tab selector we check for the event on either
// fullscreen window. // fullscreen window.
KeyEventCounter key_count; EventCounter event_count;
w0->AddPreTargetHandler(&key_count); w0->AddPreTargetHandler(&event_count);
w1->AddPreTargetHandler(&key_count); w1->AddPreTargetHandler(&event_count);
generator.PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN); generator.PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
EXPECT_EQ(1u, key_count.GetCountAndReset()); EXPECT_EQ(1, event_count.GetKeyEventCountAndReset());
} }
} // namespace ash } // 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