Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3073)

Unified Diff: ash/wm/overview/window_selector.cc

Issue 358553004: Added text filtering to Overview Mode (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed unittest Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ash/wm/overview/window_selector.cc
diff --git a/ash/wm/overview/window_selector.cc b/ash/wm/overview/window_selector.cc
index 467aca6a8be669310006d0cafc85b779f1f87e3f..fd8604e5ab228e8c7c0597af9d7a1938834f637c 100644
--- a/ash/wm/overview/window_selector.cc
+++ b/ash/wm/overview/window_selector.cc
@@ -19,6 +19,7 @@
#include "ash/wm/overview/window_selector_item.h"
#include "ash/wm/window_state.h"
#include "base/auto_reset.h"
+#include "base/command_line.h"
#include "base/metrics/histogram.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/window.h"
@@ -27,6 +28,8 @@
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/events/event.h"
#include "ui/gfx/screen.h"
+#include "ui/views/border.h"
+#include "ui/views/controls/textfield/textfield.h"
#include "ui/wm/core/window_util.h"
#include "ui/wm/public/activation_client.h"
@@ -34,6 +37,21 @@ namespace ash {
namespace {
+// The proportion of screen width that the text filter takes.
+const float kTextFilterScreenProportion = 0.5;
+
+// The height of the text filter.
+const int kTextFilterHeight = 50;
+
+// Solid shadow length from the text filter.
+const int kVerticalShadowOffset = 1;
+
+// Amount of blur applied to the text filter shadow.
+const int kShadowBlur = 10;
+
+// Text filter shadow color.
+const SkColor kTextFilterShadow = 0xB0000000;
+
// A comparator for locating a grid with a given root window.
struct RootWindowGridComparator
: public std::unary_function<WindowGrid*, bool> {
@@ -87,6 +105,42 @@ void UpdateShelfVisibility() {
}
}
+// Initializes the text filter on the top of the main root window and requests
+// focus on its textfield.
+views::Widget* CreateTextFilter(views::TextfieldController* controller,
+ aura::Window* root_window) {
+ views::Widget* widget = new views::Widget;
+ views::Widget::InitParams params;
+ 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.parent =
+ Shell::GetContainer(root_window, ash::kShellWindowId_OverlayContainer);
+ params.accept_events = true;
+ params.bounds = gfx::Rect(
+ root_window->bounds().width() / 2 * (1 - kTextFilterScreenProportion), 0,
+ root_window->bounds().width() * kTextFilterScreenProportion,
+ kTextFilterHeight);
+ widget->Init(params);
+
+ views::Textfield* textfield = new views::Textfield;
+ textfield->set_controller(controller);
+ textfield->SetBackgroundColor(SK_ColorTRANSPARENT);
+ textfield->SetBorder(views::Border::NullBorder());
+ textfield->SetTextColor(SK_ColorWHITE);
+ textfield->SetShadows(gfx::ShadowValues(1, gfx::ShadowValue(
+ gfx::Point(0, kVerticalShadowOffset), kShadowBlur, kTextFilterShadow)));
+ widget->SetContentsView(textfield);
+
+ gfx::Transform transform;
+ transform.Translate(0, -kTextFilterHeight);
+ widget->GetNativeWindow()->SetTransform(transform);
+ widget->Show();
+ textfield->RequestFocus();
+
+ return widget;
+}
+
} // namespace
WindowSelector::WindowSelector(const WindowList& windows,
@@ -98,7 +152,8 @@ WindowSelector::WindowSelector(const WindowList& windows,
selected_grid_index_(0),
overview_start_time_(base::Time::Now()),
num_key_presses_(0),
- num_items_(0) {
+ num_items_(0),
+ showing_selection_widget_(false) {
DCHECK(delegate_);
Shell* shell = Shell::GetInstance();
shell->OnOverviewModeStarting();
@@ -127,13 +182,11 @@ WindowSelector::WindowSelector(const WindowList& windows,
DCHECK(!grid_list_.empty());
UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.Items", num_items_);
- shell->activation_client()->AddObserver(this);
+ text_filter_widget_.reset(
+ CreateTextFilter(this, Shell::GetPrimaryRootWindow()));
- // Remove focus from active window before entering overview.
- aura::client::GetFocusClient(
- Shell::GetPrimaryRootWindow())->FocusWindow(NULL);
+ shell->activation_client()->AddObserver(this);
- shell->PrependPreTargetHandler(this);
shell->GetScreen()->AddObserver(this);
shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW);
HideAndTrackNonOverviewWindows();
@@ -168,7 +221,6 @@ WindowSelector::~WindowSelector() {
(*iter)->Show();
}
- shell->RemovePreTargetHandler(this);
shell->GetScreen()->RemoveObserver(this);
size_t remaining_items = 0;
@@ -207,34 +259,35 @@ void WindowSelector::OnGridEmpty(WindowGrid* grid) {
CancelSelection();
}
-void WindowSelector::OnKeyEvent(ui::KeyEvent* event) {
- if (event->type() != ui::ET_KEY_PRESSED)
- return;
+bool WindowSelector::HandleKeyEvent(views::Textfield* sender,
+ const ui::KeyEvent& key_event) {
+ if (key_event.type() != ui::ET_KEY_PRESSED)
+ return false;
- switch (event->key_code()) {
+ switch (key_event.key_code()) {
case ui::VKEY_ESCAPE:
CancelSelection();
break;
case ui::VKEY_UP:
num_key_presses_++;
- Move(WindowSelector::UP);
+ Move(WindowSelector::UP, true);
break;
case ui::VKEY_DOWN:
num_key_presses_++;
- Move(WindowSelector::DOWN);
+ Move(WindowSelector::DOWN, true);
break;
case ui::VKEY_RIGHT:
num_key_presses_++;
- Move(WindowSelector::RIGHT);
+ Move(WindowSelector::RIGHT, true);
break;
case ui::VKEY_LEFT:
num_key_presses_++;
- Move(WindowSelector::LEFT);
+ Move(WindowSelector::LEFT, true);
break;
case ui::VKEY_RETURN:
// Ignore if no item is selected.
if (!grid_list_[selected_grid_index_]->is_selecting())
- return;
+ return false;
UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.ArrowKeyPresses",
num_key_presses_);
UMA_HISTOGRAM_CUSTOM_COUNTS(
@@ -246,10 +299,10 @@ void WindowSelector::OnKeyEvent(ui::KeyEvent* event) {
SelectedWindow()->SelectionWindow())->Activate();
break;
default:
- // Not a key we are interested in.
- return;
+ // Not a key we are interested in, allow the textfield to handle it.
+ return false;
}
- event->StopPropagation();
+ return true;
}
void WindowSelector::OnDisplayAdded(const gfx::Display& display) {
@@ -290,8 +343,11 @@ void WindowSelector::OnWindowDestroying(aura::Window* window) {
void WindowSelector::OnWindowActivated(aura::Window* gained_active,
aura::Window* lost_active) {
- if (ignore_activations_ || !gained_active)
+ if (ignore_activations_ ||
+ !gained_active ||
+ gained_active == text_filter_widget_->GetNativeWindow()) {
return;
+ }
ScopedVector<WindowGrid>::iterator grid =
std::find_if(grid_list_.begin(), grid_list_.end(),
@@ -317,6 +373,43 @@ void WindowSelector::OnAttemptToReactivateWindow(aura::Window* request_active,
OnWindowActivated(request_active, actual_active);
}
+void WindowSelector::ContentsChanged(views::Textfield* sender,
+ const base::string16& new_contents) {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kAshDisableTextFilteringInOverviewMode)) {
+ return;
+ }
+
+ bool should_show_selection_widget = !new_contents.empty();
+ if (showing_selection_widget_ != should_show_selection_widget) {
+ ui::ScopedLayerAnimationSettings animation_settings(
+ text_filter_widget_->GetNativeWindow()->layer()->GetAnimator());
+ animation_settings.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ animation_settings.SetTweenType(showing_selection_widget_ ?
+ gfx::Tween::FAST_OUT_LINEAR_IN : gfx::Tween::LINEAR_OUT_SLOW_IN);
+
+ gfx::Transform transform;
+ if (should_show_selection_widget)
+ transform.Translate(0, 0);
+ else
+ transform.Translate(0, -kTextFilterHeight);
+
+ text_filter_widget_->GetNativeWindow()->SetTransform(transform);
+ showing_selection_widget_ = should_show_selection_widget;
+ }
+ for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin();
+ iter != grid_list_.end(); iter++) {
+ (*iter)->FilterItems(new_contents);
+ }
+
+ // If the selection widget is not active, execute a Move() command so that it
+ // shows up on the first undimmed item.
+ if (grid_list_[selected_grid_index_]->is_selecting())
+ return;
+ Move(WindowSelector::RIGHT, false);
+}
+
void WindowSelector::PositionWindows(bool animate) {
for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin();
iter != grid_list_.end(); iter++) {
@@ -379,16 +472,15 @@ void WindowSelector::ResetFocusRestoreWindow(bool focus) {
restore_focus_window_ = NULL;
}
-void WindowSelector::Move(Direction direction) {
- bool overflowed = grid_list_[selected_grid_index_]->Move(direction);
- if (overflowed) {
- // The grid reported that the movement command corresponds to the next
- // root window, identify it and call Move() on it to initialize the
- // selection widget.
+void WindowSelector::Move(Direction direction, bool animate) {
+ // Keep calling Move() on the grids until one of them reports no overflow or
+ // we made a full cycle on all the grids.
+ for (size_t i = 0;
+ i <= grid_list_.size() &&
+ grid_list_[selected_grid_index_]->Move(direction, animate); i++) {
// TODO(nsatragno): If there are more than two monitors, move between grids
// in the requested direction.
selected_grid_index_ = (selected_grid_index_ + 1) % grid_list_.size();
- grid_list_[selected_grid_index_]->Move(direction);
}
}

Powered by Google App Engine
This is Rietveld 408576698