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_message_pump_dispatcher_win.h" 6 7 #include <windowsx.h> 8 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/controls/menu/menu_item_view.h" 14 15 namespace views { 16 namespace internal { 17 18 MenuMessagePumpDispatcher::MenuMessagePumpDispatcher(MenuController* controller) 19 : menu_controller_(controller) {} 20 21 MenuMessagePumpDispatcher::~MenuMessagePumpDispatcher() {} 22 23 uint32_t MenuMessagePumpDispatcher::Dispatch(const MSG& msg) { 24 DCHECK(menu_controller_->IsBlockingRun()); 25 26 bool should_quit = false; 27 bool should_perform_default = true; 28 if (menu_controller_->exit_type() == MenuController::EXIT_ALL || 29 menu_controller_->exit_type() == MenuController::EXIT_DESTROYED) { 30 should_quit = true; 31 } else { 32 // NOTE: we don't get WM_ACTIVATE or anything else interesting in here. 33 switch (msg.message) { 34 case WM_CONTEXTMENU: { 35 MenuItemView* item = menu_controller_->pending_state_.item; 36 if (item && item->GetRootMenuItem() != item) { 37 gfx::Point screen_loc(0, item->height()); 38 View::ConvertPointToScreen(item, &screen_loc); 39 ui::MenuSourceType source_type = ui::MENU_SOURCE_MOUSE; 40 if (GET_X_LPARAM(msg.lParam) == -1 && GET_Y_LPARAM(msg.lParam) == -1) 41 source_type = ui::MENU_SOURCE_KEYBOARD; 42 item->GetDelegate()->ShowContextMenu( 43 item, item->GetCommand(), screen_loc, source_type); 44 } 45 should_quit = false; 46 should_perform_default = false; 47 break; 48 } 49 50 // NOTE: focus wasn't changed when the menu was shown. As such, don't 51 // dispatch key events otherwise the focused window will get the events. 52 case WM_KEYDOWN: { 53 bool result = 54 menu_controller_->OnKeyDown(ui::KeyboardCodeFromNative(msg)); 55 TranslateMessage(&msg); 56 should_perform_default = false; 57 should_quit = !result; 58 break; 59 } 60 case WM_CHAR: { 61 should_quit = menu_controller_->SelectByChar( 62 static_cast<base::char16>(msg.wParam)); 63 should_perform_default = false; 64 break; 65 } 66 case WM_KEYUP: 67 case WM_SYSKEYUP: 68 // We may have been shown on a system key, as such don't do anything 69 // here. If another system key is pushed we'll get a WM_SYSKEYDOWN and 70 // close the menu. 71 should_quit = false; 72 should_perform_default = false; 73 break; 74 75 case WM_CANCELMODE: 76 case WM_SYSKEYDOWN: 77 // Exit immediately on system keys. 78 menu_controller_->Cancel(MenuController::EXIT_ALL); 79 should_quit = true; 80 should_perform_default = false; 81 break; 82 83 default: 84 break; 85 } 86 } 87 88 if (should_quit || menu_controller_->exit_type() != MenuController::EXIT_NONE) 89 menu_controller_->TerminateNestedMessageLoop(); 90 return should_perform_default ? POST_DISPATCH_PERFORM_DEFAULT 91 : POST_DISPATCH_NONE; 92 } 93 94 } // namespace internal 95 } // namespace views 96