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

Side by Side Diff: ui/views/focus/focus_manager.cc

Issue 8907029: AURA/X11: Handle VKEY_MENU accelerator on content area (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: sync Created 8 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « ui/views/focus/focus_manager.h ('k') | ui/views/widget/native_widget_aura.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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"
11 #include "build/build_config.h" 11 #include "build/build_config.h"
12 #include "ui/base/accelerators/accelerator.h" 12 #include "ui/base/accelerators/accelerator.h"
13 #include "ui/base/accelerators/accelerator_manager.h" 13 #include "ui/base/accelerators/accelerator_manager.h"
14 #include "ui/base/keycodes/keyboard_codes.h" 14 #include "ui/base/keycodes/keyboard_codes.h"
15 #include "ui/views/focus/focus_search.h" 15 #include "ui/views/focus/focus_search.h"
16 #include "ui/views/focus/view_storage.h" 16 #include "ui/views/focus/view_storage.h"
17 #include "ui/views/focus/widget_focus_manager.h" 17 #include "ui/views/focus/widget_focus_manager.h"
18 #include "ui/views/view.h" 18 #include "ui/views/view.h"
19 #include "ui/views/widget/root_view.h" 19 #include "ui/views/widget/root_view.h"
20 #include "ui/views/widget/widget.h" 20 #include "ui/views/widget/widget.h"
21 21
22 namespace views { 22 namespace views {
23 23
24 FocusManager::FocusManager(Widget* widget) 24 FocusManager::FocusManager(Widget* widget)
25 : widget_(widget), 25 : widget_(widget),
26 focused_view_(NULL), 26 focused_view_(NULL),
27 accelerator_manager_(new ui::AcceleratorManager), 27 accelerator_manager_(new ui::AcceleratorManager),
28 focus_change_reason_(kReasonDirectFocusChange), 28 focus_change_reason_(kReasonDirectFocusChange),
29 #if defined(USE_X11)
30 should_handle_menu_key_release_(false),
31 #endif
29 is_changing_focus_(false) { 32 is_changing_focus_(false) {
30 DCHECK(widget_); 33 DCHECK(widget_);
31 stored_focused_view_storage_id_ = 34 stored_focused_view_storage_id_ =
32 ViewStorage::GetInstance()->CreateStorageID(); 35 ViewStorage::GetInstance()->CreateStorageID();
33 } 36 }
34 37
35 FocusManager::~FocusManager() { 38 FocusManager::~FocusManager() {
36 } 39 }
37 40
38 bool FocusManager::OnKeyEvent(const KeyEvent& event) { 41 bool FocusManager::OnKeyEvent(const KeyEvent& event) {
42 const int key_code = event.key_code();
43
44 #if defined(USE_X11)
45 // TODO(ben): beng believes that this should be done in
46 // RootWindowHosLinux for aura/linux.
47
48 // Always reset |should_handle_menu_key_release_| unless we are handling a
49 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only
50 // be activated when handling a VKEY_MENU key release event which is preceded
51 // by an un-handled VKEY_MENU key press event.
52 if (key_code != ui::VKEY_MENU || event.type() != ui::ET_KEY_RELEASED)
53 should_handle_menu_key_release_ = false;
54
55 if (event.type() == ui::ET_KEY_PRESSED) {
56 // VKEY_MENU is triggered by key release event.
57 // FocusManager::OnKeyEvent() returns false when the key has been consumed.
58 if (key_code == ui::VKEY_MENU) {
59 should_handle_menu_key_release_ = true;
60 return false;
61 }
62 // Pass through to the reset of OnKeyEvent.
63 } else if (key_code == ui::VKEY_MENU && should_handle_menu_key_release_ &&
64 (event.flags() & ~ui::EF_ALT_DOWN) == 0) {
65 // Trigger VKEY_MENU when only this key is pressed and released, and both
66 // press and release events are not handled by others.
67 ui::Accelerator accelerator(ui::VKEY_MENU, false, false, false);
68 return ProcessAccelerator(accelerator);
69 } else {
70 return false;
71 }
72 #else
73 if (event.type() != ui::ET_KEY_PRESSED)
74 return false;
75 #endif
76
39 #if defined(OS_WIN) 77 #if defined(OS_WIN)
40 // If the focused view wants to process the key event as is, let it be. 78 // If the focused view wants to process the key event as is, let it be.
41 // On Linux we always dispatch key events to the focused view first, so 79 // On Linux we always dispatch key events to the focused view first, so
42 // we should not do this check here. See also NativeWidgetGtk::OnKeyEvent(). 80 // we should not do this check here. See also NativeWidgetGtk::OnKeyEvent().
43 if (focused_view_ && focused_view_->SkipDefaultKeyEventProcessing(event)) 81 if (focused_view_ && focused_view_->SkipDefaultKeyEventProcessing(event))
44 return true; 82 return true;
45 #endif 83 #endif
46 84
47 // Intercept Tab related messages for focus traversal. 85 // Intercept Tab related messages for focus traversal.
48 // Note that we don't do focus traversal if the root window is not part of the 86 // Note that we don't do focus traversal if the root window is not part of the
49 // active window hierarchy as this would mean we have no focused view and 87 // active window hierarchy as this would mean we have no focused view and
50 // would focus the first focusable view. 88 // would focus the first focusable view.
51 #if defined(OS_WIN) && !defined(USE_AURA) 89 #if defined(OS_WIN) && !defined(USE_AURA)
52 HWND top_window = widget_->GetNativeView(); 90 HWND top_window = widget_->GetNativeView();
53 HWND active_window = ::GetActiveWindow(); 91 HWND active_window = ::GetActiveWindow();
54 if ((active_window == top_window || ::IsChild(active_window, top_window)) && 92 if ((active_window == top_window || ::IsChild(active_window, top_window)) &&
55 IsTabTraversalKeyEvent(event)) { 93 IsTabTraversalKeyEvent(event)) {
56 AdvanceFocus(event.IsShiftDown()); 94 AdvanceFocus(event.IsShiftDown());
57 return false; 95 return false;
58 } 96 }
59 #else 97 #else
60 if (IsTabTraversalKeyEvent(event)) { 98 if (IsTabTraversalKeyEvent(event)) {
61 AdvanceFocus(event.IsShiftDown()); 99 AdvanceFocus(event.IsShiftDown());
62 return false; 100 return false;
63 } 101 }
64 #endif 102 #endif
65 103
66 // Intercept arrow key messages to switch between grouped views. 104 // Intercept arrow key messages to switch between grouped views.
67 ui::KeyboardCode key_code = event.key_code();
68 if (focused_view_ && focused_view_->GetGroup() != -1 && 105 if (focused_view_ && focused_view_->GetGroup() != -1 &&
69 (key_code == ui::VKEY_UP || key_code == ui::VKEY_DOWN || 106 (key_code == ui::VKEY_UP || key_code == ui::VKEY_DOWN ||
70 key_code == ui::VKEY_LEFT || key_code == ui::VKEY_RIGHT)) { 107 key_code == ui::VKEY_LEFT || key_code == ui::VKEY_RIGHT)) {
71 bool next = (key_code == ui::VKEY_RIGHT || key_code == ui::VKEY_DOWN); 108 bool next = (key_code == ui::VKEY_RIGHT || key_code == ui::VKEY_DOWN);
72 View::Views views; 109 View::Views views;
73 focused_view_->parent()->GetViewsInGroup(focused_view_->GetGroup(), &views); 110 focused_view_->parent()->GetViewsInGroup(focused_view_->GetGroup(), &views);
74 View::Views::const_iterator i( 111 View::Views::const_iterator i(
75 std::find(views.begin(), views.end(), focused_view_)); 112 std::find(views.begin(), views.end(), focused_view_));
76 DCHECK(i != views.end()); 113 DCHECK(i != views.end());
77 int index = static_cast<int>(i - views.begin()); 114 int index = static_cast<int>(i - views.begin());
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 FOR_EACH_OBSERVER(FocusChangeListener, focus_change_listeners_, 284 FOR_EACH_OBSERVER(FocusChangeListener, focus_change_listeners_,
248 OnDidChangeFocus(old_focused_view, focused_view_)); 285 OnDidChangeFocus(old_focused_view, focused_view_));
249 } 286 }
250 287
251 void FocusManager::ClearFocus() { 288 void FocusManager::ClearFocus() {
252 SetFocusedView(NULL); 289 SetFocusedView(NULL);
253 ClearNativeFocus(); 290 ClearNativeFocus();
254 } 291 }
255 292
256 void FocusManager::StoreFocusedView() { 293 void FocusManager::StoreFocusedView() {
294 #if defined(USE_X11)
295 // Forget menu key state when the window lost focus.
296 should_handle_menu_key_release_ = false;
297 #endif
257 ViewStorage* view_storage = ViewStorage::GetInstance(); 298 ViewStorage* view_storage = ViewStorage::GetInstance();
258 if (!view_storage) { 299 if (!view_storage) {
259 // This should never happen but bug 981648 seems to indicate it could. 300 // This should never happen but bug 981648 seems to indicate it could.
260 NOTREACHED(); 301 NOTREACHED();
261 return; 302 return;
262 } 303 }
263 304
264 // TODO (jcampan): when a TabContents containing a popup is closed, the focus 305 // TODO (jcampan): when a TabContents containing a popup is closed, the focus
265 // is stored twice causing an assert. We should find a better alternative than 306 // is stored twice causing an assert. We should find a better alternative than
266 // removing the view from the storage explicitly. 307 // removing the view from the storage explicitly.
(...skipping 13 matching lines...) Expand all
280 // is not changing due to a user-initiated event. 321 // is not changing due to a user-initiated event.
281 AutoNativeNotificationDisabler local_notification_disabler; 322 AutoNativeNotificationDisabler local_notification_disabler;
282 ClearFocus(); 323 ClearFocus();
283 } 324 }
284 325
285 if (v) 326 if (v)
286 v->SchedulePaint(); // Remove focus border. 327 v->SchedulePaint(); // Remove focus border.
287 } 328 }
288 329
289 void FocusManager::RestoreFocusedView() { 330 void FocusManager::RestoreFocusedView() {
331 #if defined(USE_X11)
332 DCHECK(!should_handle_menu_key_release_);
333 #endif
290 ViewStorage* view_storage = ViewStorage::GetInstance(); 334 ViewStorage* view_storage = ViewStorage::GetInstance();
291 if (!view_storage) { 335 if (!view_storage) {
292 // This should never happen but bug 981648 seems to indicate it could. 336 // This should never happen but bug 981648 seems to indicate it could.
293 NOTREACHED(); 337 NOTREACHED();
294 return; 338 return;
295 } 339 }
296 340
297 View* view = view_storage->RetrieveView(stored_focused_view_storage_id_); 341 View* view = view_storage->RetrieveView(stored_focused_view_storage_id_);
298 if (view) { 342 if (view) {
299 if (ContainsView(view)) { 343 if (ContainsView(view)) {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 } 415 }
372 416
373 void FocusManager::UnregisterAccelerators(ui::AcceleratorTarget* target) { 417 void FocusManager::UnregisterAccelerators(ui::AcceleratorTarget* target) {
374 accelerator_manager_->UnregisterAll(target); 418 accelerator_manager_->UnregisterAll(target);
375 } 419 }
376 420
377 bool FocusManager::ProcessAccelerator(const ui::Accelerator& accelerator) { 421 bool FocusManager::ProcessAccelerator(const ui::Accelerator& accelerator) {
378 return accelerator_manager_->Process(accelerator); 422 return accelerator_manager_->Process(accelerator);
379 } 423 }
380 424
425 void FocusManager::MaybeResetMenuKeyState(const KeyEvent& key) {
426 #if defined(USE_X11)
427 // Always reset |should_handle_menu_key_release_| unless we are handling a
428 // VKEY_MENU key release event. It ensures that VKEY_MENU accelerator can only
429 // be activated when handling a VKEY_MENU key release event which is preceded
430 // by an unhandled VKEY_MENU key press event. See also HandleKeyboardEvent().
431 if (key.key_code() != ui::VKEY_MENU || key.type() != ui::ET_KEY_RELEASED)
432 should_handle_menu_key_release_ = false;
433 #endif
434 }
435
436 #if defined(TOOLKIT_USES_GTK)
437 void FocusManager::ResetMenuKeyState() {
438 should_handle_menu_key_release_ = false;
439 }
440 #endif
441
381 ui::AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator( 442 ui::AcceleratorTarget* FocusManager::GetCurrentTargetForAccelerator(
382 const ui::Accelerator& accelerator) const { 443 const ui::Accelerator& accelerator) const {
383 return accelerator_manager_->GetCurrentTarget(accelerator); 444 return accelerator_manager_->GetCurrentTarget(accelerator);
384 } 445 }
385 446
386 // static 447 // static
387 bool FocusManager::IsTabTraversalKeyEvent(const KeyEvent& key_event) { 448 bool FocusManager::IsTabTraversalKeyEvent(const KeyEvent& key_event) {
388 return key_event.key_code() == ui::VKEY_TAB && !key_event.IsControlDown(); 449 return key_event.key_code() == ui::VKEY_TAB && !key_event.IsControlDown();
389 } 450 }
390 451
391 void FocusManager::ViewRemoved(View* removed) { 452 void FocusManager::ViewRemoved(View* removed) {
392 // If the view being removed contains (or is) the focused view, 453 // If the view being removed contains (or is) the focused view,
393 // clear the focus. However, it's not safe to call ClearFocus() 454 // clear the focus. However, it's not safe to call ClearFocus()
394 // (and in turn ClearNativeFocus()) here because ViewRemoved() can 455 // (and in turn ClearNativeFocus()) here because ViewRemoved() can
395 // be called while the top level widget is being destroyed. 456 // be called while the top level widget is being destroyed.
396 if (focused_view_ && removed && removed->Contains(focused_view_)) 457 if (focused_view_ && removed && removed->Contains(focused_view_))
397 SetFocusedView(NULL); 458 SetFocusedView(NULL);
398 } 459 }
399 460
400 void FocusManager::AddFocusChangeListener(FocusChangeListener* listener) { 461 void FocusManager::AddFocusChangeListener(FocusChangeListener* listener) {
401 focus_change_listeners_.AddObserver(listener); 462 focus_change_listeners_.AddObserver(listener);
402 } 463 }
403 464
404 void FocusManager::RemoveFocusChangeListener(FocusChangeListener* listener) { 465 void FocusManager::RemoveFocusChangeListener(FocusChangeListener* listener) {
405 focus_change_listeners_.RemoveObserver(listener); 466 focus_change_listeners_.RemoveObserver(listener);
406 } 467 }
407 468
408 } // namespace views 469 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/focus/focus_manager.h ('k') | ui/views/widget/native_widget_aura.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698