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

Side by Side 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: Created 6 years, 6 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 unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ash/wm/overview/window_selector.h" 5 #include "ash/wm/overview/window_selector.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "ash/accessibility_delegate.h" 9 #include "ash/accessibility_delegate.h"
10 #include "ash/ash_switches.h" 10 #include "ash/ash_switches.h"
11 #include "ash/metrics/user_metrics_recorder.h" 11 #include "ash/metrics/user_metrics_recorder.h"
12 #include "ash/root_window_controller.h" 12 #include "ash/root_window_controller.h"
13 #include "ash/shell.h" 13 #include "ash/shell.h"
14 #include "ash/shell_window_ids.h" 14 #include "ash/shell_window_ids.h"
15 #include "ash/switchable_windows.h" 15 #include "ash/switchable_windows.h"
16 #include "ash/wm/overview/scoped_transform_overview_window.h" 16 #include "ash/wm/overview/scoped_transform_overview_window.h"
17 #include "ash/wm/overview/window_grid.h" 17 #include "ash/wm/overview/window_grid.h"
18 #include "ash/wm/overview/window_selector_delegate.h" 18 #include "ash/wm/overview/window_selector_delegate.h"
19 #include "ash/wm/overview/window_selector_item.h" 19 #include "ash/wm/overview/window_selector_item.h"
20 #include "ash/wm/window_state.h" 20 #include "ash/wm/window_state.h"
21 #include "base/auto_reset.h" 21 #include "base/auto_reset.h"
22 #include "base/metrics/histogram.h" 22 #include "base/metrics/histogram.h"
23 #include "ui/aura/client/focus_client.h" 23 #include "ui/aura/client/focus_client.h"
24 #include "ui/aura/window.h" 24 #include "ui/aura/window.h"
25 #include "ui/aura/window_event_dispatcher.h" 25 #include "ui/aura/window_event_dispatcher.h"
26 #include "ui/aura/window_observer.h" 26 #include "ui/aura/window_observer.h"
27 #include "ui/compositor/scoped_layer_animation_settings.h" 27 #include "ui/compositor/scoped_layer_animation_settings.h"
28 #include "ui/events/event.h" 28 #include "ui/events/event.h"
29 #include "ui/gfx/screen.h" 29 #include "ui/gfx/screen.h"
30 #include "ui/views/border.h"
31 #include "ui/views/controls/textfield/textfield.h"
30 #include "ui/wm/core/window_util.h" 32 #include "ui/wm/core/window_util.h"
31 #include "ui/wm/public/activation_client.h" 33 #include "ui/wm/public/activation_client.h"
32 34
33 namespace ash { 35 namespace ash {
34 36
35 namespace { 37 namespace {
36 38
37 // A comparator for locating a grid with a given root window. 39 // A comparator for locating a grid with a given root window.
38 struct RootWindowGridComparator 40 struct RootWindowGridComparator
39 : public std::unary_function<WindowGrid*, bool> { 41 : public std::unary_function<WindowGrid*, bool> {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 void UpdateShelfVisibility() { 82 void UpdateShelfVisibility() {
81 Shell::RootWindowControllerList root_window_controllers = 83 Shell::RootWindowControllerList root_window_controllers =
82 Shell::GetInstance()->GetAllRootWindowControllers(); 84 Shell::GetInstance()->GetAllRootWindowControllers();
83 for (Shell::RootWindowControllerList::iterator iter = 85 for (Shell::RootWindowControllerList::iterator iter =
84 root_window_controllers.begin(); 86 root_window_controllers.begin();
85 iter != root_window_controllers.end(); ++iter) { 87 iter != root_window_controllers.end(); ++iter) {
86 (*iter)->UpdateShelfVisibility(); 88 (*iter)->UpdateShelfVisibility();
87 } 89 }
88 } 90 }
89 91
92 views::Widget* CreateTextFilter(views::TextfieldController* controller,
tdanderson 2014/06/25 15:48:23 Add some documentation on line 91 for this method.
Nina 2014/06/26 15:20:17 Done.
93 aura::Window* root_window) {
94 views::Widget* widget = new views::Widget;
95 views::Widget::InitParams params;
96 params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
97 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
98 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
99 params.parent =
100 Shell::GetContainer(root_window, ash::kShellWindowId_OverlayContainer);
101 params.accept_events = true;
102 params.bounds = gfx::Rect(root_window->bounds().width() / 4, 0,
103 root_window->bounds().width() / 2, 0);
104 widget->Init(params);
105 views::Textfield* textfield = new views::Textfield;
106 textfield->set_controller(controller);
107 textfield->SetBackgroundColor(SK_ColorTRANSPARENT);
108 textfield->SetBorder(views::Border::NullBorder());
109 textfield->SetTextColor(SK_ColorWHITE);
110 textfield->DisplayShadow(true);
111 widget->SetContentsView(textfield);
112 widget->Show();
113 textfield->RequestFocus();
114
115 return widget;
116 }
117
90 } // namespace 118 } // namespace
91 119
92 WindowSelector::WindowSelector(const WindowList& windows, 120 WindowSelector::WindowSelector(const WindowList& windows,
93 WindowSelectorDelegate* delegate) 121 WindowSelectorDelegate* delegate)
94 : delegate_(delegate), 122 : delegate_(delegate),
95 restore_focus_window_(aura::client::GetFocusClient( 123 restore_focus_window_(aura::client::GetFocusClient(
96 Shell::GetPrimaryRootWindow())->GetFocusedWindow()), 124 Shell::GetPrimaryRootWindow())->GetFocusedWindow()),
97 ignore_activations_(false), 125 ignore_activations_(false),
98 selected_grid_index_(0), 126 selected_grid_index_(0),
99 overview_start_time_(base::Time::Now()), 127 overview_start_time_(base::Time::Now()),
100 num_key_presses_(0), 128 num_key_presses_(0),
101 num_items_(0) { 129 num_items_(0),
130 showing_selection_widget_(false) {
102 DCHECK(delegate_); 131 DCHECK(delegate_);
103 Shell* shell = Shell::GetInstance(); 132 Shell* shell = Shell::GetInstance();
104 shell->OnOverviewModeStarting(); 133 shell->OnOverviewModeStarting();
105 134
106 if (restore_focus_window_) 135 if (restore_focus_window_)
107 restore_focus_window_->AddObserver(this); 136 restore_focus_window_->AddObserver(this);
108 137
109 const aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 138 const aura::Window::Windows root_windows = Shell::GetAllRootWindows();
110 for (aura::Window::Windows::const_iterator iter = root_windows.begin(); 139 for (aura::Window::Windows::const_iterator iter = root_windows.begin();
111 iter != root_windows.end(); iter++) { 140 iter != root_windows.end(); iter++) {
112 // Observed switchable containers for newly created windows on all root 141 // Observed switchable containers for newly created windows on all root
113 // windows. 142 // windows.
114 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { 143 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) {
115 aura::Window* container = Shell::GetContainer(*iter, 144 aura::Window* container = Shell::GetContainer(*iter,
116 kSwitchableWindowContainerIds[i]); 145 kSwitchableWindowContainerIds[i]);
117 container->AddObserver(this); 146 container->AddObserver(this);
118 observed_windows_.insert(container); 147 observed_windows_.insert(container);
119 } 148 }
120 scoped_ptr<WindowGrid> grid(new WindowGrid(*iter, windows, this)); 149 scoped_ptr<WindowGrid> grid(new WindowGrid(*iter, windows, this));
121 if (grid->empty()) 150 if (grid->empty())
122 continue; 151 continue;
123 num_items_ += grid->size(); 152 num_items_ += grid->size();
124 grid_list_.push_back(grid.release()); 153 grid_list_.push_back(grid.release());
125 } 154 }
126 155
127 DCHECK(!grid_list_.empty()); 156 DCHECK(!grid_list_.empty());
128 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.Items", num_items_); 157 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.Items", num_items_);
129 158
159 text_filter_widget_.reset(
160 CreateTextFilter(this, Shell::GetPrimaryRootWindow()));
161
130 shell->activation_client()->AddObserver(this); 162 shell->activation_client()->AddObserver(this);
131 163
132 // Remove focus from active window before entering overview.
133 aura::client::GetFocusClient(
134 Shell::GetPrimaryRootWindow())->FocusWindow(NULL);
135
136 shell->PrependPreTargetHandler(this);
137 shell->GetScreen()->AddObserver(this); 164 shell->GetScreen()->AddObserver(this);
138 shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW); 165 shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW);
139 HideAndTrackNonOverviewWindows(); 166 HideAndTrackNonOverviewWindows();
140 // Send an a11y alert. 167 // Send an a11y alert.
141 shell->accessibility_delegate()->TriggerAccessibilityAlert( 168 shell->accessibility_delegate()->TriggerAccessibilityAlert(
142 A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED); 169 A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED);
143 170
144 UpdateShelfVisibility(); 171 UpdateShelfVisibility();
145 } 172 }
146 173
(...skipping 14 matching lines...) Expand all
161 ui::ScopedLayerAnimationSettings settings( 188 ui::ScopedLayerAnimationSettings settings(
162 (*iter)->layer()->GetAnimator()); 189 (*iter)->layer()->GetAnimator());
163 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( 190 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
164 ScopedTransformOverviewWindow::kTransitionMilliseconds)); 191 ScopedTransformOverviewWindow::kTransitionMilliseconds));
165 settings.SetPreemptionStrategy( 192 settings.SetPreemptionStrategy(
166 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 193 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
167 (*iter)->layer()->SetOpacity(1); 194 (*iter)->layer()->SetOpacity(1);
168 (*iter)->Show(); 195 (*iter)->Show();
169 } 196 }
170 197
171 shell->RemovePreTargetHandler(this);
172 shell->GetScreen()->RemoveObserver(this); 198 shell->GetScreen()->RemoveObserver(this);
173 199
174 size_t remaining_items = 0; 200 size_t remaining_items = 0;
175 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin(); 201 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin();
176 iter != grid_list_.end(); iter++) { 202 iter != grid_list_.end(); iter++) {
177 remaining_items += (*iter)->size(); 203 remaining_items += (*iter)->size();
178 } 204 }
179 205
180 DCHECK(num_items_ >= remaining_items); 206 DCHECK(num_items_ >= remaining_items);
181 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.OverviewClosedItems", 207 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.OverviewClosedItems",
(...skipping 18 matching lines...) Expand all
200 ScopedVector<WindowGrid>::iterator iter = 226 ScopedVector<WindowGrid>::iterator iter =
201 std::find(grid_list_.begin(), grid_list_.end(), grid); 227 std::find(grid_list_.begin(), grid_list_.end(), grid);
202 DCHECK(iter != grid_list_.end()); 228 DCHECK(iter != grid_list_.end());
203 grid_list_.erase(iter); 229 grid_list_.erase(iter);
204 // TODO(nsatragno): Use the previous index for more than two displays. 230 // TODO(nsatragno): Use the previous index for more than two displays.
205 selected_grid_index_ = 0; 231 selected_grid_index_ = 0;
206 if (grid_list_.empty()) 232 if (grid_list_.empty())
207 CancelSelection(); 233 CancelSelection();
208 } 234 }
209 235
210 void WindowSelector::OnKeyEvent(ui::KeyEvent* event) { 236 bool WindowSelector::HandleKeyEvent(views::Textfield* sender,
211 if (event->type() != ui::ET_KEY_PRESSED) 237 const ui::KeyEvent& key_event) {
212 return; 238 if (key_event.type() != ui::ET_KEY_PRESSED)
239 return false;
213 240
214 switch (event->key_code()) { 241 switch (key_event.key_code()) {
215 case ui::VKEY_ESCAPE: 242 case ui::VKEY_ESCAPE:
216 CancelSelection(); 243 CancelSelection();
217 break; 244 break;
218 case ui::VKEY_UP: 245 case ui::VKEY_UP:
219 num_key_presses_++; 246 num_key_presses_++;
220 Move(WindowSelector::UP); 247 Move(WindowSelector::UP);
221 break; 248 break;
222 case ui::VKEY_DOWN: 249 case ui::VKEY_DOWN:
223 num_key_presses_++; 250 num_key_presses_++;
224 Move(WindowSelector::DOWN); 251 Move(WindowSelector::DOWN);
225 break; 252 break;
226 case ui::VKEY_RIGHT: 253 case ui::VKEY_RIGHT:
227 num_key_presses_++; 254 num_key_presses_++;
228 Move(WindowSelector::RIGHT); 255 Move(WindowSelector::RIGHT);
229 break; 256 break;
230 case ui::VKEY_LEFT: 257 case ui::VKEY_LEFT:
231 num_key_presses_++; 258 num_key_presses_++;
232 Move(WindowSelector::LEFT); 259 Move(WindowSelector::LEFT);
233 break; 260 break;
234 case ui::VKEY_RETURN: 261 case ui::VKEY_RETURN:
235 // Ignore if no item is selected. 262 // Ignore if no item is selected.
236 if (!grid_list_[selected_grid_index_]->is_selecting()) 263 if (!grid_list_[selected_grid_index_]->is_selecting())
237 return; 264 return true;
tdanderson 2014/06/25 15:48:23 Should this be return false?
Nina 2014/06/26 15:20:17 I don't think we want the user to be able to write
238 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.ArrowKeyPresses", 265 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.ArrowKeyPresses",
239 num_key_presses_); 266 num_key_presses_);
240 UMA_HISTOGRAM_CUSTOM_COUNTS( 267 UMA_HISTOGRAM_CUSTOM_COUNTS(
241 "Ash.WindowSelector.KeyPressesOverItemsRatio", 268 "Ash.WindowSelector.KeyPressesOverItemsRatio",
242 (num_key_presses_ * 100) / num_items_, 1, 300, 30); 269 (num_key_presses_ * 100) / num_items_, 1, 300, 30);
243 Shell::GetInstance()->metrics()->RecordUserMetricsAction( 270 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
244 UMA_WINDOW_OVERVIEW_ENTER_KEY); 271 UMA_WINDOW_OVERVIEW_ENTER_KEY);
245 wm::GetWindowState(grid_list_[selected_grid_index_]-> 272 wm::GetWindowState(grid_list_[selected_grid_index_]->
246 SelectedWindow()->SelectionWindow())->Activate(); 273 SelectedWindow()->SelectionWindow())->Activate();
247 break; 274 break;
248 default: 275 default:
249 // Not a key we are interested in. 276 // Not a key we are interested in, allow the textfield to handle it.
250 return; 277 return false;
251 } 278 }
252 event->StopPropagation(); 279 return true;
253 } 280 }
254 281
255 void WindowSelector::OnDisplayAdded(const gfx::Display& display) { 282 void WindowSelector::OnDisplayAdded(const gfx::Display& display) {
256 } 283 }
257 284
258 void WindowSelector::OnDisplayRemoved(const gfx::Display& display) { 285 void WindowSelector::OnDisplayRemoved(const gfx::Display& display) {
259 // TODO(nsatragno): Keep window selection active on remaining displays. 286 // TODO(nsatragno): Keep window selection active on remaining displays.
260 CancelSelection(); 287 CancelSelection();
261 } 288 }
262 289
(...skipping 20 matching lines...) Expand all
283 310
284 void WindowSelector::OnWindowDestroying(aura::Window* window) { 311 void WindowSelector::OnWindowDestroying(aura::Window* window) {
285 window->RemoveObserver(this); 312 window->RemoveObserver(this);
286 observed_windows_.erase(window); 313 observed_windows_.erase(window);
287 if (window == restore_focus_window_) 314 if (window == restore_focus_window_)
288 restore_focus_window_ = NULL; 315 restore_focus_window_ = NULL;
289 } 316 }
290 317
291 void WindowSelector::OnWindowActivated(aura::Window* gained_active, 318 void WindowSelector::OnWindowActivated(aura::Window* gained_active,
292 aura::Window* lost_active) { 319 aura::Window* lost_active) {
293 if (ignore_activations_ || !gained_active) 320 if (ignore_activations_ || !gained_active ||
tdanderson 2014/06/25 15:48:23 Use three lines.
Nina 2014/06/26 15:20:17 Done.
321 gained_active == text_filter_widget_->GetNativeWindow()) {
294 return; 322 return;
323 }
295 324
296 ScopedVector<WindowGrid>::iterator grid = 325 ScopedVector<WindowGrid>::iterator grid =
297 std::find_if(grid_list_.begin(), grid_list_.end(), 326 std::find_if(grid_list_.begin(), grid_list_.end(),
298 RootWindowGridComparator(gained_active->GetRootWindow())); 327 RootWindowGridComparator(gained_active->GetRootWindow()));
299 if (grid == grid_list_.end()) 328 if (grid == grid_list_.end())
300 return; 329 return;
301 const std::vector<WindowSelectorItem*> windows = (*grid)->window_list(); 330 const std::vector<WindowSelectorItem*> windows = (*grid)->window_list();
302 331
303 ScopedVector<WindowSelectorItem>::const_iterator iter = std::find_if( 332 ScopedVector<WindowSelectorItem>::const_iterator iter = std::find_if(
304 windows.begin(), windows.end(), 333 windows.begin(), windows.end(),
305 WindowSelectorItemTargetComparator(gained_active)); 334 WindowSelectorItemTargetComparator(gained_active));
306 335
307 if (iter != windows.end()) 336 if (iter != windows.end())
308 (*iter)->RestoreWindowOnExit(gained_active); 337 (*iter)->RestoreWindowOnExit(gained_active);
309 338
310 // Don't restore focus on exit if a window was just activated. 339 // Don't restore focus on exit if a window was just activated.
311 ResetFocusRestoreWindow(false); 340 ResetFocusRestoreWindow(false);
312 CancelSelection(); 341 CancelSelection();
313 } 342 }
314 343
315 void WindowSelector::OnAttemptToReactivateWindow(aura::Window* request_active, 344 void WindowSelector::OnAttemptToReactivateWindow(aura::Window* request_active,
316 aura::Window* actual_active) { 345 aura::Window* actual_active) {
317 OnWindowActivated(request_active, actual_active); 346 OnWindowActivated(request_active, actual_active);
318 } 347 }
319 348
349 void WindowSelector::ContentsChanged(views::Textfield* sender,
350 const base::string16& new_contents) {
351 if (!showing_selection_widget_ || new_contents.empty()) {
352 ui::ScopedLayerAnimationSettings animation_settings(
353 text_filter_widget_->GetNativeWindow()->layer()->GetAnimator());
354 animation_settings.SetPreemptionStrategy(
355 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
356 animation_settings.SetTweenType(showing_selection_widget_ ?
357 gfx::Tween::FAST_OUT_LINEAR_IN : gfx::Tween::LINEAR_OUT_SLOW_IN);
358 size_t root_window_width = Shell::GetPrimaryRootWindow()->bounds().width();
359 text_filter_widget_->SetBounds(
360 gfx::Rect(root_window_width / 4, 0,root_window_width / 2,
361 showing_selection_widget_ ? 0 : 50));
362 showing_selection_widget_ = !showing_selection_widget_;
363 }
364 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin();
365 iter != grid_list_.end(); iter++) {
tdanderson 2014/06/25 15:48:23 Align iter with ScopedVector.
Nina 2014/06/26 15:20:17 Done.
366 (*iter)->Filter(new_contents);
367 }
368 }
369
320 void WindowSelector::PositionWindows(bool animate) { 370 void WindowSelector::PositionWindows(bool animate) {
321 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin(); 371 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin();
322 iter != grid_list_.end(); iter++) { 372 iter != grid_list_.end(); iter++) {
323 (*iter)->PositionWindows(animate); 373 (*iter)->PositionWindows(animate);
324 } 374 }
325 } 375 }
326 376
327 void WindowSelector::HideAndTrackNonOverviewWindows() { 377 void WindowSelector::HideAndTrackNonOverviewWindows() {
328 // Add the windows to hidden_windows first so that if any are destroyed 378 // Add the windows to hidden_windows first so that if any are destroyed
329 // while hiding them they are tracked. 379 // while hiding them they are tracked.
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 // root window, identify it and call Move() on it to initialize the 436 // root window, identify it and call Move() on it to initialize the
387 // selection widget. 437 // selection widget.
388 // TODO(nsatragno): If there are more than two monitors, move between grids 438 // TODO(nsatragno): If there are more than two monitors, move between grids
389 // in the requested direction. 439 // in the requested direction.
390 selected_grid_index_ = (selected_grid_index_ + 1) % grid_list_.size(); 440 selected_grid_index_ = (selected_grid_index_ + 1) % grid_list_.size();
391 grid_list_[selected_grid_index_]->Move(direction); 441 grid_list_[selected_grid_index_]->Move(direction);
392 } 442 }
393 } 443 }
394 444
395 } // namespace ash 445 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698