1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ui/views/controls/menu/menu_event_dispatcher_linux.h" 6 7 #include "base/memory/scoped_ptr.h" 8 #include "ui/aura/window.h" 9 #include "ui/events/event_utils.h" 10 #include "ui/events/keycodes/keyboard_code_conversion.h" 11 #include "ui/events/keycodes/keyboard_codes.h" 12 #include "ui/views/controls/menu/menu_controller.h" 13 #include "ui/views/widget/widget.h" 14 15 namespace views { 16 namespace internal { 17 18 MenuEventDispatcher::MenuEventDispatcher(MenuController* controller) 19 : menu_controller_(controller) {} 20 21 MenuEventDispatcher::~MenuEventDispatcher() {} 22 23 bool MenuEventDispatcher::CanDispatchEvent(const ui::PlatformEvent& event) { 24 return true; 25 } 26 27 uint32_t MenuEventDispatcher::DispatchEvent(const ui::PlatformEvent& event) { 28 bool should_quit = false; 29 bool should_perform_default = true; 30 bool should_process_event = true; 31 32 // Check if the event should be handled. 33 scoped_ptr<ui::Event> ui_event(ui::EventFromNative(event)); 34 if (ui_event && menu_controller_->owner()) { 35 aura::Window* menu_window = menu_controller_->owner()->GetNativeWindow(); 36 aura::Window* target_window = static_cast<aura::Window*>( 37 static_cast<ui::EventTarget*>(menu_window->GetRootWindow())-> 38 GetEventTargeter()->FindTargetForEvent(menu_window, 39 ui_event.get())); 40 // TODO(flackr): The event shouldn't be handled if target_window is not 41 // menu_window, however the event targeter does not properly target the 42 // open menu. For now, we allow targeters to prevent handling by the menu. 43 if (!target_window) 44 should_process_event = false; 45 } 46 47 if (menu_controller_->exit_type() == MenuController::EXIT_ALL || 48 menu_controller_->exit_type() == MenuController::EXIT_DESTROYED) { 49 should_quit = true; 50 } else if (should_process_event) { 51 switch (ui::EventTypeFromNative(event)) { 52 case ui::ET_KEY_PRESSED: { 53 if (!menu_controller_->OnKeyDown(ui::KeyboardCodeFromNative(event))) { 54 should_quit = true; 55 should_perform_default = false; 56 break; 57 } 58 59 // Do not check mnemonics if the Alt or Ctrl modifiers are pressed. 60 int flags = ui::EventFlagsFromNative(event); 61 if ((flags & (ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)) == 0) { 62 char c = ui::GetCharacterFromKeyCode( 63 ui::KeyboardCodeFromNative(event), flags); 64 if (menu_controller_->SelectByChar(c)) { 65 should_quit = true; 66 should_perform_default = false; 67 break; 68 } 69 } 70 should_quit = false; 71 should_perform_default = false; 72 break; 73 } 74 case ui::ET_KEY_RELEASED: 75 should_quit = false; 76 should_perform_default = false; 77 break; 78 default: 79 break; 80 } 81 } 82 83 if (should_quit || menu_controller_->exit_type() != MenuController::EXIT_NONE) 84 menu_controller_->TerminateNestedMessageLoop(); 85 86 return should_perform_default ? ui::POST_DISPATCH_PERFORM_DEFAULT 87 : ui::POST_DISPATCH_NONE; 88 } 89 90 } // namespace internal 91 } // namespace views 92