bool FocusManager::OnKeyEvent(const KeyEvent& event) { // If the focused view wants to process the key event as is, let it be. // On Linux we always dispatch key events to the focused view first, so // we should not do this check here. See also WidgetGtk::OnKeyEvent(). if(focused_view_ && focused_view_->SkipDefaultKeyEventProcessing(event)) { return true; } // Intercept Tab related messages for focus traversal. // Note that we don't do focus traversal if the root window is not part of the // active window hierarchy as this would mean we have no focused view and // would focus the first focusable view. HWND top_window = widget_->GetNativeView(); HWND active_window = ::GetActiveWindow(); if((active_window==top_window || ::IsChild(active_window, top_window)) && IsTabTraversalKeyEvent(event)) { AdvanceFocus(event.IsShiftDown()); return false; } // Intercept arrow key messages to switch between grouped views. KeyboardCode key_code = event.GetKeyCode(); if(focused_view_ && focused_view_->GetGroup()!=-1 && (key_code==VKEY_UP || key_code==VKEY_DOWN || key_code==VKEY_LEFT || key_code==VKEY_RIGHT)) { bool next = (key_code==VKEY_RIGHT || key_code==VKEY_DOWN); std::vector<View*> views; focused_view_->GetParent()->GetViewsWithGroup( focused_view_->GetGroup(), &views); std::vector<View*>::const_iterator iter = std::find(views.begin(), views.end(), focused_view_); DCHECK(iter != views.end()); int index = static_cast<int>(iter - views.begin()); index += next ? 1 : -1; if(index < 0) { index = static_cast<int>(views.size()) - 1; } else if(index >= static_cast<int>(views.size())) { index = 0; } SetFocusedViewWithReason(views[index], kReasonFocusTraversal); return false; } // Process keyboard accelerators. // If the key combination matches an accelerator, the accelerator is // triggered, otherwise the key event is processed as usual. Accelerator accelerator(event.GetKeyCode(), event.IsShiftDown(), event.IsControlDown(), event.IsAltDown()); if(ProcessAccelerator(accelerator)) { // If a shortcut was activated for this keydown message, do not propagate // the event further. return false; } return true; }