15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef UI_VIEWS_CONTROLS_MENU_NATIVE_MENU_WIN_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UI_VIEWS_CONTROLS_MENU_NATIVE_MENU_WIN_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/observer_list.h" 155e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string16.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_wrapper.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/views_export.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MenuModel; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace views { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A Windows implementation of MenuWrapper. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(beng): rename to MenuWin once the old class is dead. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VIEWS_EXPORT NativeMenuWin : public MenuWrapper { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Construct a NativeMenuWin, with a model and delegate. If |system_menu_for| 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is non-NULL, the NativeMenuWin wraps the system menu for that window. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The caller owns the model and the delegate. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NativeMenuWin(ui::MenuModel* model, HWND system_menu_for); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~NativeMenuWin(); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Overridden from MenuWrapper: 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void RunMenuAt(const gfx::Point& point, int alignment) OVERRIDE; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void CancelMenu() OVERRIDE; 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void Rebuild(MenuInsertionDelegateWin* delegate) OVERRIDE; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void UpdateStates() OVERRIDE; 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual HMENU GetNativeMenu() const OVERRIDE; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual MenuAction GetMenuAction() const OVERRIDE; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void AddMenuListener(MenuListener* listener) OVERRIDE; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void RemoveMenuListener(MenuListener* listener) OVERRIDE; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void SetMinimumWidth(int width) OVERRIDE; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IMPORTANT: Note about indices. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Functions in this class deal in two index spaces: 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. menu_index - the index of an item within the actual Windows 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // native menu. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. model_index - the index of the item within our model. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These two are most often but not always the same value! The 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // notable exception is when this object is used to wrap the 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Windows System Menu. In this instance, the model indices start 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // at 0, but the insertion index into the existing menu is not. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It is important to take this into consideration when editing the 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // code in the functions in this class. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct HighlightedMenuItemInfo; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if the item at the specified index is a separator. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsSeparatorItemAt(int menu_index) const; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add items. See note above about indices. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddMenuItemAt(int menu_index, int model_index); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddSeparatorItemAt(int menu_index, int model_index); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the state of the item at the specified index. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetMenuItemState(int menu_index, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool enabled, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool checked, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_default); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets the label of the item at the specified index. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetMenuItemLabel(int menu_index, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int model_index, 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16& label); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Updates the local data structure with the correctly formatted version of 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |label| at the specified model_index, and adds string data to |mii| if 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the menu is not owner-draw. That's a mouthful. This function exists because 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the peculiarities of the Windows menu API. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void UpdateMenuItemInfoForString(MENUITEMINFO* mii, 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int model_index, 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16& label); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the alignment flags to be passed to TrackPopupMenuEx, based on the 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // supplied alignment and the UI text direction. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UINT GetAlignmentFlags(int alignment) const; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Resets the native menu stored in |menu_| by destroying any old menu then 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // creating a new empty one. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ResetNativeMenu(); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates the host window that receives notifications from the menu. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CreateHostWindow(); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Callback from task to notify menu it was selected. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DelayedSelect(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Given a menu that's currently popped-up, find the currently highlighted 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // item. Returns true if a highlighted item was found. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool GetHighlightedMenuItemInfo(HMENU menu, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HighlightedMenuItemInfo* info); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hook to receive keyboard events while the menu is open. 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static LRESULT CALLBACK MenuMessageHook( 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int n_code, WPARAM w_param, LPARAM l_param); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our attached model and delegate. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::MenuModel* model_; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HMENU menu_; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // True if the contents of menu items in this menu are drawn by the menu host 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // window, rather than Windows. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool owner_draw_; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An object that collects all of the data associated with an individual menu 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // item. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct ItemData; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<ItemData*> items_; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The window that receives notifications from the menu. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class MenuHostWindow; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend MenuHostWindow; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<MenuHostWindow> host_window_; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The HWND this menu is the system menu for, or NULL if the menu is not a 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // system menu. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HWND system_menu_for_; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The index of the first item in the model in the menu. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int first_item_index_; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The action that took place during the call to RunMenuAt. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuAction menu_action_; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A list of listeners to call when the menu opens. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ObserverList<MenuListener> listeners_; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Keep track of whether the listeners have already been called at least 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // once. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool listeners_called_; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See comment in MenuMessageHook for details on these. 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NativeMenuWin* menu_to_select_; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int position_to_select_; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WeakPtrFactory<NativeMenuWin> menu_to_select_factory_; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're a submenu, this is our parent. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NativeMenuWin* parent_; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If non-null the destructor sets this to true. This is set to non-null while 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the menu is showing. It is used to detect if the menu was deleted while 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // running. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool* destroyed_flag_; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ugly: a static pointer to the instance of this class that currently 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // has a menu open, because our hook function that receives keyboard 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // events doesn't have a mechanism to get a user data pointer. 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static NativeMenuWin* open_native_menu_win_; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(NativeMenuWin); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace views 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // UI_VIEWS_CONTROLS_MENU_NATIVE_MENU_WIN_H_ 170