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

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: Fixed Terry's comments. 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 // Initializes the text filter on the top of the main root window and requests
93 // focus on its textfield.
94 views::Widget* CreateTextFilter(views::TextfieldController* controller,
95 aura::Window* root_window) {
96 views::Widget* widget = new views::Widget;
97 views::Widget::InitParams params;
98 params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
99 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
100 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
101 params.parent =
102 Shell::GetContainer(root_window, ash::kShellWindowId_OverlayContainer);
103 params.accept_events = true;
104 params.bounds = gfx::Rect(root_window->bounds().width() / 4, 0,
105 root_window->bounds().width() / 2, 0);
flackr 2014/06/26 17:33:07 nit: use constants, in this case something like kT
Nina 2014/06/27 15:20:39 Done.
106 widget->Init(params);
107 views::Textfield* textfield = new views::Textfield;
108 textfield->set_controller(controller);
109 textfield->SetBackgroundColor(SK_ColorTRANSPARENT);
110 textfield->SetBorder(views::Border::NullBorder());
111 textfield->SetTextColor(SK_ColorWHITE);
112 textfield->DisplayShadow(true);
113 widget->SetContentsView(textfield);
114 widget->Show();
115 textfield->RequestFocus();
116
117 return widget;
118 }
119
90 } // namespace 120 } // namespace
91 121
92 WindowSelector::WindowSelector(const WindowList& windows, 122 WindowSelector::WindowSelector(const WindowList& windows,
93 WindowSelectorDelegate* delegate) 123 WindowSelectorDelegate* delegate)
94 : delegate_(delegate), 124 : delegate_(delegate),
95 restore_focus_window_(aura::client::GetFocusClient( 125 restore_focus_window_(aura::client::GetFocusClient(
96 Shell::GetPrimaryRootWindow())->GetFocusedWindow()), 126 Shell::GetPrimaryRootWindow())->GetFocusedWindow()),
97 ignore_activations_(false), 127 ignore_activations_(false),
98 selected_grid_index_(0), 128 selected_grid_index_(0),
99 overview_start_time_(base::Time::Now()), 129 overview_start_time_(base::Time::Now()),
100 num_key_presses_(0), 130 num_key_presses_(0),
101 num_items_(0) { 131 num_items_(0),
132 showing_selection_widget_(false) {
flackr 2014/06/26 17:33:07 Do we need this variable or can we just check if t
Nina 2014/06/27 15:20:39 We could remove the variable at the cost of having
102 DCHECK(delegate_); 133 DCHECK(delegate_);
103 Shell* shell = Shell::GetInstance(); 134 Shell* shell = Shell::GetInstance();
104 shell->OnOverviewModeStarting(); 135 shell->OnOverviewModeStarting();
105 136
106 if (restore_focus_window_) 137 if (restore_focus_window_)
107 restore_focus_window_->AddObserver(this); 138 restore_focus_window_->AddObserver(this);
108 139
109 const aura::Window::Windows root_windows = Shell::GetAllRootWindows(); 140 const aura::Window::Windows root_windows = Shell::GetAllRootWindows();
110 for (aura::Window::Windows::const_iterator iter = root_windows.begin(); 141 for (aura::Window::Windows::const_iterator iter = root_windows.begin();
111 iter != root_windows.end(); iter++) { 142 iter != root_windows.end(); iter++) {
112 // Observed switchable containers for newly created windows on all root 143 // Observed switchable containers for newly created windows on all root
113 // windows. 144 // windows.
114 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) { 145 for (size_t i = 0; i < kSwitchableWindowContainerIdsLength; ++i) {
115 aura::Window* container = Shell::GetContainer(*iter, 146 aura::Window* container = Shell::GetContainer(*iter,
116 kSwitchableWindowContainerIds[i]); 147 kSwitchableWindowContainerIds[i]);
117 container->AddObserver(this); 148 container->AddObserver(this);
118 observed_windows_.insert(container); 149 observed_windows_.insert(container);
119 } 150 }
120 scoped_ptr<WindowGrid> grid(new WindowGrid(*iter, windows, this)); 151 scoped_ptr<WindowGrid> grid(new WindowGrid(*iter, windows, this));
121 if (grid->empty()) 152 if (grid->empty())
122 continue; 153 continue;
123 num_items_ += grid->size(); 154 num_items_ += grid->size();
124 grid_list_.push_back(grid.release()); 155 grid_list_.push_back(grid.release());
125 } 156 }
126 157
127 DCHECK(!grid_list_.empty()); 158 DCHECK(!grid_list_.empty());
128 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.Items", num_items_); 159 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.Items", num_items_);
129 160
161 text_filter_widget_.reset(
162 CreateTextFilter(this, Shell::GetPrimaryRootWindow()));
163
130 shell->activation_client()->AddObserver(this); 164 shell->activation_client()->AddObserver(this);
131 165
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); 166 shell->GetScreen()->AddObserver(this);
138 shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW); 167 shell->metrics()->RecordUserMetricsAction(UMA_WINDOW_OVERVIEW);
139 HideAndTrackNonOverviewWindows(); 168 HideAndTrackNonOverviewWindows();
140 // Send an a11y alert. 169 // Send an a11y alert.
141 shell->accessibility_delegate()->TriggerAccessibilityAlert( 170 shell->accessibility_delegate()->TriggerAccessibilityAlert(
142 A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED); 171 A11Y_ALERT_WINDOW_OVERVIEW_MODE_ENTERED);
143 172
144 UpdateShelfVisibility(); 173 UpdateShelfVisibility();
145 } 174 }
146 175
(...skipping 14 matching lines...) Expand all
161 ui::ScopedLayerAnimationSettings settings( 190 ui::ScopedLayerAnimationSettings settings(
162 (*iter)->layer()->GetAnimator()); 191 (*iter)->layer()->GetAnimator());
163 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( 192 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(
164 ScopedTransformOverviewWindow::kTransitionMilliseconds)); 193 ScopedTransformOverviewWindow::kTransitionMilliseconds));
165 settings.SetPreemptionStrategy( 194 settings.SetPreemptionStrategy(
166 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); 195 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
167 (*iter)->layer()->SetOpacity(1); 196 (*iter)->layer()->SetOpacity(1);
168 (*iter)->Show(); 197 (*iter)->Show();
169 } 198 }
170 199
171 shell->RemovePreTargetHandler(this);
172 shell->GetScreen()->RemoveObserver(this); 200 shell->GetScreen()->RemoveObserver(this);
173 201
174 size_t remaining_items = 0; 202 size_t remaining_items = 0;
175 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin(); 203 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin();
176 iter != grid_list_.end(); iter++) { 204 iter != grid_list_.end(); iter++) {
177 remaining_items += (*iter)->size(); 205 remaining_items += (*iter)->size();
178 } 206 }
179 207
180 DCHECK(num_items_ >= remaining_items); 208 DCHECK(num_items_ >= remaining_items);
181 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.OverviewClosedItems", 209 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.OverviewClosedItems",
(...skipping 18 matching lines...) Expand all
200 ScopedVector<WindowGrid>::iterator iter = 228 ScopedVector<WindowGrid>::iterator iter =
201 std::find(grid_list_.begin(), grid_list_.end(), grid); 229 std::find(grid_list_.begin(), grid_list_.end(), grid);
202 DCHECK(iter != grid_list_.end()); 230 DCHECK(iter != grid_list_.end());
203 grid_list_.erase(iter); 231 grid_list_.erase(iter);
204 // TODO(nsatragno): Use the previous index for more than two displays. 232 // TODO(nsatragno): Use the previous index for more than two displays.
205 selected_grid_index_ = 0; 233 selected_grid_index_ = 0;
206 if (grid_list_.empty()) 234 if (grid_list_.empty())
207 CancelSelection(); 235 CancelSelection();
208 } 236 }
209 237
210 void WindowSelector::OnKeyEvent(ui::KeyEvent* event) { 238 bool WindowSelector::HandleKeyEvent(views::Textfield* sender,
211 if (event->type() != ui::ET_KEY_PRESSED) 239 const ui::KeyEvent& key_event) {
212 return; 240 if (key_event.type() != ui::ET_KEY_PRESSED)
241 return false;
213 242
214 switch (event->key_code()) { 243 switch (key_event.key_code()) {
215 case ui::VKEY_ESCAPE: 244 case ui::VKEY_ESCAPE:
216 CancelSelection(); 245 CancelSelection();
217 break; 246 break;
218 case ui::VKEY_UP: 247 case ui::VKEY_UP:
219 num_key_presses_++; 248 num_key_presses_++;
220 Move(WindowSelector::UP); 249 Move(WindowSelector::UP);
221 break; 250 break;
222 case ui::VKEY_DOWN: 251 case ui::VKEY_DOWN:
223 num_key_presses_++; 252 num_key_presses_++;
224 Move(WindowSelector::DOWN); 253 Move(WindowSelector::DOWN);
225 break; 254 break;
226 case ui::VKEY_RIGHT: 255 case ui::VKEY_RIGHT:
227 num_key_presses_++; 256 num_key_presses_++;
228 Move(WindowSelector::RIGHT); 257 Move(WindowSelector::RIGHT);
229 break; 258 break;
230 case ui::VKEY_LEFT: 259 case ui::VKEY_LEFT:
231 num_key_presses_++; 260 num_key_presses_++;
232 Move(WindowSelector::LEFT); 261 Move(WindowSelector::LEFT);
233 break; 262 break;
234 case ui::VKEY_RETURN: 263 case ui::VKEY_RETURN:
235 // Ignore if no item is selected. 264 // Ignore if no item is selected.
236 if (!grid_list_[selected_grid_index_]->is_selecting()) 265 if (!grid_list_[selected_grid_index_]->is_selecting())
237 return; 266 return true;
238 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.ArrowKeyPresses", 267 UMA_HISTOGRAM_COUNTS_100("Ash.WindowSelector.ArrowKeyPresses",
239 num_key_presses_); 268 num_key_presses_);
240 UMA_HISTOGRAM_CUSTOM_COUNTS( 269 UMA_HISTOGRAM_CUSTOM_COUNTS(
241 "Ash.WindowSelector.KeyPressesOverItemsRatio", 270 "Ash.WindowSelector.KeyPressesOverItemsRatio",
242 (num_key_presses_ * 100) / num_items_, 1, 300, 30); 271 (num_key_presses_ * 100) / num_items_, 1, 300, 30);
243 Shell::GetInstance()->metrics()->RecordUserMetricsAction( 272 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
244 UMA_WINDOW_OVERVIEW_ENTER_KEY); 273 UMA_WINDOW_OVERVIEW_ENTER_KEY);
245 wm::GetWindowState(grid_list_[selected_grid_index_]-> 274 wm::GetWindowState(grid_list_[selected_grid_index_]->
246 SelectedWindow()->SelectionWindow())->Activate(); 275 SelectedWindow()->SelectionWindow())->Activate();
247 break; 276 break;
248 default: 277 default:
249 // Not a key we are interested in. 278 // Not a key we are interested in, allow the textfield to handle it.
250 return; 279 return false;
251 } 280 }
252 event->StopPropagation(); 281 return true;
253 } 282 }
254 283
255 void WindowSelector::OnDisplayAdded(const gfx::Display& display) { 284 void WindowSelector::OnDisplayAdded(const gfx::Display& display) {
256 } 285 }
257 286
258 void WindowSelector::OnDisplayRemoved(const gfx::Display& display) { 287 void WindowSelector::OnDisplayRemoved(const gfx::Display& display) {
259 // TODO(nsatragno): Keep window selection active on remaining displays. 288 // TODO(nsatragno): Keep window selection active on remaining displays.
260 CancelSelection(); 289 CancelSelection();
261 } 290 }
262 291
(...skipping 20 matching lines...) Expand all
283 312
284 void WindowSelector::OnWindowDestroying(aura::Window* window) { 313 void WindowSelector::OnWindowDestroying(aura::Window* window) {
285 window->RemoveObserver(this); 314 window->RemoveObserver(this);
286 observed_windows_.erase(window); 315 observed_windows_.erase(window);
287 if (window == restore_focus_window_) 316 if (window == restore_focus_window_)
288 restore_focus_window_ = NULL; 317 restore_focus_window_ = NULL;
289 } 318 }
290 319
291 void WindowSelector::OnWindowActivated(aura::Window* gained_active, 320 void WindowSelector::OnWindowActivated(aura::Window* gained_active,
292 aura::Window* lost_active) { 321 aura::Window* lost_active) {
293 if (ignore_activations_ || !gained_active) 322 if (ignore_activations_ ||
323 !gained_active ||
324 gained_active == text_filter_widget_->GetNativeWindow()) {
294 return; 325 return;
326 }
295 327
296 ScopedVector<WindowGrid>::iterator grid = 328 ScopedVector<WindowGrid>::iterator grid =
297 std::find_if(grid_list_.begin(), grid_list_.end(), 329 std::find_if(grid_list_.begin(), grid_list_.end(),
298 RootWindowGridComparator(gained_active->GetRootWindow())); 330 RootWindowGridComparator(gained_active->GetRootWindow()));
299 if (grid == grid_list_.end()) 331 if (grid == grid_list_.end())
300 return; 332 return;
301 const std::vector<WindowSelectorItem*> windows = (*grid)->window_list(); 333 const std::vector<WindowSelectorItem*> windows = (*grid)->window_list();
302 334
303 ScopedVector<WindowSelectorItem>::const_iterator iter = std::find_if( 335 ScopedVector<WindowSelectorItem>::const_iterator iter = std::find_if(
304 windows.begin(), windows.end(), 336 windows.begin(), windows.end(),
305 WindowSelectorItemTargetComparator(gained_active)); 337 WindowSelectorItemTargetComparator(gained_active));
306 338
307 if (iter != windows.end()) 339 if (iter != windows.end())
308 (*iter)->RestoreWindowOnExit(gained_active); 340 (*iter)->RestoreWindowOnExit(gained_active);
309 341
310 // Don't restore focus on exit if a window was just activated. 342 // Don't restore focus on exit if a window was just activated.
311 ResetFocusRestoreWindow(false); 343 ResetFocusRestoreWindow(false);
312 CancelSelection(); 344 CancelSelection();
313 } 345 }
314 346
315 void WindowSelector::OnAttemptToReactivateWindow(aura::Window* request_active, 347 void WindowSelector::OnAttemptToReactivateWindow(aura::Window* request_active,
316 aura::Window* actual_active) { 348 aura::Window* actual_active) {
317 OnWindowActivated(request_active, actual_active); 349 OnWindowActivated(request_active, actual_active);
318 } 350 }
319 351
352 void WindowSelector::ContentsChanged(views::Textfield* sender,
353 const base::string16& new_contents) {
354 if (!showing_selection_widget_ || new_contents.empty()) {
flackr 2014/06/26 17:33:07 We did say this should be behind a flag right? Can
Nina 2014/06/27 15:20:39 Added --disable* flag
355 ui::ScopedLayerAnimationSettings animation_settings(
356 text_filter_widget_->GetNativeWindow()->layer()->GetAnimator());
357 animation_settings.SetPreemptionStrategy(
358 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
359 animation_settings.SetTweenType(showing_selection_widget_ ?
360 gfx::Tween::FAST_OUT_LINEAR_IN : gfx::Tween::LINEAR_OUT_SLOW_IN);
361 size_t root_window_width = Shell::GetPrimaryRootWindow()->bounds().width();
362 text_filter_widget_->SetBounds(
363 gfx::Rect(root_window_width / 4, 0,root_window_width / 2,
364 showing_selection_widget_ ? 0 : 50));
flackr 2014/06/26 17:33:07 To do this animation on the compositor this should
Nina 2014/06/27 15:20:39 Done!
365 showing_selection_widget_ = !showing_selection_widget_;
366 }
367 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin();
368 iter != grid_list_.end(); iter++) {
369 (*iter)->FilterItems(new_contents);
370 }
371 }
372
320 void WindowSelector::PositionWindows(bool animate) { 373 void WindowSelector::PositionWindows(bool animate) {
321 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin(); 374 for (ScopedVector<WindowGrid>::iterator iter = grid_list_.begin();
322 iter != grid_list_.end(); iter++) { 375 iter != grid_list_.end(); iter++) {
323 (*iter)->PositionWindows(animate); 376 (*iter)->PositionWindows(animate);
324 } 377 }
325 } 378 }
326 379
327 void WindowSelector::HideAndTrackNonOverviewWindows() { 380 void WindowSelector::HideAndTrackNonOverviewWindows() {
328 // Add the windows to hidden_windows first so that if any are destroyed 381 // Add the windows to hidden_windows first so that if any are destroyed
329 // while hiding them they are tracked. 382 // 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 439 // root window, identify it and call Move() on it to initialize the
387 // selection widget. 440 // selection widget.
388 // TODO(nsatragno): If there are more than two monitors, move between grids 441 // TODO(nsatragno): If there are more than two monitors, move between grids
389 // in the requested direction. 442 // in the requested direction.
390 selected_grid_index_ = (selected_grid_index_ + 1) % grid_list_.size(); 443 selected_grid_index_ = (selected_grid_index_ + 1) % grid_list_.size();
391 grid_list_[selected_grid_index_]->Move(direction); 444 grid_list_[selected_grid_index_]->Move(direction);
392 } 445 }
393 } 446 }
394 447
395 } // namespace ash 448 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698