diff options
author | tdanderson <tdanderson@chromium.org> | 2015-05-14 13:08:58 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-14 20:09:16 +0000 |
commit | ec8ba66f8e43042b4115ef911955db19db62191f (patch) | |
tree | d21c55240e9effb696d61a069d5bb715d986f107 | |
parent | 326d757e1864bedb122f811e70add8d507d1952c (diff) | |
download | chromium_src-ec8ba66f8e43042b4115ef911955db19db62191f.zip chromium_src-ec8ba66f8e43042b4115ef911955db19db62191f.tar.gz chromium_src-ec8ba66f8e43042b4115ef911955db19db62191f.tar.bz2 |
Add user action for changing the active window in Ash overview mode
Introduce the user action
WindowSelector_ActiveWindowChanged to track
the number of overview mode sessions in which
the user selected a window that is different
from the previously-active window.
BUG=486900
TEST=WindowSelectorTest.ActiveWindowChangedUserAction*
Review URL: https://codereview.chromium.org/1138253002
Cr-Commit-Position: refs/heads/master@{#329915}
-rw-r--r-- | ash/metrics/user_metrics_recorder.cc | 4 | ||||
-rw-r--r-- | ash/metrics/user_metrics_recorder.h | 4 | ||||
-rw-r--r-- | ash/wm/overview/window_grid.cc | 2 | ||||
-rw-r--r-- | ash/wm/overview/window_selector.cc | 19 | ||||
-rw-r--r-- | ash/wm/overview/window_selector.h | 3 | ||||
-rw-r--r-- | ash/wm/overview/window_selector_item.cc | 9 | ||||
-rw-r--r-- | ash/wm/overview/window_selector_item.h | 8 | ||||
-rw-r--r-- | ash/wm/overview/window_selector_unittest.cc | 109 | ||||
-rw-r--r-- | tools/metrics/actions/actions.xml | 9 |
9 files changed, 160 insertions, 7 deletions
diff --git a/ash/metrics/user_metrics_recorder.cc b/ash/metrics/user_metrics_recorder.cc index f26b450..e992940 100644 --- a/ash/metrics/user_metrics_recorder.cc +++ b/ash/metrics/user_metrics_recorder.cc @@ -581,6 +581,10 @@ void UserMetricsRecorder::RecordUserMetricsAction(UserMetricsAction action) { base::RecordAction( base::UserMetricsAction("WindowSelector_Overview")); break; + case ash::UMA_WINDOW_OVERVIEW_ACTIVE_WINDOW_CHANGED: + base::RecordAction( + base::UserMetricsAction("WindowSelector_ActiveWindowChanged")); + break; case ash::UMA_WINDOW_OVERVIEW_ENTER_KEY: base::RecordAction( base::UserMetricsAction("WindowSelector_OverviewEnterKey")); diff --git a/ash/metrics/user_metrics_recorder.h b/ash/metrics/user_metrics_recorder.h index 28dbd26..956bb40 100644 --- a/ash/metrics/user_metrics_recorder.h +++ b/ash/metrics/user_metrics_recorder.h @@ -121,6 +121,10 @@ enum UserMetricsAction { // Thumbnail sized overview of windows triggered by pressing the overview key. UMA_WINDOW_OVERVIEW, + // User selected a window in overview mode different from the + // previously-active window. + UMA_WINDOW_OVERVIEW_ACTIVE_WINDOW_CHANGED, + // Selecting a window in overview mode by pressing the enter key. UMA_WINDOW_OVERVIEW_ENTER_KEY, diff --git a/ash/wm/overview/window_grid.cc b/ash/wm/overview/window_grid.cc index 47087c3..64d063f 100644 --- a/ash/wm/overview/window_grid.cc +++ b/ash/wm/overview/window_grid.cc @@ -137,7 +137,7 @@ WindowGrid::WindowGrid(aura::Window* root_window, (*iter)->AddObserver(this); observed_windows_.insert(*iter); - window_list_.push_back(new WindowSelectorItem(*iter)); + window_list_.push_back(new WindowSelectorItem(*iter, window_selector_)); } } diff --git a/ash/wm/overview/window_selector.cc b/ash/wm/overview/window_selector.cc index 43771ea..3e033cc 100644 --- a/ash/wm/overview/window_selector.cc +++ b/ash/wm/overview/window_selector.cc @@ -16,6 +16,7 @@ #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/switchable_windows.h" +#include "ash/wm/mru_window_tracker.h" #include "ash/wm/overview/window_grid.h" #include "ash/wm/overview/window_selector_delegate.h" #include "ash/wm/overview/window_selector_item.h" @@ -393,6 +394,20 @@ void WindowSelector::OnGridEmpty(WindowGrid* grid) { CancelSelection(); } +void WindowSelector::SelectWindow(aura::Window* window) { + // Record UMA_WINDOW_OVERVIEW_ACTIVE_WINDOW_CHANGED if the user is selecting + // a window other than the window that was active prior to entering overview + // mode (i.e., the window at the front of the MRU list). + MruWindowTracker::WindowList window_list = + Shell::GetInstance()->mru_window_tracker()->BuildMruWindowList(); + if (window_list.size() > 0 && window_list[0] != window) { + Shell::GetInstance()->metrics()->RecordUserMetricsAction( + UMA_WINDOW_OVERVIEW_ACTIVE_WINDOW_CHANGED); + } + + wm::GetWindowState(window)->Activate(); +} + bool WindowSelector::HandleKeyEvent(views::Textfield* sender, const ui::KeyEvent& key_event) { if (key_event.type() != ui::ET_KEY_PRESSED) @@ -430,8 +445,8 @@ bool WindowSelector::HandleKeyEvent(views::Textfield* sender, (num_key_presses_ * 100) / num_items_, 1, 300, 30); Shell::GetInstance()->metrics()->RecordUserMetricsAction( UMA_WINDOW_OVERVIEW_ENTER_KEY); - wm::GetWindowState(grid_list_[selected_grid_index_]-> - SelectedWindow()->GetWindow())->Activate(); + SelectWindow( + grid_list_[selected_grid_index_]->SelectedWindow()->GetWindow()); break; default: // Not a key we are interested in, allow the textfield to handle it. diff --git a/ash/wm/overview/window_selector.h b/ash/wm/overview/window_selector.h index 254d9dc..7c783b8 100644 --- a/ash/wm/overview/window_selector.h +++ b/ash/wm/overview/window_selector.h @@ -84,6 +84,9 @@ class ASH_EXPORT WindowSelector // Called when the last window selector item from a grid is deleted. void OnGridEmpty(WindowGrid* grid); + // Activates |window|. + void SelectWindow(aura::Window* window); + bool restoring_minimized_windows() const { return restoring_minimized_windows_; } diff --git a/ash/wm/overview/window_selector_item.cc b/ash/wm/overview/window_selector_item.cc index f3e8eca..02a9bb2 100644 --- a/ash/wm/overview/window_selector_item.cc +++ b/ash/wm/overview/window_selector_item.cc @@ -13,6 +13,7 @@ #include "ash/wm/overview/overview_animation_type.h" #include "ash/wm/overview/scoped_overview_animation_settings.h" #include "ash/wm/overview/scoped_transform_overview_window.h" +#include "ash/wm/overview/window_selector.h" #include "ash/wm/overview/window_selector_controller.h" #include "ash/wm/window_state.h" #include "base/auto_reset.h" @@ -126,13 +127,15 @@ gfx::Rect WindowSelectorItem::OverviewLabelButton::GetChildAreaBounds() { return bounds; } -WindowSelectorItem::WindowSelectorItem(aura::Window* window) +WindowSelectorItem::WindowSelectorItem(aura::Window* window, + WindowSelector* window_selector) : dimmed_(false), root_window_(window->GetRootWindow()), transform_window_(window), in_bounds_update_(false), window_label_button_view_(nullptr), - close_button_(new OverviewCloseButton(this)) { + close_button_(new OverviewCloseButton(this)), + window_selector_(window_selector) { CreateWindowLabel(window->title()); views::Widget::InitParams params; params.type = views::Widget::InitParams::TYPE_POPUP; @@ -225,7 +228,7 @@ void WindowSelectorItem::ButtonPressed(views::Button* sender, return; } CHECK(sender == window_label_button_view_); - wm::GetWindowState(transform_window_.window())->Activate(); + window_selector_->SelectWindow(transform_window_.window()); } void WindowSelectorItem::OnWindowDestroying(aura::Window* window) { diff --git a/ash/wm/overview/window_selector_item.h b/ash/wm/overview/window_selector_item.h index 063b141..40063a3 100644 --- a/ash/wm/overview/window_selector_item.h +++ b/ash/wm/overview/window_selector_item.h @@ -27,6 +27,8 @@ class Widget; namespace ash { +class WindowSelector; + // This class represents an item in overview mode. class ASH_EXPORT WindowSelectorItem : public views::ButtonListener, public aura::WindowObserver { @@ -51,7 +53,7 @@ class ASH_EXPORT WindowSelectorItem : public views::ButtonListener, DISALLOW_COPY_AND_ASSIGN(OverviewLabelButton); }; - explicit WindowSelectorItem(aura::Window* window); + WindowSelectorItem(aura::Window* window, WindowSelector* window_selector); ~WindowSelectorItem() override; aura::Window* GetWindow(); @@ -158,6 +160,10 @@ class ASH_EXPORT WindowSelectorItem : public views::ButtonListener, // close_button_widget_. views::ImageButton* close_button_; + // Pointer to the WindowSelector that owns the WindowGrid containing |this|. + // Guaranteed to be non-null for the lifetime of |this|. + WindowSelector* window_selector_; + DISALLOW_COPY_AND_ASSIGN(WindowSelectorItem); }; diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc index 3ae60cc..9612104 100644 --- a/ash/wm/overview/window_selector_unittest.cc +++ b/ash/wm/overview/window_selector_unittest.cc @@ -35,6 +35,7 @@ #include "base/run_loop.h" #include "base/strings/string_piece.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/user_action_tester.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/client/cursor_client.h" #include "ui/aura/client/focus_client.h" @@ -58,6 +59,9 @@ namespace ash { namespace { +const char kActiveWindowChangedFromOverview[] = + "WindowSelector_ActiveWindowChanged"; + class NonActivatableActivationDelegate : public aura::client::ActivationDelegate { public: @@ -374,6 +378,111 @@ TEST_F(WindowSelectorTest, BasicGesture) { EXPECT_EQ(window2.get(), GetFocusedWindow()); } +// Tests that the user action WindowSelector_ActiveWindowChanged is +// recorded when the mouse/touchscreen/keyboard are used to select a window +// in overview mode which is different from the previously-active window. +TEST_F(WindowSelectorTest, ActiveWindowChangedUserActionRecorded) { + base::UserActionTester user_action_tester; + gfx::Rect bounds(0, 0, 400, 400); + scoped_ptr<aura::Window> window1(CreateWindow(bounds)); + scoped_ptr<aura::Window> window2(CreateWindow(bounds)); + + // Tap on |window2| to activate it and exit overview. + wm::ActivateWindow(window1.get()); + ToggleOverview(); + ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), + window2.get()); + generator.GestureTapAt( + gfx::ToEnclosingRect(GetTransformedTargetBounds(window2.get())) + .CenterPoint()); + EXPECT_EQ( + 1, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview)); + + // Click on |window2| to activate it and exit overview. + wm::ActivateWindow(window1.get()); + ToggleOverview(); + ClickWindow(window2.get()); + EXPECT_EQ( + 2, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview)); + + // Select |window2| using the arrow keys. Activate it (and exit overview) by + // pressing the return key. + wm::ActivateWindow(window1.get()); + ToggleOverview(); + SendKey(ui::VKEY_RIGHT); + SendKey(ui::VKEY_RIGHT); + SendKey(ui::VKEY_RETURN); + EXPECT_EQ( + 3, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview)); +} + +// Tests that the user action WindowSelector_ActiveWindowChanged is not +// recorded when the mouse/touchscreen/keyboard are used to select the +// already-active window from overview mode. Also verifies that entering and +// exiting overview without selecting a window does not record the action. +TEST_F(WindowSelectorTest, ActiveWindowChangedUserActionNotRecorded) { + base::UserActionTester user_action_tester; + gfx::Rect bounds(0, 0, 400, 400); + scoped_ptr<aura::Window> window1(CreateWindow(bounds)); + scoped_ptr<aura::Window> window2(CreateWindow(bounds)); + + // Set |window1| to be initially active. + wm::ActivateWindow(window1.get()); + ToggleOverview(); + + // Tap on |window1| to exit overview. + ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), + window1.get()); + generator.GestureTapAt( + gfx::ToEnclosingRect(GetTransformedTargetBounds(window1.get())) + .CenterPoint()); + EXPECT_EQ( + 0, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview)); + + // |window1| remains active. Click on it to exit overview. + ASSERT_EQ(window1.get(), GetFocusedWindow()); + ToggleOverview(); + ClickWindow(window1.get()); + EXPECT_EQ( + 0, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview)); + + // |window1| remains active. Select using the keyboard. + ASSERT_EQ(window1.get(), GetFocusedWindow()); + ToggleOverview(); + SendKey(ui::VKEY_RIGHT); + SendKey(ui::VKEY_RETURN); + EXPECT_EQ( + 0, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview)); + + // Entering and exiting overview without user input should not record + // the action. + ToggleOverview(); + ToggleOverview(); + EXPECT_EQ( + 0, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview)); +} + +// Tests that the user action WindowSelector_ActiveWindowChanged is not +// recorded when overview mode exits as a result of closing its only window. +TEST_F(WindowSelectorTest, ActiveWindowChangedUserActionWindowClose) { + base::UserActionTester user_action_tester; + scoped_ptr<views::Widget> widget = + CreateWindowWidget(gfx::Rect(0, 0, 400, 400)); + + ToggleOverview(); + + aura::Window* window = widget->GetNativeWindow(); + gfx::RectF bounds = GetTransformedBoundsInRootWindow(window); + gfx::Point point(bounds.top_right().x() - 1, bounds.top_right().y() - 1); + ui::test::EventGenerator event_generator(window->GetRootWindow(), point); + + ASSERT_FALSE(widget->IsClosed()); + event_generator.ClickLeftButton(); + ASSERT_TRUE(widget->IsClosed()); + EXPECT_EQ( + 0, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview)); +} + // Tests that we do not crash and overview mode remains engaged if the desktop // is tapped while a finger is already down over a window. TEST_F(WindowSelectorTest, NoCrashWithDesktopTap) { diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index a66fd71..ebec682 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml @@ -12205,6 +12205,15 @@ should be able to be added at any place in this file. <description>Please enter the description of this user action.</description> </action> +<action name="WindowSelector_ActiveWindowChanged"> + <owner>tdanderson@chromium.org</owner> + <owner>bruthig@chromium.org</owner> + <description> + Recorded when the user selects a window from Ash overview mode which is + different from the window that was active prior to entering overview mode. + </description> +</action> + <action name="WindowSelector_Overview"> <owner>tdanderson@chromium.org</owner> <owner>flackr@chromium.org</owner> |