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 3 // found in the LICENSE file. 4 5 #ifndef CEF_LIBCEF_BROWSER_NATIVE_NATIVE_MENU_WIN_H_ 6 #define CEF_LIBCEF_BROWSER_NATIVE_NATIVE_MENU_WIN_H_ 7 8 #include <memory> 9 #include <vector> 10 11 #include "libcef/browser/native/menu_wrapper.h" 12 13 #include "base/compiler_specific.h" 14 #include "base/macros.h" 15 #include "base/memory/weak_ptr.h" 16 #include "base/observer_list.h" 17 18 namespace ui { 19 class MenuModel; 20 } 21 22 namespace views { 23 24 // A Windows implementation of MenuWrapper. 25 // TODO(beng): rename to MenuWin once the old class is dead. 26 class CefNativeMenuWin : public MenuWrapper { 27 public: 28 // Construct a CefNativeMenuWin, with a model and delegate. If 29 // |system_menu_for| is non-NULL, the CefNativeMenuWin wraps the system menu 30 // for that window. 31 // The caller owns the model and the delegate. 32 CefNativeMenuWin(ui::MenuModel* model, HWND system_menu_for); 33 ~CefNativeMenuWin() override; 34 35 // Overridden from MenuWrapper: 36 void RunMenuAt(const gfx::Point& point, int alignment) override; 37 void CancelMenu() override; 38 void Rebuild(MenuInsertionDelegateWin* delegate) override; 39 void UpdateStates() override; 40 HMENU GetNativeMenu() const override; 41 MenuAction GetMenuAction() const override; 42 void SetMinimumWidth(int width) override; 43 44 private: 45 // IMPORTANT: Note about indices. 46 // Functions in this class deal in two index spaces: 47 // 1. menu_index - the index of an item within the actual Windows 48 // native menu. 49 // 2. model_index - the index of the item within our model. 50 // These two are most often but not always the same value! The 51 // notable exception is when this object is used to wrap the 52 // Windows System Menu. In this instance, the model indices start 53 // at 0, but the insertion index into the existing menu is not. 54 // It is important to take this into consideration when editing the 55 // code in the functions in this class. 56 57 struct HighlightedMenuItemInfo; 58 59 // Returns true if the item at the specified index is a separator. 60 bool IsSeparatorItemAt(int menu_index) const; 61 62 // Add items. See note above about indices. 63 void AddMenuItemAt(int menu_index, int model_index); 64 void AddSeparatorItemAt(int menu_index, int model_index); 65 66 // Sets the state of the item at the specified index. 67 void SetMenuItemState(int menu_index, 68 bool enabled, 69 bool checked, 70 bool is_default); 71 72 // Sets the label of the item at the specified index. 73 void SetMenuItemLabel(int menu_index, 74 int model_index, 75 const std::wstring& label); 76 77 // Updates the local data structure with the correctly formatted version of 78 // |label| at the specified model_index, and adds string data to |mii| if 79 // the menu is not owner-draw. That's a mouthful. This function exists because 80 // of the peculiarities of the Windows menu API. 81 void UpdateMenuItemInfoForString(MENUITEMINFO* mii, 82 int model_index, 83 const std::wstring& label); 84 85 // Returns the alignment flags to be passed to TrackPopupMenuEx, based on the 86 // supplied alignment and the UI text direction. 87 UINT GetAlignmentFlags(int alignment) const; 88 89 // Resets the native menu stored in |menu_| by destroying any old menu then 90 // creating a new empty one. 91 void ResetNativeMenu(); 92 93 // Creates the host window that receives notifications from the menu. 94 void CreateHostWindow(); 95 96 // Callback from task to notify menu it was selected. 97 void DelayedSelect(); 98 99 // Given a menu that's currently popped-up, find the currently highlighted 100 // item. Returns true if a highlighted item was found. 101 static bool GetHighlightedMenuItemInfo(HMENU menu, 102 HighlightedMenuItemInfo* info); 103 104 // Hook to receive keyboard events while the menu is open. 105 static LRESULT CALLBACK MenuMessageHook(int n_code, 106 WPARAM w_param, 107 LPARAM l_param); 108 109 // Our attached model and delegate. 110 ui::MenuModel* model_; 111 112 HMENU menu_; 113 114 // True if the contents of menu items in this menu are drawn by the menu host 115 // window, rather than Windows. 116 bool owner_draw_; 117 118 // An object that collects all of the data associated with an individual menu 119 // item. 120 struct ItemData; 121 typedef std::vector<std::unique_ptr<ItemData>> ItemDataList; 122 ItemDataList items_; 123 124 // The window that receives notifications from the menu. 125 class MenuHostWindow; 126 friend MenuHostWindow; 127 std::unique_ptr<MenuHostWindow> host_window_; 128 129 // The HWND this menu is the system menu for, or NULL if the menu is not a 130 // system menu. 131 HWND system_menu_for_; 132 133 // The index of the first item in the model in the menu. 134 int first_item_index_; 135 136 // The action that took place during the call to RunMenuAt. 137 MenuAction menu_action_; 138 139 // See comment in MenuMessageHook for details on these. 140 CefNativeMenuWin* menu_to_select_; 141 int position_to_select_; 142 143 // If we're a submenu, this is our parent. 144 CefNativeMenuWin* parent_; 145 146 // If non-null the destructor sets this to true. This is set to non-null while 147 // the menu is showing. It is used to detect if the menu was deleted while 148 // running. 149 bool* destroyed_flag_; 150 151 base::WeakPtrFactory<CefNativeMenuWin> menu_to_select_factory_; 152 153 // Ugly: a static pointer to the instance of this class that currently 154 // has a menu open, because our hook function that receives keyboard 155 // events doesn't have a mechanism to get a user data pointer. 156 static CefNativeMenuWin* open_native_menu_win_; 157 158 DISALLOW_COPY_AND_ASSIGN(CefNativeMenuWin); 159 }; 160 161 } // namespace views 162 163 #endif // CEF_LIBCEF_BROWSER_NATIVE_NATIVE_MENU_WIN_H_ 164