Commit 6eaf11f0 authored by Marshall Greenblatt's avatar Marshall Greenblatt

views: Support top menu switching with mouse and arrow keys (issue #2102)

- cefclient: Add example ViewsMenuBar implementation and show top menu
  by default (specify `--hide-top-menu` to hide it).
parent fbc8b983
...@@ -299,6 +299,8 @@ ...@@ -299,6 +299,8 @@
'tests/cefclient/browser/root_window_win.h', 'tests/cefclient/browser/root_window_win.h',
'tests/cefclient/browser/temp_window_win.cc', 'tests/cefclient/browser/temp_window_win.cc',
'tests/cefclient/browser/temp_window_win.h', 'tests/cefclient/browser/temp_window_win.h',
'tests/cefclient/browser/views_menu_bar.cc',
'tests/cefclient/browser/views_menu_bar.h',
'tests/cefclient/browser/views_window.cc', 'tests/cefclient/browser/views_window.cc',
'tests/cefclient/browser/views_window.h', 'tests/cefclient/browser/views_window.h',
'tests/cefclient/browser/window_test_runner_views.cc', 'tests/cefclient/browser/window_test_runner_views.cc',
...@@ -350,6 +352,8 @@ ...@@ -350,6 +352,8 @@
'tests/cefclient/browser/root_window_views.h', 'tests/cefclient/browser/root_window_views.h',
'tests/cefclient/browser/temp_window_x11.cc', 'tests/cefclient/browser/temp_window_x11.cc',
'tests/cefclient/browser/temp_window_x11.h', 'tests/cefclient/browser/temp_window_x11.h',
'tests/cefclient/browser/views_menu_bar.cc',
'tests/cefclient/browser/views_menu_bar.h',
'tests/cefclient/browser/views_window.cc', 'tests/cefclient/browser/views_window.cc',
'tests/cefclient/browser/views_window.h', 'tests/cefclient/browser/views_window.h',
'tests/cefclient/browser/window_test_runner_gtk.cc', 'tests/cefclient/browser/window_test_runner_gtk.cc',
......
...@@ -58,6 +58,11 @@ typedef struct _cef_menu_model_t { ...@@ -58,6 +58,11 @@ typedef struct _cef_menu_model_t {
/// ///
cef_base_ref_counted_t base; cef_base_ref_counted_t base;
///
// Returns true (1) if this menu is a submenu.
///
int (CEF_CALLBACK *is_sub_menu)(struct _cef_menu_model_t* self);
/// ///
// Clears the menu. Returns true (1) on success. // Clears the menu. Returns true (1) on success.
/// ///
......
...@@ -65,6 +65,30 @@ typedef struct _cef_menu_model_delegate_t { ...@@ -65,6 +65,30 @@ typedef struct _cef_menu_model_delegate_t {
struct _cef_menu_model_t* menu_model, int command_id, struct _cef_menu_model_t* menu_model, int command_id,
cef_event_flags_t event_flags); cef_event_flags_t event_flags);
///
// Called when the user moves the mouse outside the menu and over the owning
// window.
///
void (CEF_CALLBACK *mouse_outside_menu)(
struct _cef_menu_model_delegate_t* self,
struct _cef_menu_model_t* menu_model, const cef_point_t* screen_point);
///
// Called on unhandled open submenu keyboard commands. |is_rtl| will be true
// (1) if the menu is displaying a right-to-left language.
///
void (CEF_CALLBACK *unhandled_open_submenu)(
struct _cef_menu_model_delegate_t* self,
struct _cef_menu_model_t* menu_model, int is_rtl);
///
// Called on unhandled close submenu keyboard commands. |is_rtl| will be true
// (1) if the menu is displaying a right-to-left language.
///
void (CEF_CALLBACK *unhandled_close_submenu)(
struct _cef_menu_model_delegate_t* self,
struct _cef_menu_model_t* menu_model, int is_rtl);
/// ///
// The menu is about to show. // The menu is about to show.
/// ///
......
...@@ -62,6 +62,12 @@ typedef struct _cef_button_delegate_t { ...@@ -62,6 +62,12 @@ typedef struct _cef_button_delegate_t {
/// ///
void (CEF_CALLBACK *on_button_pressed)(struct _cef_button_delegate_t* self, void (CEF_CALLBACK *on_button_pressed)(struct _cef_button_delegate_t* self,
struct _cef_button_t* button); struct _cef_button_t* button);
///
// Called when the state of |button| changes.
///
void (CEF_CALLBACK *on_button_state_changed)(
struct _cef_button_delegate_t* self, struct _cef_button_t* button);
} cef_button_delegate_t; } cef_button_delegate_t;
......
...@@ -68,6 +68,12 @@ typedef struct _cef_menu_button_t { ...@@ -68,6 +68,12 @@ typedef struct _cef_menu_button_t {
void (CEF_CALLBACK *show_menu)(struct _cef_menu_button_t* self, void (CEF_CALLBACK *show_menu)(struct _cef_menu_button_t* self,
struct _cef_menu_model_t* menu_model, const cef_point_t* screen_point, struct _cef_menu_model_t* menu_model, const cef_point_t* screen_point,
cef_menu_anchor_position_t anchor_position); cef_menu_anchor_position_t anchor_position);
///
// Show the menu for this button. Results in a call to
// cef_menu_button_delegate_t::on_menu_button_pressed().
///
void (CEF_CALLBACK *trigger_menu)(struct _cef_menu_button_t* self);
} cef_menu_button_t; } cef_menu_button_t;
......
...@@ -59,6 +59,12 @@ class CefMenuModel : public virtual CefBaseRefCounted { ...@@ -59,6 +59,12 @@ class CefMenuModel : public virtual CefBaseRefCounted {
static CefRefPtr<CefMenuModel> CreateMenuModel( static CefRefPtr<CefMenuModel> CreateMenuModel(
CefRefPtr<CefMenuModelDelegate> delegate); CefRefPtr<CefMenuModelDelegate> delegate);
///
// Returns true if this menu is a submenu.
///
/*--cef()--*/
virtual bool IsSubMenu() =0;
/// ///
// Clears the menu. Returns true on success. // Clears the menu. Returns true on success.
/// ///
......
...@@ -59,6 +59,30 @@ class CefMenuModelDelegate : public virtual CefBaseRefCounted { ...@@ -59,6 +59,30 @@ class CefMenuModelDelegate : public virtual CefBaseRefCounted {
int command_id, int command_id,
cef_event_flags_t event_flags) =0; cef_event_flags_t event_flags) =0;
///
// Called when the user moves the mouse outside the menu and over the owning
// window.
///
/*--cef()--*/
virtual void MouseOutsideMenu(CefRefPtr<CefMenuModel> menu_model,
const CefPoint& screen_point) {}
///
// Called on unhandled open submenu keyboard commands. |is_rtl| will be true
// if the menu is displaying a right-to-left language.
///
/*--cef()--*/
virtual void UnhandledOpenSubmenu(CefRefPtr<CefMenuModel> menu_model,
bool is_rtl) {}
///
// Called on unhandled close submenu keyboard commands. |is_rtl| will be true
// if the menu is displaying a right-to-left language.
///
/*--cef()--*/
virtual void UnhandledCloseSubmenu(CefRefPtr<CefMenuModel> menu_model,
bool is_rtl) {}
/// ///
// The menu is about to show. // The menu is about to show.
/// ///
......
...@@ -54,6 +54,12 @@ class CefButtonDelegate : public CefViewDelegate { ...@@ -54,6 +54,12 @@ class CefButtonDelegate : public CefViewDelegate {
/// ///
/*--cef()--*/ /*--cef()--*/
virtual void OnButtonPressed(CefRefPtr<CefButton> button) =0; virtual void OnButtonPressed(CefRefPtr<CefButton> button) =0;
///
// Called when the state of |button| changes.
///
/*--cef()--*/
virtual void OnButtonStateChanged(CefRefPtr<CefButton> button) {};
}; };
#endif // CEF_INCLUDE_VIEWS_CEF_BUTTON_DELEGATE_H_ #endif // CEF_INCLUDE_VIEWS_CEF_BUTTON_DELEGATE_H_
...@@ -78,6 +78,13 @@ class CefMenuButton : public CefLabelButton { ...@@ -78,6 +78,13 @@ class CefMenuButton : public CefLabelButton {
virtual void ShowMenu(CefRefPtr<CefMenuModel> menu_model, virtual void ShowMenu(CefRefPtr<CefMenuModel> menu_model,
const CefPoint& screen_point, const CefPoint& screen_point,
cef_menu_anchor_position_t anchor_position) =0; cef_menu_anchor_position_t anchor_position) =0;
///
// Show the menu for this button. Results in a call to
// CefMenuButtonDelegate::OnMenuButtonPressed().
///
/*--cef()--*/
virtual void TriggerMenu() =0;
}; };
#endif // CEF_INCLUDE_VIEWS_CEF_MENU_BUTTON_H_ #endif // CEF_INCLUDE_VIEWS_CEF_MENU_BUTTON_H_
...@@ -113,6 +113,7 @@ class CefWindowDelegate : public CefPanelDelegate { ...@@ -113,6 +113,7 @@ class CefWindowDelegate : public CefPanelDelegate {
/*--cef()--*/ /*--cef()--*/
virtual bool OnKeyEvent(CefRefPtr<CefWindow> window, virtual bool OnKeyEvent(CefRefPtr<CefWindow> window,
const CefKeyEvent& event) { return false; } const CefKeyEvent& event) { return false; }
}; };
#endif // CEF_INCLUDE_VIEWS_CEF_WINDOW_DELEGATE_H_ #endif // CEF_INCLUDE_VIEWS_CEF_WINDOW_DELEGATE_H_
...@@ -99,7 +99,7 @@ CefMenuManager::CefMenuManager(CefBrowserHostImpl* browser, ...@@ -99,7 +99,7 @@ CefMenuManager::CefMenuManager(CefBrowserHostImpl* browser,
weak_ptr_factory_(this) { weak_ptr_factory_(this) {
DCHECK(web_contents()); DCHECK(web_contents());
DCHECK(runner_.get()); DCHECK(runner_.get());
model_ = new CefMenuModelImpl(this, nullptr); model_ = new CefMenuModelImpl(this, nullptr, false);
} }
CefMenuManager::~CefMenuManager() { CefMenuManager::~CefMenuManager() {
...@@ -289,7 +289,8 @@ void CefMenuManager::MenuClosed(CefRefPtr<CefMenuModelImpl> source) { ...@@ -289,7 +289,8 @@ void CefMenuManager::MenuClosed(CefRefPtr<CefMenuModelImpl> source) {
web_contents()->NotifyContextMenuClosed(params_.custom_context); web_contents()->NotifyContextMenuClosed(params_.custom_context);
} }
bool CefMenuManager::FormatLabel(base::string16& label) { bool CefMenuManager::FormatLabel(CefRefPtr<CefMenuModelImpl> source,
base::string16& label) {
return runner_->FormatLabel(label); return runner_->FormatLabel(label);
} }
......
...@@ -46,7 +46,8 @@ class CefMenuManager : public CefMenuModelImpl::Delegate, ...@@ -46,7 +46,8 @@ class CefMenuManager : public CefMenuModelImpl::Delegate,
cef_event_flags_t event_flags) override; cef_event_flags_t event_flags) override;
void MenuWillShow(CefRefPtr<CefMenuModelImpl> source) override; void MenuWillShow(CefRefPtr<CefMenuModelImpl> source) override;
void MenuClosed(CefRefPtr<CefMenuModelImpl> source) override; void MenuClosed(CefRefPtr<CefMenuModelImpl> source) override;
bool FormatLabel(base::string16& label) override; bool FormatLabel(CefRefPtr<CefMenuModelImpl> source,
base::string16& label) override;
void ExecuteCommandCallback(int command_id, void ExecuteCommandCallback(int command_id,
cef_event_flags_t event_flags); cef_event_flags_t event_flags);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "content/public/common/menu_item.h" #include "content/public/common/menu_item.h"
#include "ui/base/accelerators/accelerator.h" #include "ui/base/accelerators/accelerator.h"
#include "ui/gfx/geometry/point.h"
namespace { namespace {
...@@ -138,6 +139,18 @@ class CefSimpleMenuModel : public ui::MenuModel { ...@@ -138,6 +139,18 @@ class CefSimpleMenuModel : public ui::MenuModel {
return NULL; return NULL;
} }
void MouseOutsideMenu(const gfx::Point& screen_point) override {
impl_->MouseOutsideMenu(screen_point);
}
void UnhandledOpenSubmenu(bool is_rtl) override {
impl_->UnhandledOpenSubmenu(is_rtl);
}
void UnhandledCloseSubmenu(bool is_rtl) override {
impl_->UnhandledCloseSubmenu(is_rtl);
}
void MenuWillShow() override { void MenuWillShow() override {
impl_->MenuWillShow(); impl_->MenuWillShow();
} }
...@@ -173,7 +186,7 @@ CefRefPtr<CefMenuModel> CefMenuModel::CreateMenuModel( ...@@ -173,7 +186,7 @@ CefRefPtr<CefMenuModel> CefMenuModel::CreateMenuModel(
return nullptr; return nullptr;
CefRefPtr<CefMenuModelImpl> menu_model = CefRefPtr<CefMenuModelImpl> menu_model =
new CefMenuModelImpl(nullptr, delegate); new CefMenuModelImpl(nullptr, delegate, false);
return menu_model; return menu_model;
} }
...@@ -219,10 +232,12 @@ struct CefMenuModelImpl::Item { ...@@ -219,10 +232,12 @@ struct CefMenuModelImpl::Item {
CefMenuModelImpl::CefMenuModelImpl( CefMenuModelImpl::CefMenuModelImpl(
Delegate* delegate, Delegate* delegate,
CefRefPtr<CefMenuModelDelegate> menu_model_delegate) CefRefPtr<CefMenuModelDelegate> menu_model_delegate,
bool is_submenu)
: supported_thread_id_(base::PlatformThread::CurrentId()), : supported_thread_id_(base::PlatformThread::CurrentId()),
delegate_(delegate), delegate_(delegate),
menu_model_delegate_(menu_model_delegate) { menu_model_delegate_(menu_model_delegate),
is_submenu_(is_submenu) {
DCHECK(delegate_ || menu_model_delegate_); DCHECK(delegate_ || menu_model_delegate_);
model_.reset(new CefSimpleMenuModel(this)); model_.reset(new CefSimpleMenuModel(this));
} }
...@@ -230,6 +245,12 @@ CefMenuModelImpl::CefMenuModelImpl( ...@@ -230,6 +245,12 @@ CefMenuModelImpl::CefMenuModelImpl(
CefMenuModelImpl::~CefMenuModelImpl() { CefMenuModelImpl::~CefMenuModelImpl() {
} }
bool CefMenuModelImpl::IsSubMenu() {
if (!VerifyContext())
return false;
return is_submenu_;
}
bool CefMenuModelImpl::Clear() { bool CefMenuModelImpl::Clear() {
if (!VerifyContext()) if (!VerifyContext())
return false; return false;
...@@ -284,7 +305,7 @@ CefRefPtr<CefMenuModel> CefMenuModelImpl::AddSubMenu(int command_id, ...@@ -284,7 +305,7 @@ CefRefPtr<CefMenuModel> CefMenuModelImpl::AddSubMenu(int command_id,
return NULL; return NULL;
Item item(MENUITEMTYPE_SUBMENU, command_id, label, -1); Item item(MENUITEMTYPE_SUBMENU, command_id, label, -1);
item.submenu_ = new CefMenuModelImpl(delegate_, menu_model_delegate_); item.submenu_ = new CefMenuModelImpl(delegate_, menu_model_delegate_, true);
AppendItem(item); AppendItem(item);
return item.submenu_.get(); return item.submenu_.get();
} }
...@@ -331,7 +352,7 @@ CefRefPtr<CefMenuModel> CefMenuModelImpl::InsertSubMenuAt( ...@@ -331,7 +352,7 @@ CefRefPtr<CefMenuModel> CefMenuModelImpl::InsertSubMenuAt(
return NULL; return NULL;
Item item(MENUITEMTYPE_SUBMENU, command_id, label, -1); Item item(MENUITEMTYPE_SUBMENU, command_id, label, -1);
item.submenu_ = new CefMenuModelImpl(delegate_, menu_model_delegate_); item.submenu_ = new CefMenuModelImpl(delegate_, menu_model_delegate_, true);
InsertItemAt(item, index); InsertItemAt(item, index);
return item.submenu_.get(); return item.submenu_.get();
} }
...@@ -646,6 +667,39 @@ void CefMenuModelImpl::ActivatedAt(int index, cef_event_flags_t event_flags) { ...@@ -646,6 +667,39 @@ void CefMenuModelImpl::ActivatedAt(int index, cef_event_flags_t event_flags) {
menu_model_delegate_->ExecuteCommand(this, command_id, event_flags); menu_model_delegate_->ExecuteCommand(this, command_id, event_flags);
} }
void CefMenuModelImpl::MouseOutsideMenu(const gfx::Point& screen_point) {
if (!VerifyContext())
return;
// Allow the callstack to unwind before notifying the delegate since it may
// result in the menu being destroyed.
base::MessageLoop::current()->task_runner()->PostTask(
FROM_HERE,
base::Bind(&CefMenuModelImpl::OnMouseOutsideMenu, this, screen_point));
}
void CefMenuModelImpl::UnhandledOpenSubmenu(bool is_rtl) {
if (!VerifyContext())
return;
// Allow the callstack to unwind before notifying the delegate since it may
// result in the menu being destroyed.
base::MessageLoop::current()->task_runner()->PostTask(
FROM_HERE,
base::Bind(&CefMenuModelImpl::OnUnhandledOpenSubmenu, this, is_rtl));
}
void CefMenuModelImpl::UnhandledCloseSubmenu(bool is_rtl) {
if (!VerifyContext())
return;
// Allow the callstack to unwind before notifying the delegate since it may
// result in the menu being destroyed.
base::MessageLoop::current()->task_runner()->PostTask(
FROM_HERE,
base::Bind(&CefMenuModelImpl::OnUnhandledCloseSubmenu, this, is_rtl));
}
void CefMenuModelImpl::MenuWillShow() { void CefMenuModelImpl::MenuWillShow() {
if (!VerifyContext()) if (!VerifyContext())
return; return;
...@@ -654,14 +708,15 @@ void CefMenuModelImpl::MenuWillShow() { ...@@ -654,14 +708,15 @@ void CefMenuModelImpl::MenuWillShow() {
delegate_->MenuWillShow(this); delegate_->MenuWillShow(this);
if (menu_model_delegate_) if (menu_model_delegate_)
menu_model_delegate_->MenuWillShow(this); menu_model_delegate_->MenuWillShow(this);
for (auto& observer : observers_)
observer.MenuWillShow(this);
} }
void CefMenuModelImpl::MenuWillClose() { void CefMenuModelImpl::MenuWillClose() {
if (!VerifyContext()) if (!VerifyContext())
return; return;
if (!auto_notify_menu_closed_)
return;
// Due to how menus work on the different platforms, ActivatedAt will be // Due to how menus work on the different platforms, ActivatedAt will be
// called after this. It's more convenient for the delegate to be called // called after this. It's more convenient for the delegate to be called
// afterwards, though, so post a task. // afterwards, though, so post a task.
...@@ -673,7 +728,7 @@ void CefMenuModelImpl::MenuWillClose() { ...@@ -673,7 +728,7 @@ void CefMenuModelImpl::MenuWillClose() {
base::string16 CefMenuModelImpl::GetFormattedLabelAt(int index) { base::string16 CefMenuModelImpl::GetFormattedLabelAt(int index) {
base::string16 label = GetLabelAt(index).ToString16(); base::string16 label = GetLabelAt(index).ToString16();
if (delegate_) if (delegate_)
delegate_->FormatLabel(label); delegate_->FormatLabel(this, label);
if (menu_model_delegate_) { if (menu_model_delegate_) {
CefString new_label = label; CefString new_label = label;
if (menu_model_delegate_->FormatLabel(this, new_label)) if (menu_model_delegate_->FormatLabel(this, new_label))
...@@ -699,18 +754,6 @@ bool CefMenuModelImpl::VerifyRefCount() { ...@@ -699,18 +754,6 @@ bool CefMenuModelImpl::VerifyRefCount() {
return true; return true;
} }
void CefMenuModelImpl::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
void CefMenuModelImpl::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
bool CefMenuModelImpl::HasObserver(Observer* observer) const {
return observers_.HasObserver(observer);
}
void CefMenuModelImpl::AddMenuItem(const content::MenuItem& menu_item) { void CefMenuModelImpl::AddMenuItem(const content::MenuItem& menu_item) {
const int command_id = static_cast<int>(menu_item.action); const int command_id = static_cast<int>(menu_item.action);
...@@ -746,6 +789,11 @@ void CefMenuModelImpl::AddMenuItem(const content::MenuItem& menu_item) { ...@@ -746,6 +789,11 @@ void CefMenuModelImpl::AddMenuItem(const content::MenuItem& menu_item) {
} }
} }
void CefMenuModelImpl::NotifyMenuClosed() {
DCHECK(!auto_notify_menu_closed_);
OnMenuClosed();
}
void CefMenuModelImpl::AppendItem(const Item& item) { void CefMenuModelImpl::AppendItem(const Item& item) {
ValidateItem(item); ValidateItem(item);
items_.push_back(item); items_.push_back(item);
...@@ -772,13 +820,34 @@ void CefMenuModelImpl::ValidateItem(const Item& item) { ...@@ -772,13 +820,34 @@ void CefMenuModelImpl::ValidateItem(const Item& item) {
#endif #endif
} }
void CefMenuModelImpl::OnMouseOutsideMenu(const gfx::Point& screen_point) {
if (delegate_)
delegate_->MouseOutsideMenu(this, screen_point);
if (menu_model_delegate_) {
menu_model_delegate_->MouseOutsideMenu(this,
CefPoint(screen_point.x(), screen_point.y()));
}
}
void CefMenuModelImpl::OnUnhandledOpenSubmenu(bool is_rtl) {
if (delegate_)
delegate_->UnhandledOpenSubmenu(this, is_rtl);
if (menu_model_delegate_)
menu_model_delegate_->UnhandledOpenSubmenu(this, is_rtl);
}
void CefMenuModelImpl::OnUnhandledCloseSubmenu(bool is_rtl) {
if (delegate_)
delegate_->UnhandledCloseSubmenu(this, is_rtl);
if (menu_model_delegate_)
menu_model_delegate_->UnhandledCloseSubmenu(this, is_rtl);
}
void CefMenuModelImpl::OnMenuClosed() { void CefMenuModelImpl::OnMenuClosed() {
if (delegate_) if (delegate_)
delegate_->MenuClosed(this); delegate_->MenuClosed(this);
if (menu_model_delegate_) if (menu_model_delegate_)
menu_model_delegate_->MenuClosed(this); menu_model_delegate_->MenuClosed(this);
for (auto& observer : observers_)
observer.MenuClosed(this);
} }
bool CefMenuModelImpl::VerifyContext() { bool CefMenuModelImpl::VerifyContext() {
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include "include/cef_menu_model.h" #include "include/cef_menu_model.h"
#include "include/cef_menu_model_delegate.h" #include "include/cef_menu_model_delegate.h"
#include "base/observer_list.h"
#include "base/threading/platform_thread.h" #include "base/threading/platform_thread.h"
#include "ui/base/models/menu_model.h" #include "ui/base/models/menu_model.h"
...@@ -30,38 +29,41 @@ class CefMenuModelImpl : public CefMenuModel { ...@@ -30,38 +29,41 @@ class CefMenuModelImpl : public CefMenuModel {
int command_id, int command_id,
cef_event_flags_t event_flags) =0; cef_event_flags_t event_flags) =0;
// Notifies the delegate that the menu is about to show. // Called when the user moves the mouse outside the menu and over the owning
// window.
virtual void MouseOutsideMenu(CefRefPtr<CefMenuModelImpl> source,
const gfx::Point& screen_point) {}
// Called on unhandled open/close submenu keyboard commands. |is_rtl| will
// be true if the menu is displaying a right-to-left language.
virtual void UnhandledOpenSubmenu(CefRefPtr<CefMenuModelImpl> source,
bool is_rtl) {}
virtual void UnhandledCloseSubmenu(CefRefPtr<CefMenuModelImpl> source,
bool is_rtl) {}
// Called when the menu is about to show.
virtual void MenuWillShow(CefRefPtr<CefMenuModelImpl> source) =0; virtual void MenuWillShow(CefRefPtr<CefMenuModelImpl> source) =0;
// Notifies the delegate that the menu has closed. // Called when the menu has closed.
virtual void MenuClosed(CefRefPtr<CefMenuModelImpl> source) =0; virtual void MenuClosed(CefRefPtr<CefMenuModelImpl> source) =0;
// Allows the delegate to modify a menu item label before it's displayed. // Allows the delegate to modify a menu item label before it's displayed.
virtual bool FormatLabel(base::string16& label) =0; virtual bool FormatLabel(CefRefPtr<CefMenuModelImpl> source,
base::string16& label) =0;
protected: protected:
virtual ~Delegate() {} virtual ~Delegate() {}
}; };
class Observer {
public:
// Notifies the delegate that the menu is about to show.
virtual void MenuWillShow(CefRefPtr<CefMenuModelImpl> source) {};
// Notifies the delegate that the menu has closed.
virtual void MenuClosed(CefRefPtr<CefMenuModelImpl> source) {};
protected:
virtual ~Observer() {}
};
// Either |delegate| or |menu_model_delegate| must be non-nullptr. // Either |delegate| or |menu_model_delegate| must be non-nullptr.
// If |delegate| is non-nullptr it must outlive this class. // If |delegate| is non-nullptr it must outlive this class.
CefMenuModelImpl(Delegate* delegate, CefMenuModelImpl(Delegate* delegate,
CefRefPtr<CefMenuModelDelegate> menu_model_delegate); CefRefPtr<CefMenuModelDelegate> menu_model_delegate,
bool is_submenu);
~CefMenuModelImpl() override; ~CefMenuModelImpl() override;
// CefMenuModel methods. // CefMenuModel methods.
bool IsSubMenu() override;
bool Clear() override; bool Clear() override;
int GetCount() override; int GetCount() override;
bool AddSeparator() override; bool AddSeparator() override;
...@@ -124,6 +126,9 @@ class CefMenuModelImpl : public CefMenuModel { ...@@ -124,6 +126,9 @@ class CefMenuModelImpl : public CefMenuModel {
// Callbacks from the ui::MenuModel implementation. // Callbacks from the ui::MenuModel implementation.
void ActivatedAt(int index, cef_event_flags_t event_flags); void ActivatedAt(int index, cef_event_flags_t event_flags);
void MouseOutsideMenu(const gfx::Point& screen_point);
void UnhandledOpenSubmenu(bool is_rtl);
void UnhandledCloseSubmenu(bool is_rtl);
void MenuWillShow(); void MenuWillShow();
void MenuWillClose(); void MenuWillClose();
base::string16 GetFormattedLabelAt(int index); base::string16 GetFormattedLabelAt(int index);
...@@ -131,21 +136,20 @@ class CefMenuModelImpl : public CefMenuModel { ...@@ -131,21 +136,20 @@ class CefMenuModelImpl : public CefMenuModel {
// Verify that only a single reference exists to all CefMenuModelImpl objects. // Verify that only a single reference exists to all CefMenuModelImpl objects.
bool VerifyRefCount(); bool VerifyRefCount();
// Manage observer objects. The observer must either outlive this object or
// remove itself before destruction.
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
bool HasObserver(Observer* observer) const;
// Helper for adding custom menu items originating from the renderer process. // Helper for adding custom menu items originating from the renderer process.
void AddMenuItem(const content::MenuItem& menu_item); void AddMenuItem(const content::MenuItem& menu_item);
ui::MenuModel* model() { return model_.get(); } ui::MenuModel* model() const { return model_.get(); }
// Used when created via CefMenuManager.