OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ui/views/focus/focus_manager.h" | 5 #include "ui/views/focus/focus_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 namespace views { | 23 namespace views { |
24 | 24 |
25 bool FocusManager::shortcut_handling_suspended_ = false; | 25 bool FocusManager::shortcut_handling_suspended_ = false; |
26 | 26 |
27 FocusManager::FocusManager(Widget* widget, FocusManagerDelegate* delegate) | 27 FocusManager::FocusManager(Widget* widget, FocusManagerDelegate* delegate) |
28 : widget_(widget), | 28 : widget_(widget), |
29 delegate_(delegate), | 29 delegate_(delegate), |
30 focused_view_(NULL), | 30 focused_view_(NULL), |
31 accelerator_manager_(new ui::AcceleratorManager), | 31 accelerator_manager_(new ui::AcceleratorManager), |
32 focus_change_reason_(kReasonDirectFocusChange), | 32 focus_change_reason_(kReasonDirectFocusChange), |
33 #if defined(USE_X11) | |
34 should_handle_menu_key_release_(false), | |
35 #endif | |
36 is_changing_focus_(false) { | 33 is_changing_focus_(false) { |
37 DCHECK(widget_); | 34 DCHECK(widget_); |
38 stored_focused_view_storage_id_ = | 35 stored_focused_view_storage_id_ = |
39 ViewStorage::GetInstance()->CreateStorageID(); | 36 ViewStorage::GetInstance()->CreateStorageID(); |
40 } | 37 } |
41 | 38 |
42 FocusManager::~FocusManager() { | 39 FocusManager::~FocusManager() { |
43 } | 40 } |
44 | 41 |
45 bool FocusManager::OnKeyEvent(const ui::KeyEvent& event) { | 42 bool FocusManager::OnKeyEvent(const ui::KeyEvent& event) { |
46 const int key_code = event.key_code(); | 43 const int key_code = event.key_code(); |
47 | 44 |
48 #if defined(USE_X11) | |
49 // TODO(ben): beng believes that this should be done in | |
50 // RootWindowHosLinux for aura/linux. | |
51 | |
52 // Always reset |should_handle_menu_key_release_| unless we are handling a | |
53 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only | |
54 // be activated when handling a VKEY_MENU key release event which is preceded | |
55 // by an un-handled VKEY_MENU key press event. | |
56 if (key_code != ui::VKEY_MENU || event.type() != ui::ET_KEY_RELEASED) | |
57 should_handle_menu_key_release_ = false; | |
58 | |
59 if (event.type() == ui::ET_KEY_PRESSED) { | |
60 // VKEY_MENU is triggered by key release event. | |
61 // FocusManager::OnKeyEvent() returns false when the key has been consumed. | |
62 if ((key_code == ui::VKEY_MENU) && | |
63 (event.flags() & ~ui::EF_ALT_DOWN) == 0) { | |
64 should_handle_menu_key_release_ = true; | |
65 return false; | |
66 } | |
67 // Pass through to the rest of OnKeyEvent. | |
68 } else if (key_code == ui::VKEY_MENU && should_handle_menu_key_release_ && | |
69 (event.flags() & ~ui::EF_ALT_DOWN) == 0) { | |
70 // Trigger VKEY_MENU when only this key is pressed and released, and both | |
71 // press and release events are not handled by others. | |
72 ui::Accelerator accelerator(ui::VKEY_MENU, ui::EF_NONE); | |
73 return ProcessAccelerator(accelerator); | |
74 } else if (event.type() != ui::ET_KEY_RELEASED) { | |
75 return false; | |
76 } | |
77 #else | |
78 if (event.type() != ui::ET_KEY_PRESSED && event.type() != ui::ET_KEY_RELEASED) | 45 if (event.type() != ui::ET_KEY_PRESSED && event.type() != ui::ET_KEY_RELEASED) |
79 return false; | 46 return false; |
80 #endif | |
81 | 47 |
82 if (shortcut_handling_suspended()) | 48 if (shortcut_handling_suspended()) |
83 return true; | 49 return true; |
84 | 50 |
85 int modifiers = ui::EF_NONE; | 51 int modifiers = ui::EF_NONE; |
86 if (event.IsShiftDown()) | 52 if (event.IsShiftDown()) |
87 modifiers |= ui::EF_SHIFT_DOWN; | 53 modifiers |= ui::EF_SHIFT_DOWN; |
88 if (event.IsControlDown()) | 54 if (event.IsControlDown()) |
89 modifiers |= ui::EF_CONTROL_DOWN; | 55 modifiers |= ui::EF_CONTROL_DOWN; |
90 if (event.IsAltDown()) | 56 if (event.IsAltDown()) |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 FOR_EACH_OBSERVER(FocusChangeListener, focus_change_listeners_, | 267 FOR_EACH_OBSERVER(FocusChangeListener, focus_change_listeners_, |
302 OnDidChangeFocus(old_focused_view, focused_view_)); | 268 OnDidChangeFocus(old_focused_view, focused_view_)); |
303 } | 269 } |
304 | 270 |
305 void FocusManager::ClearFocus() { | 271 void FocusManager::ClearFocus() { |
306 SetFocusedView(NULL); | 272 SetFocusedView(NULL); |
307 ClearNativeFocus(); | 273 ClearNativeFocus(); |
308 } | 274 } |
309 | 275 |
310 void FocusManager::StoreFocusedView() { | 276 void FocusManager::StoreFocusedView() { |
311 #if defined(USE_X11) | |
312 // Forget menu key state when the window lost focus. | |
313 should_handle_menu_key_release_ = false; | |
314 #endif | |
315 ViewStorage* view_storage = ViewStorage::GetInstance(); | 277 ViewStorage* view_storage = ViewStorage::GetInstance(); |
316 if (!view_storage) { | 278 if (!view_storage) { |
317 // This should never happen but bug 981648 seems to indicate it could. | 279 // This should never happen but bug 981648 seems to indicate it could. |
318 NOTREACHED(); | 280 NOTREACHED(); |
319 return; | 281 return; |
320 } | 282 } |
321 | 283 |
322 // TODO(jcivelli): when a TabContents containing a popup is closed, the focus | 284 // TODO(jcivelli): when a TabContents containing a popup is closed, the focus |
323 // is stored twice causing an assert. We should find a better alternative than | 285 // is stored twice causing an assert. We should find a better alternative than |
324 // removing the view from the storage explicitly. | 286 // removing the view from the storage explicitly. |
(...skipping 13 matching lines...) Expand all Loading... |
338 // is not changing due to a user-initiated event. | 300 // is not changing due to a user-initiated event. |
339 AutoNativeNotificationDisabler local_notification_disabler; | 301 AutoNativeNotificationDisabler local_notification_disabler; |
340 ClearFocus(); | 302 ClearFocus(); |
341 } | 303 } |
342 | 304 |
343 if (v) | 305 if (v) |
344 v->SchedulePaint(); // Remove focus border. | 306 v->SchedulePaint(); // Remove focus border. |
345 } | 307 } |
346 | 308 |
347 void FocusManager::RestoreFocusedView() { | 309 void FocusManager::RestoreFocusedView() { |
348 #if defined(USE_X11) | |
349 DCHECK(!should_handle_menu_key_release_); | |
350 #endif | |
351 ViewStorage* view_storage = ViewStorage::GetInstance(); | 310 ViewStorage* view_storage = ViewStorage::GetInstance(); |
352 if (!view_storage) { | 311 if (!view_storage) { |
353 // This should never happen but bug 981648 seems to indicate it could. | 312 // This should never happen but bug 981648 seems to indicate it could. |
354 NOTREACHED(); | 313 NOTREACHED(); |
355 return; | 314 return; |
356 } | 315 } |
357 | 316 |
358 View* view = view_storage->RetrieveView(stored_focused_view_storage_id_); | 317 View* view = view_storage->RetrieveView(stored_focused_view_storage_id_); |
359 if (view) { | 318 if (view) { |
360 if (ContainsView(view)) { | 319 if (ContainsView(view)) { |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 } | 396 } |
438 | 397 |
439 bool FocusManager::ProcessAccelerator(const ui::Accelerator& accelerator) { | 398 bool FocusManager::ProcessAccelerator(const ui::Accelerator& accelerator) { |
440 if (accelerator_manager_->Process(accelerator)) | 399 if (accelerator_manager_->Process(accelerator)) |
441 return true; | 400 return true; |
442 if (delegate_.get()) | 401 if (delegate_.get()) |
443 return delegate_->ProcessAccelerator(accelerator); | 402 return delegate_->ProcessAccelerator(accelerator); |
444 return false; | 403 return false; |
445 } | 404 } |
446 | 405 |
447 void FocusManager::MaybeResetMenuKeyState(const ui::KeyEvent& key) { | |
448 #if defined(USE_X11) | |
449 // Always reset |should_handle_menu_key_release_| unless we are handling a | |
450 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only | |
451 // be activated when handling a VKEY_MENU key release event which is preceded | |
452 // by an unhandled VKEY_MENU key press event. See also HandleKeyboardEvent(). | |
453 if (key.key_code() != ui::VKEY_MENU || key.type() != ui::ET_KEY_RELEASED) | |
454 should_handle_menu_key_release_ = false; | |
455 #endif | |
456 } | |
457 | |
458 ui::AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator( | 406 ui::AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator( |
459 const ui::Accelerator& accelerator) const { | 407 const ui::Accelerator& accelerator) const { |
460 ui::AcceleratorTarget* target = | 408 ui::AcceleratorTarget* target = |
461 accelerator_manager_->GetCurrentTarget(accelerator); | 409 accelerator_manager_->GetCurrentTarget(accelerator); |
462 if (!target && delegate_.get()) | 410 if (!target && delegate_.get()) |
463 target = delegate_->GetCurrentTargetForAccelerator(accelerator); | 411 target = delegate_->GetCurrentTargetForAccelerator(accelerator); |
464 return target; | 412 return target; |
465 } | 413 } |
466 | 414 |
467 bool FocusManager::HasPriorityHandler( | 415 bool FocusManager::HasPriorityHandler( |
(...skipping 17 matching lines...) Expand all Loading... |
485 | 433 |
486 void FocusManager::AddFocusChangeListener(FocusChangeListener* listener) { | 434 void FocusManager::AddFocusChangeListener(FocusChangeListener* listener) { |
487 focus_change_listeners_.AddObserver(listener); | 435 focus_change_listeners_.AddObserver(listener); |
488 } | 436 } |
489 | 437 |
490 void FocusManager::RemoveFocusChangeListener(FocusChangeListener* listener) { | 438 void FocusManager::RemoveFocusChangeListener(FocusChangeListener* listener) { |
491 focus_change_listeners_.RemoveObserver(listener); | 439 focus_change_listeners_.RemoveObserver(listener); |
492 } | 440 } |
493 | 441 |
494 } // namespace views | 442 } // namespace views |
OLD | NEW |