174 lines
6.2 KiB
C++
174 lines
6.2 KiB
C++
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef CEF_LIBCEF_BROWSER_NATIVE_NATIVE_MENU_WIN_H_
|
|
#define CEF_LIBCEF_BROWSER_NATIVE_NATIVE_MENU_WIN_H_
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include "libcef/browser/native/menu_wrapper.h"
|
|
|
|
#include "base/compiler_specific.h"
|
|
#include "base/macros.h"
|
|
#include "base/memory/weak_ptr.h"
|
|
#include "base/observer_list.h"
|
|
#include "base/strings/string16.h"
|
|
|
|
namespace ui {
|
|
class MenuModel;
|
|
}
|
|
|
|
namespace views {
|
|
|
|
// A Windows implementation of MenuWrapper.
|
|
// TODO(beng): rename to MenuWin once the old class is dead.
|
|
class CefNativeMenuWin : public MenuWrapper {
|
|
public:
|
|
// Construct a CefNativeMenuWin, with a model and delegate. If
|
|
// |system_menu_for| is non-NULL, the CefNativeMenuWin wraps the system menu
|
|
// for that window.
|
|
// The caller owns the model and the delegate.
|
|
CefNativeMenuWin(ui::MenuModel* model, HWND system_menu_for);
|
|
~CefNativeMenuWin() override;
|
|
|
|
// Overridden from MenuWrapper:
|
|
void RunMenuAt(const gfx::Point& point, int alignment) override;
|
|
void CancelMenu() override;
|
|
void Rebuild(MenuInsertionDelegateWin* delegate) override;
|
|
void UpdateStates() override;
|
|
HMENU GetNativeMenu() const override;
|
|
MenuAction GetMenuAction() const override;
|
|
void AddMenuListener(MenuListener* listener) override;
|
|
void RemoveMenuListener(MenuListener* listener) override;
|
|
void SetMinimumWidth(int width) override;
|
|
|
|
private:
|
|
// IMPORTANT: Note about indices.
|
|
// Functions in this class deal in two index spaces:
|
|
// 1. menu_index - the index of an item within the actual Windows
|
|
// native menu.
|
|
// 2. model_index - the index of the item within our model.
|
|
// These two are most often but not always the same value! The
|
|
// notable exception is when this object is used to wrap the
|
|
// Windows System Menu. In this instance, the model indices start
|
|
// at 0, but the insertion index into the existing menu is not.
|
|
// It is important to take this into consideration when editing the
|
|
// code in the functions in this class.
|
|
|
|
struct HighlightedMenuItemInfo;
|
|
|
|
// Returns true if the item at the specified index is a separator.
|
|
bool IsSeparatorItemAt(int menu_index) const;
|
|
|
|
// Add items. See note above about indices.
|
|
void AddMenuItemAt(int menu_index, int model_index);
|
|
void AddSeparatorItemAt(int menu_index, int model_index);
|
|
|
|
// Sets the state of the item at the specified index.
|
|
void SetMenuItemState(int menu_index,
|
|
bool enabled,
|
|
bool checked,
|
|
bool is_default);
|
|
|
|
// Sets the label of the item at the specified index.
|
|
void SetMenuItemLabel(int menu_index,
|
|
int model_index,
|
|
const base::string16& label);
|
|
|
|
// Updates the local data structure with the correctly formatted version of
|
|
// |label| at the specified model_index, and adds string data to |mii| if
|
|
// the menu is not owner-draw. That's a mouthful. This function exists because
|
|
// of the peculiarities of the Windows menu API.
|
|
void UpdateMenuItemInfoForString(MENUITEMINFO* mii,
|
|
int model_index,
|
|
const base::string16& label);
|
|
|
|
// Returns the alignment flags to be passed to TrackPopupMenuEx, based on the
|
|
// supplied alignment and the UI text direction.
|
|
UINT GetAlignmentFlags(int alignment) const;
|
|
|
|
// Resets the native menu stored in |menu_| by destroying any old menu then
|
|
// creating a new empty one.
|
|
void ResetNativeMenu();
|
|
|
|
// Creates the host window that receives notifications from the menu.
|
|
void CreateHostWindow();
|
|
|
|
// Callback from task to notify menu it was selected.
|
|
void DelayedSelect();
|
|
|
|
// Given a menu that's currently popped-up, find the currently highlighted
|
|
// item. Returns true if a highlighted item was found.
|
|
static bool GetHighlightedMenuItemInfo(HMENU menu,
|
|
HighlightedMenuItemInfo* info);
|
|
|
|
// Hook to receive keyboard events while the menu is open.
|
|
static LRESULT CALLBACK MenuMessageHook(int n_code,
|
|
WPARAM w_param,
|
|
LPARAM l_param);
|
|
|
|
// Our attached model and delegate.
|
|
ui::MenuModel* model_;
|
|
|
|
HMENU menu_;
|
|
|
|
// True if the contents of menu items in this menu are drawn by the menu host
|
|
// window, rather than Windows.
|
|
bool owner_draw_;
|
|
|
|
// An object that collects all of the data associated with an individual menu
|
|
// item.
|
|
struct ItemData;
|
|
typedef std::vector<std::unique_ptr<ItemData>> ItemDataList;
|
|
ItemDataList items_;
|
|
|
|
// The window that receives notifications from the menu.
|
|
class MenuHostWindow;
|
|
friend MenuHostWindow;
|
|
std::unique_ptr<MenuHostWindow> host_window_;
|
|
|
|
// The HWND this menu is the system menu for, or NULL if the menu is not a
|
|
// system menu.
|
|
HWND system_menu_for_;
|
|
|
|
// The index of the first item in the model in the menu.
|
|
int first_item_index_;
|
|
|
|
// The action that took place during the call to RunMenuAt.
|
|
MenuAction menu_action_;
|
|
|
|
// A list of listeners to call when the menu opens.
|
|
base::ObserverList<MenuListener> listeners_;
|
|
|
|
// Keep track of whether the listeners have already been called at least
|
|
// once.
|
|
bool listeners_called_;
|
|
|
|
// See comment in MenuMessageHook for details on these.
|
|
CefNativeMenuWin* menu_to_select_;
|
|
int position_to_select_;
|
|
|
|
// If we're a submenu, this is our parent.
|
|
CefNativeMenuWin* parent_;
|
|
|
|
// If non-null the destructor sets this to true. This is set to non-null while
|
|
// the menu is showing. It is used to detect if the menu was deleted while
|
|
// running.
|
|
bool* destroyed_flag_;
|
|
|
|
base::WeakPtrFactory<CefNativeMenuWin> menu_to_select_factory_;
|
|
|
|
// Ugly: a static pointer to the instance of this class that currently
|
|
// has a menu open, because our hook function that receives keyboard
|
|
// events doesn't have a mechanism to get a user data pointer.
|
|
static CefNativeMenuWin* open_native_menu_win_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(CefNativeMenuWin);
|
|
};
|
|
|
|
} // namespace views
|
|
|
|
#endif // CEF_LIBCEF_BROWSER_NATIVE_NATIVE_MENU_WIN_H_
|