summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortdanderson <tdanderson@chromium.org>2015-05-14 13:08:58 -0700
committerCommit bot <commit-bot@chromium.org>2015-05-14 20:09:16 +0000
commitec8ba66f8e43042b4115ef911955db19db62191f (patch)
treed21c55240e9effb696d61a069d5bb715d986f107
parent326d757e1864bedb122f811e70add8d507d1952c (diff)
downloadchromium_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.cc4
-rw-r--r--ash/metrics/user_metrics_recorder.h4
-rw-r--r--ash/wm/overview/window_grid.cc2
-rw-r--r--ash/wm/overview/window_selector.cc19
-rw-r--r--ash/wm/overview/window_selector.h3
-rw-r--r--ash/wm/overview/window_selector_item.cc9
-rw-r--r--ash/wm/overview/window_selector_item.h8
-rw-r--r--ash/wm/overview/window_selector_unittest.cc109
-rw-r--r--tools/metrics/actions/actions.xml9
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>