Commit ec8ba66f authored by tdanderson's avatar tdanderson Committed by Commit bot

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}
parent 326d757e
......@@ -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"));
......
......@@ -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,
......
......@@ -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_));
}
}
......
......@@ -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.
......
......@@ -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_;
}
......
......@@ -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) {
......
......@@ -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);
};
......
......@@ -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) {
......
......@@ -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>
......
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