mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
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).
This commit is contained in:
@ -299,6 +299,8 @@
|
||||
'tests/cefclient/browser/root_window_win.h',
|
||||
'tests/cefclient/browser/temp_window_win.cc',
|
||||
'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.h',
|
||||
'tests/cefclient/browser/window_test_runner_views.cc',
|
||||
@ -350,6 +352,8 @@
|
||||
'tests/cefclient/browser/root_window_views.h',
|
||||
'tests/cefclient/browser/temp_window_x11.cc',
|
||||
'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.h',
|
||||
'tests/cefclient/browser/window_test_runner_gtk.cc',
|
||||
|
@ -58,6 +58,11 @@ typedef struct _cef_menu_model_t {
|
||||
///
|
||||
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.
|
||||
///
|
||||
|
@ -65,6 +65,30 @@ typedef struct _cef_menu_model_delegate_t {
|
||||
struct _cef_menu_model_t* menu_model, int command_id,
|
||||
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.
|
||||
///
|
||||
|
@ -62,6 +62,12 @@ typedef struct _cef_button_delegate_t {
|
||||
///
|
||||
void (CEF_CALLBACK *on_button_pressed)(struct _cef_button_delegate_t* self,
|
||||
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;
|
||||
|
||||
|
||||
|
@ -68,6 +68,12 @@ typedef struct _cef_menu_button_t {
|
||||
void (CEF_CALLBACK *show_menu)(struct _cef_menu_button_t* self,
|
||||
struct _cef_menu_model_t* menu_model, const cef_point_t* screen_point,
|
||||
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;
|
||||
|
||||
|
||||
|
@ -59,6 +59,12 @@ class CefMenuModel : public virtual CefBaseRefCounted {
|
||||
static CefRefPtr<CefMenuModel> CreateMenuModel(
|
||||
CefRefPtr<CefMenuModelDelegate> delegate);
|
||||
|
||||
///
|
||||
// Returns true if this menu is a submenu.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual bool IsSubMenu() =0;
|
||||
|
||||
///
|
||||
// Clears the menu. Returns true on success.
|
||||
///
|
||||
|
@ -59,6 +59,30 @@ class CefMenuModelDelegate : public virtual CefBaseRefCounted {
|
||||
int command_id,
|
||||
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.
|
||||
///
|
||||
|
@ -54,6 +54,12 @@ class CefButtonDelegate : public CefViewDelegate {
|
||||
///
|
||||
/*--cef()--*/
|
||||
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_
|
||||
|
@ -78,6 +78,13 @@ class CefMenuButton : public CefLabelButton {
|
||||
virtual void ShowMenu(CefRefPtr<CefMenuModel> menu_model,
|
||||
const CefPoint& screen_point,
|
||||
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_
|
||||
|
@ -113,6 +113,7 @@ class CefWindowDelegate : public CefPanelDelegate {
|
||||
/*--cef()--*/
|
||||
virtual bool OnKeyEvent(CefRefPtr<CefWindow> window,
|
||||
const CefKeyEvent& event) { return false; }
|
||||
|
||||
};
|
||||
|
||||
#endif // CEF_INCLUDE_VIEWS_CEF_WINDOW_DELEGATE_H_
|
||||
|
@ -99,7 +99,7 @@ CefMenuManager::CefMenuManager(CefBrowserHostImpl* browser,
|
||||
weak_ptr_factory_(this) {
|
||||
DCHECK(web_contents());
|
||||
DCHECK(runner_.get());
|
||||
model_ = new CefMenuModelImpl(this, nullptr);
|
||||
model_ = new CefMenuModelImpl(this, nullptr, false);
|
||||
}
|
||||
|
||||
CefMenuManager::~CefMenuManager() {
|
||||
@ -289,7 +289,8 @@ void CefMenuManager::MenuClosed(CefRefPtr<CefMenuModelImpl> source) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,8 @@ class CefMenuManager : public CefMenuModelImpl::Delegate,
|
||||
cef_event_flags_t event_flags) override;
|
||||
void MenuWillShow(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,
|
||||
cef_event_flags_t event_flags);
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "content/public/common/menu_item.h"
|
||||
#include "ui/base/accelerators/accelerator.h"
|
||||
#include "ui/gfx/geometry/point.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -138,6 +139,18 @@ class CefSimpleMenuModel : public ui::MenuModel {
|
||||
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 {
|
||||
impl_->MenuWillShow();
|
||||
}
|
||||
@ -173,7 +186,7 @@ CefRefPtr<CefMenuModel> CefMenuModel::CreateMenuModel(
|
||||
return nullptr;
|
||||
|
||||
CefRefPtr<CefMenuModelImpl> menu_model =
|
||||
new CefMenuModelImpl(nullptr, delegate);
|
||||
new CefMenuModelImpl(nullptr, delegate, false);
|
||||
return menu_model;
|
||||
}
|
||||
|
||||
@ -219,10 +232,12 @@ struct CefMenuModelImpl::Item {
|
||||
|
||||
CefMenuModelImpl::CefMenuModelImpl(
|
||||
Delegate* delegate,
|
||||
CefRefPtr<CefMenuModelDelegate> menu_model_delegate)
|
||||
CefRefPtr<CefMenuModelDelegate> menu_model_delegate,
|
||||
bool is_submenu)
|
||||
: supported_thread_id_(base::PlatformThread::CurrentId()),
|
||||
delegate_(delegate),
|
||||
menu_model_delegate_(menu_model_delegate) {
|
||||
menu_model_delegate_(menu_model_delegate),
|
||||
is_submenu_(is_submenu) {
|
||||
DCHECK(delegate_ || menu_model_delegate_);
|
||||
model_.reset(new CefSimpleMenuModel(this));
|
||||
}
|
||||
@ -230,6 +245,12 @@ CefMenuModelImpl::CefMenuModelImpl(
|
||||
CefMenuModelImpl::~CefMenuModelImpl() {
|
||||
}
|
||||
|
||||
bool CefMenuModelImpl::IsSubMenu() {
|
||||
if (!VerifyContext())
|
||||
return false;
|
||||
return is_submenu_;
|
||||
}
|
||||
|
||||
bool CefMenuModelImpl::Clear() {
|
||||
if (!VerifyContext())
|
||||
return false;
|
||||
@ -284,7 +305,7 @@ CefRefPtr<CefMenuModel> CefMenuModelImpl::AddSubMenu(int command_id,
|
||||
return NULL;
|
||||
|
||||
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);
|
||||
return item.submenu_.get();
|
||||
}
|
||||
@ -331,7 +352,7 @@ CefRefPtr<CefMenuModel> CefMenuModelImpl::InsertSubMenuAt(
|
||||
return NULL;
|
||||
|
||||
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);
|
||||
return item.submenu_.get();
|
||||
}
|
||||
@ -646,6 +667,39 @@ void CefMenuModelImpl::ActivatedAt(int index, cef_event_flags_t 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() {
|
||||
if (!VerifyContext())
|
||||
return;
|
||||
@ -654,14 +708,15 @@ void CefMenuModelImpl::MenuWillShow() {
|
||||
delegate_->MenuWillShow(this);
|
||||
if (menu_model_delegate_)
|
||||
menu_model_delegate_->MenuWillShow(this);
|
||||
for (auto& observer : observers_)
|
||||
observer.MenuWillShow(this);
|
||||
}
|
||||
|
||||
void CefMenuModelImpl::MenuWillClose() {
|
||||
if (!VerifyContext())
|
||||
return;
|
||||
|
||||
if (!auto_notify_menu_closed_)
|
||||
return;
|
||||
|
||||
// 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
|
||||
// afterwards, though, so post a task.
|
||||
@ -673,7 +728,7 @@ void CefMenuModelImpl::MenuWillClose() {
|
||||
base::string16 CefMenuModelImpl::GetFormattedLabelAt(int index) {
|
||||
base::string16 label = GetLabelAt(index).ToString16();
|
||||
if (delegate_)
|
||||
delegate_->FormatLabel(label);
|
||||
delegate_->FormatLabel(this, label);
|
||||
if (menu_model_delegate_) {
|
||||
CefString new_label = label;
|
||||
if (menu_model_delegate_->FormatLabel(this, new_label))
|
||||
@ -699,18 +754,6 @@ bool CefMenuModelImpl::VerifyRefCount() {
|
||||
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) {
|
||||
const int command_id = static_cast<int>(menu_item.action);
|
||||
|
||||
@ -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) {
|
||||
ValidateItem(item);
|
||||
items_.push_back(item);
|
||||
@ -772,13 +820,34 @@ void CefMenuModelImpl::ValidateItem(const Item& item) {
|
||||
#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() {
|
||||
if (delegate_)
|
||||
delegate_->MenuClosed(this);
|
||||
if (menu_model_delegate_)
|
||||
menu_model_delegate_->MenuClosed(this);
|
||||
for (auto& observer : observers_)
|
||||
observer.MenuClosed(this);
|
||||
}
|
||||
|
||||
bool CefMenuModelImpl::VerifyContext() {
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include "include/cef_menu_model.h"
|
||||
#include "include/cef_menu_model_delegate.h"
|
||||
|
||||
#include "base/observer_list.h"
|
||||
#include "base/threading/platform_thread.h"
|
||||
#include "ui/base/models/menu_model.h"
|
||||
|
||||
@ -30,38 +29,41 @@ class CefMenuModelImpl : public CefMenuModel {
|
||||
int command_id,
|
||||
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;
|
||||
|
||||
// Notifies the delegate that the menu has closed.
|
||||
// Called when the menu has closed.
|
||||
virtual void MenuClosed(CefRefPtr<CefMenuModelImpl> source) =0;
|
||||
|
||||
// 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:
|
||||
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.
|
||||
// If |delegate| is non-nullptr it must outlive this class.
|
||||
CefMenuModelImpl(Delegate* delegate,
|
||||
CefRefPtr<CefMenuModelDelegate> menu_model_delegate);
|
||||
CefRefPtr<CefMenuModelDelegate> menu_model_delegate,
|
||||
bool is_submenu);
|
||||
~CefMenuModelImpl() override;
|
||||
|
||||
// CefMenuModel methods.
|
||||
bool IsSubMenu() override;
|
||||
bool Clear() override;
|
||||
int GetCount() override;
|
||||
bool AddSeparator() override;
|
||||
@ -124,6 +126,9 @@ class CefMenuModelImpl : public CefMenuModel {
|
||||
|
||||
// Callbacks from the ui::MenuModel implementation.
|
||||
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 MenuWillClose();
|
||||
base::string16 GetFormattedLabelAt(int index);
|
||||
@ -131,21 +136,20 @@ class CefMenuModelImpl : public CefMenuModel {
|
||||
// Verify that only a single reference exists to all CefMenuModelImpl objects.
|
||||
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.
|
||||
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.
|
||||
Delegate* delegate() { return delegate_; }
|
||||
Delegate* delegate() const { return delegate_; }
|
||||
void set_delegate(Delegate* delegate) { delegate_ = delegate; }
|
||||
|
||||
// Used for menus run via CefWindowImpl::ShowMenu to provide more accurate
|
||||
// menu close notification.
|
||||
void set_auto_notify_menu_closed(bool val) { auto_notify_menu_closed_ = val; }
|
||||
void NotifyMenuClosed();
|
||||
|
||||
private:
|
||||
struct Item;
|
||||
|
||||
@ -156,7 +160,10 @@ class CefMenuModelImpl : public CefMenuModel {
|
||||
void InsertItemAt(const Item& item, int index);
|
||||
void ValidateItem(const Item& item);
|
||||
|
||||
// Notify the delegate that the menu is closed.
|
||||
// Notify the delegate asynchronously.
|
||||
void OnMouseOutsideMenu(const gfx::Point& screen_point);
|
||||
void OnUnhandledOpenSubmenu(bool is_rtl);
|
||||
void OnUnhandledCloseSubmenu(bool is_rtl);
|
||||
void OnMenuClosed();
|
||||
|
||||
// Verify that the object is being accessed from the correct thread.
|
||||
@ -170,11 +177,12 @@ class CefMenuModelImpl : public CefMenuModel {
|
||||
// Used when created via CefMenuModel::CreateMenuModel().
|
||||
CefRefPtr<CefMenuModelDelegate> menu_model_delegate_;
|
||||
|
||||
const bool is_submenu_;
|
||||
|
||||
ItemVector items_;
|
||||
std::unique_ptr<ui::MenuModel> model_;
|
||||
|
||||
// Observers that want to be notified of changes to this object.
|
||||
base::ObserverList<Observer> observers_;
|
||||
bool auto_notify_menu_closed_ = true;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(CefMenuModelImpl);
|
||||
DISALLOW_COPY_AND_ASSIGN(CefMenuModelImpl);
|
||||
|
@ -40,10 +40,19 @@ CEF_BUTTON_VIEW_T class CefButtonView : public CEF_VIEW_VIEW_D {
|
||||
return button;
|
||||
}
|
||||
|
||||
// views::CustomButton methods:
|
||||
void StateChanged() override;
|
||||
|
||||
// views::ButtonListener methods:
|
||||
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
|
||||
};
|
||||
|
||||
CEF_BUTTON_VIEW_T void CEF_BUTTON_VIEW_D::StateChanged() {
|
||||
ParentClass::StateChanged();
|
||||
if (ParentClass::cef_delegate())
|
||||
ParentClass::cef_delegate()->OnButtonStateChanged(GetCefButton());
|
||||
}
|
||||
|
||||
CEF_BUTTON_VIEW_T void CEF_BUTTON_VIEW_D::ButtonPressed(
|
||||
views::Button* sender, const ui::Event& event) {
|
||||
if (ParentClass::cef_delegate())
|
||||
|
@ -50,6 +50,11 @@ void CefMenuButtonImpl::ShowMenu(CefRefPtr<CefMenuModel> menu_model,
|
||||
}
|
||||
}
|
||||
|
||||
void CefMenuButtonImpl::TriggerMenu() {
|
||||
CEF_REQUIRE_VALID_RETURN_VOID();
|
||||
root_view()->Activate(nullptr);
|
||||
}
|
||||
|
||||
CefMenuButtonImpl::CefMenuButtonImpl(CefRefPtr<CefMenuButtonDelegate> delegate)
|
||||
: ParentClass(delegate) {
|
||||
DCHECK(delegate);
|
||||
|
@ -32,6 +32,7 @@ class CefMenuButtonImpl :
|
||||
void ShowMenu(CefRefPtr<CefMenuModel> menu_model,
|
||||
const CefPoint& screen_point,
|
||||
cef_menu_anchor_position_t anchor_position) override;
|
||||
void TriggerMenu() override;
|
||||
|
||||
// CefLabelButton methods:
|
||||
CefRefPtr<CefMenuButton> AsMenuButton() override { return this; }
|
||||
|
@ -390,13 +390,6 @@ void CefWindowImpl::OnWindowViewDeleted() {
|
||||
Detach();
|
||||
}
|
||||
|
||||
void CefWindowImpl::MenuClosed(CefRefPtr<CefMenuModelImpl> source) {
|
||||
DCHECK_EQ(menu_model_, source);
|
||||
menu_model_->RemoveObserver(this);
|
||||
menu_model_ = nullptr;
|
||||
menu_runner_.reset(nullptr);
|
||||
}
|
||||
|
||||
// Will only be called if CanHandleAccelerators() returns true.
|
||||
bool CefWindowImpl::AcceleratorPressed(const ui::Accelerator& accelerator) {
|
||||
for (const auto& entry : accelerator_map_) {
|
||||
@ -433,12 +426,16 @@ void CefWindowImpl::ShowMenu(views::MenuButton* menu_button,
|
||||
return;
|
||||
|
||||
menu_model_ = menu_model_impl;
|
||||
menu_model_->AddObserver(this);
|
||||
|
||||
// We'll send the MenuClosed notification manually for better accuracy.
|
||||
menu_model_->set_auto_notify_menu_closed(false);
|
||||
|
||||
menu_runner_.reset(
|
||||
new views::MenuRunner(menu_model_impl->model(),
|
||||
menu_button ? views::MenuRunner::HAS_MNEMONICS :
|
||||
views::MenuRunner::CONTEXT_MENU));
|
||||
views::MenuRunner::ASYNC |
|
||||
(menu_button ? views::MenuRunner::HAS_MNEMONICS :
|
||||
views::MenuRunner::CONTEXT_MENU),
|
||||
base::Bind(&CefWindowImpl::MenuClosed, this)));
|
||||
|
||||
views::MenuRunner::RunResult result = menu_runner_->RunMenuAt(
|
||||
widget_,
|
||||
@ -449,6 +446,12 @@ void CefWindowImpl::ShowMenu(views::MenuButton* menu_button,
|
||||
ALLOW_UNUSED_LOCAL(result);
|
||||
}
|
||||
|
||||
void CefWindowImpl::MenuClosed() {
|
||||
menu_model_->NotifyMenuClosed();
|
||||
menu_model_ = nullptr;
|
||||
menu_runner_.reset(nullptr);
|
||||
}
|
||||
|
||||
void CefWindowImpl::CancelMenu() {
|
||||
CEF_REQUIRE_VALID_RETURN_VOID();
|
||||
if (menu_runner_)
|
||||
|
@ -26,7 +26,6 @@ class MenuButton;
|
||||
class CefWindowImpl :
|
||||
public CefPanelImpl<CefWindowView, CefWindow, CefWindowDelegate>,
|
||||
public CefWindowView::Delegate,
|
||||
public CefMenuModelImpl::Observer,
|
||||
public ui::AcceleratorTarget {
|
||||
public:
|
||||
typedef CefPanelImpl<CefWindowView, CefWindow, CefWindowDelegate> ParentClass;
|
||||
@ -105,9 +104,6 @@ class CefWindowImpl :
|
||||
void OnWindowClosing() override;
|
||||
void OnWindowViewDeleted() override;
|
||||
|
||||
// CefMenuModelImpl::Observer methods:
|
||||
void MenuClosed(CefRefPtr<CefMenuModelImpl> source) override;
|
||||
|
||||
// CefViewAdapter methods:
|
||||
std::string GetDebugType() override { return "Window"; }
|
||||
void GetDebugInfo(base::DictionaryValue* info,
|
||||
@ -125,6 +121,7 @@ class CefWindowImpl :
|
||||
CefRefPtr<CefMenuModel> menu_model,
|
||||
const CefPoint& screen_point,
|
||||
cef_menu_anchor_position_t anchor_position);
|
||||
void MenuClosed();
|
||||
|
||||
private:
|
||||
// Create a new implementation object.
|
||||
|
@ -38,6 +38,20 @@ namespace {
|
||||
|
||||
// MEMBER FUNCTIONS - Body may be edited by hand.
|
||||
|
||||
int CEF_CALLBACK menu_model_is_sub_menu(struct _cef_menu_model_t* self) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return 0;
|
||||
|
||||
// Execute
|
||||
bool _retval = CefMenuModelCppToC::Get(self)->IsSubMenu();
|
||||
|
||||
// Return type: bool
|
||||
return _retval;
|
||||
}
|
||||
|
||||
int CEF_CALLBACK menu_model_clear(struct _cef_menu_model_t* self) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
@ -986,6 +1000,7 @@ int CEF_CALLBACK menu_model_get_accelerator_at(struct _cef_menu_model_t* self,
|
||||
// CONSTRUCTOR - Do not edit by hand.
|
||||
|
||||
CefMenuModelCppToC::CefMenuModelCppToC() {
|
||||
GetStruct()->is_sub_menu = menu_model_is_sub_menu;
|
||||
GetStruct()->clear = menu_model_clear;
|
||||
GetStruct()->get_count = menu_model_get_count;
|
||||
GetStruct()->add_separator = menu_model_add_separator;
|
||||
|
@ -38,6 +38,70 @@ void CEF_CALLBACK menu_model_delegate_execute_command(
|
||||
event_flags);
|
||||
}
|
||||
|
||||
void CEF_CALLBACK menu_model_delegate_mouse_outside_menu(
|
||||
struct _cef_menu_model_delegate_t* self, cef_menu_model_t* menu_model,
|
||||
const cef_point_t* screen_point) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
// Verify param: menu_model; type: refptr_diff
|
||||
DCHECK(menu_model);
|
||||
if (!menu_model)
|
||||
return;
|
||||
// Verify param: screen_point; type: simple_byref_const
|
||||
DCHECK(screen_point);
|
||||
if (!screen_point)
|
||||
return;
|
||||
|
||||
// Translate param: screen_point; type: simple_byref_const
|
||||
CefPoint screen_pointVal = screen_point?*screen_point:CefPoint();
|
||||
|
||||
// Execute
|
||||
CefMenuModelDelegateCppToC::Get(self)->MouseOutsideMenu(
|
||||
CefMenuModelCToCpp::Wrap(menu_model),
|
||||
screen_pointVal);
|
||||
}
|
||||
|
||||
void CEF_CALLBACK menu_model_delegate_unhandled_open_submenu(
|
||||
struct _cef_menu_model_delegate_t* self, cef_menu_model_t* menu_model,
|
||||
int is_rtl) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
// Verify param: menu_model; type: refptr_diff
|
||||
DCHECK(menu_model);
|
||||
if (!menu_model)
|
||||
return;
|
||||
|
||||
// Execute
|
||||
CefMenuModelDelegateCppToC::Get(self)->UnhandledOpenSubmenu(
|
||||
CefMenuModelCToCpp::Wrap(menu_model),
|
||||
is_rtl?true:false);
|
||||
}
|
||||
|
||||
void CEF_CALLBACK menu_model_delegate_unhandled_close_submenu(
|
||||
struct _cef_menu_model_delegate_t* self, cef_menu_model_t* menu_model,
|
||||
int is_rtl) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
// Verify param: menu_model; type: refptr_diff
|
||||
DCHECK(menu_model);
|
||||
if (!menu_model)
|
||||
return;
|
||||
|
||||
// Execute
|
||||
CefMenuModelDelegateCppToC::Get(self)->UnhandledCloseSubmenu(
|
||||
CefMenuModelCToCpp::Wrap(menu_model),
|
||||
is_rtl?true:false);
|
||||
}
|
||||
|
||||
void CEF_CALLBACK menu_model_delegate_menu_will_show(
|
||||
struct _cef_menu_model_delegate_t* self, cef_menu_model_t* menu_model) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
@ -108,6 +172,11 @@ int CEF_CALLBACK menu_model_delegate_format_label(
|
||||
|
||||
CefMenuModelDelegateCppToC::CefMenuModelDelegateCppToC() {
|
||||
GetStruct()->execute_command = menu_model_delegate_execute_command;
|
||||
GetStruct()->mouse_outside_menu = menu_model_delegate_mouse_outside_menu;
|
||||
GetStruct()->unhandled_open_submenu =
|
||||
menu_model_delegate_unhandled_open_submenu;
|
||||
GetStruct()->unhandled_close_submenu =
|
||||
menu_model_delegate_unhandled_close_submenu;
|
||||
GetStruct()->menu_will_show = menu_model_delegate_menu_will_show;
|
||||
GetStruct()->menu_closed = menu_model_delegate_menu_closed;
|
||||
GetStruct()->format_label = menu_model_delegate_format_label;
|
||||
|
@ -37,6 +37,23 @@ void CEF_CALLBACK button_delegate_on_button_pressed(
|
||||
CefButtonCToCpp::Wrap(button));
|
||||
}
|
||||
|
||||
void CEF_CALLBACK button_delegate_on_button_state_changed(
|
||||
struct _cef_button_delegate_t* self, cef_button_t* button) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
// Verify param: button; type: refptr_diff
|
||||
DCHECK(button);
|
||||
if (!button)
|
||||
return;
|
||||
|
||||
// Execute
|
||||
CefButtonDelegateCppToC::Get(self)->OnButtonStateChanged(
|
||||
CefButtonCToCpp::Wrap(button));
|
||||
}
|
||||
|
||||
cef_size_t CEF_CALLBACK button_delegate_get_preferred_size(
|
||||
struct _cef_view_delegate_t* self, cef_view_t* view) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
@ -215,6 +232,8 @@ void CEF_CALLBACK button_delegate_on_blur(struct _cef_view_delegate_t* self,
|
||||
|
||||
CefButtonDelegateCppToC::CefButtonDelegateCppToC() {
|
||||
GetStruct()->on_button_pressed = button_delegate_on_button_pressed;
|
||||
GetStruct()->on_button_state_changed =
|
||||
button_delegate_on_button_state_changed;
|
||||
GetStruct()->base.get_preferred_size = button_delegate_get_preferred_size;
|
||||
GetStruct()->base.get_minimum_size = button_delegate_get_minimum_size;
|
||||
GetStruct()->base.get_maximum_size = button_delegate_get_maximum_size;
|
||||
|
@ -81,6 +81,17 @@ void CEF_CALLBACK menu_button_show_menu(struct _cef_menu_button_t* self,
|
||||
anchor_position);
|
||||
}
|
||||
|
||||
void CEF_CALLBACK menu_button_trigger_menu(struct _cef_menu_button_t* self) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
// Execute
|
||||
CefMenuButtonCppToC::Get(self)->TriggerMenu();
|
||||
}
|
||||
|
||||
cef_menu_button_t* CEF_CALLBACK menu_button_as_menu_button(
|
||||
struct _cef_label_button_t* self) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
@ -1186,6 +1197,7 @@ int CEF_CALLBACK menu_button_convert_point_from_view(struct _cef_view_t* self,
|
||||
|
||||
CefMenuButtonCppToC::CefMenuButtonCppToC() {
|
||||
GetStruct()->show_menu = menu_button_show_menu;
|
||||
GetStruct()->trigger_menu = menu_button_trigger_menu;
|
||||
GetStruct()->base.as_menu_button = menu_button_as_menu_button;
|
||||
GetStruct()->base.set_text = menu_button_set_text;
|
||||
GetStruct()->base.get_text = menu_button_get_text;
|
||||
|
@ -64,6 +64,25 @@ void CEF_CALLBACK menu_button_delegate_on_button_pressed(
|
||||
CefButtonCToCpp::Wrap(button));
|
||||
}
|
||||
|
||||
void CEF_CALLBACK menu_button_delegate_on_button_state_changed(
|
||||
struct _cef_button_delegate_t* self, cef_button_t* button) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return;
|
||||
// Verify param: button; type: refptr_diff
|
||||
DCHECK(button);
|
||||
if (!button)
|
||||
return;
|
||||
|
||||
// Execute
|
||||
CefMenuButtonDelegateCppToC::Get(
|
||||
reinterpret_cast<cef_menu_button_delegate_t*>(
|
||||
self))->OnButtonStateChanged(
|
||||
CefButtonCToCpp::Wrap(button));
|
||||
}
|
||||
|
||||
cef_size_t CEF_CALLBACK menu_button_delegate_get_preferred_size(
|
||||
struct _cef_view_delegate_t* self, cef_view_t* view) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
@ -244,6 +263,8 @@ CefMenuButtonDelegateCppToC::CefMenuButtonDelegateCppToC() {
|
||||
GetStruct()->on_menu_button_pressed =
|
||||
menu_button_delegate_on_menu_button_pressed;
|
||||
GetStruct()->base.on_button_pressed = menu_button_delegate_on_button_pressed;
|
||||
GetStruct()->base.on_button_state_changed =
|
||||
menu_button_delegate_on_button_state_changed;
|
||||
GetStruct()->base.base.get_preferred_size =
|
||||
menu_button_delegate_get_preferred_size;
|
||||
GetStruct()->base.base.get_minimum_size =
|
||||
|
@ -36,6 +36,20 @@ CefRefPtr<CefMenuModel> CefMenuModel::CreateMenuModel(
|
||||
|
||||
// VIRTUAL METHODS - Body may be edited by hand.
|
||||
|
||||
bool CefMenuModelCToCpp::IsSubMenu() {
|
||||
cef_menu_model_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, is_sub_menu))
|
||||
return false;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Execute
|
||||
int _retval = _struct->is_sub_menu(_struct);
|
||||
|
||||
// Return type: bool
|
||||
return _retval?true:false;
|
||||
}
|
||||
|
||||
bool CefMenuModelCToCpp::Clear() {
|
||||
cef_menu_model_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, clear))
|
||||
|
@ -31,6 +31,7 @@ class CefMenuModelCToCpp
|
||||
CefMenuModelCToCpp();
|
||||
|
||||
// CefMenuModel methods.
|
||||
bool IsSubMenu() OVERRIDE;
|
||||
bool Clear() OVERRIDE;
|
||||
int GetCount() OVERRIDE;
|
||||
bool AddSeparator() OVERRIDE;
|
||||
|
@ -37,6 +37,63 @@ void CefMenuModelDelegateCToCpp::ExecuteCommand(
|
||||
event_flags);
|
||||
}
|
||||
|
||||
void CefMenuModelDelegateCToCpp::MouseOutsideMenu(
|
||||
CefRefPtr<CefMenuModel> menu_model, const CefPoint& screen_point) {
|
||||
cef_menu_model_delegate_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, mouse_outside_menu))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Verify param: menu_model; type: refptr_diff
|
||||
DCHECK(menu_model.get());
|
||||
if (!menu_model.get())
|
||||
return;
|
||||
|
||||
// Execute
|
||||
_struct->mouse_outside_menu(_struct,
|
||||
CefMenuModelCppToC::Wrap(menu_model),
|
||||
&screen_point);
|
||||
}
|
||||
|
||||
void CefMenuModelDelegateCToCpp::UnhandledOpenSubmenu(
|
||||
CefRefPtr<CefMenuModel> menu_model, bool is_rtl) {
|
||||
cef_menu_model_delegate_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, unhandled_open_submenu))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Verify param: menu_model; type: refptr_diff
|
||||
DCHECK(menu_model.get());
|
||||
if (!menu_model.get())
|
||||
return;
|
||||
|
||||
// Execute
|
||||
_struct->unhandled_open_submenu(_struct,
|
||||
CefMenuModelCppToC::Wrap(menu_model),
|
||||
is_rtl);
|
||||
}
|
||||
|
||||
void CefMenuModelDelegateCToCpp::UnhandledCloseSubmenu(
|
||||
CefRefPtr<CefMenuModel> menu_model, bool is_rtl) {
|
||||
cef_menu_model_delegate_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, unhandled_close_submenu))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Verify param: menu_model; type: refptr_diff
|
||||
DCHECK(menu_model.get());
|
||||
if (!menu_model.get())
|
||||
return;
|
||||
|
||||
// Execute
|
||||
_struct->unhandled_close_submenu(_struct,
|
||||
CefMenuModelCppToC::Wrap(menu_model),
|
||||
is_rtl);
|
||||
}
|
||||
|
||||
void CefMenuModelDelegateCToCpp::MenuWillShow(
|
||||
CefRefPtr<CefMenuModel> menu_model) {
|
||||
cef_menu_model_delegate_t* _struct = GetStruct();
|
||||
|
@ -35,6 +35,12 @@ class CefMenuModelDelegateCToCpp
|
||||
// CefMenuModelDelegate methods.
|
||||
void ExecuteCommand(CefRefPtr<CefMenuModel> menu_model, int command_id,
|
||||
cef_event_flags_t event_flags) override;
|
||||
void MouseOutsideMenu(CefRefPtr<CefMenuModel> menu_model,
|
||||
const CefPoint& screen_point) override;
|
||||
void UnhandledOpenSubmenu(CefRefPtr<CefMenuModel> menu_model,
|
||||
bool is_rtl) override;
|
||||
void UnhandledCloseSubmenu(CefRefPtr<CefMenuModel> menu_model,
|
||||
bool is_rtl) override;
|
||||
void MenuWillShow(CefRefPtr<CefMenuModel> menu_model) override;
|
||||
void MenuClosed(CefRefPtr<CefMenuModel> menu_model) override;
|
||||
bool FormatLabel(CefRefPtr<CefMenuModel> menu_model,
|
||||
|
@ -35,6 +35,24 @@ void CefButtonDelegateCToCpp::OnButtonPressed(CefRefPtr<CefButton> button) {
|
||||
CefButtonCppToC::Wrap(button));
|
||||
}
|
||||
|
||||
void CefButtonDelegateCToCpp::OnButtonStateChanged(
|
||||
CefRefPtr<CefButton> button) {
|
||||
cef_button_delegate_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, on_button_state_changed))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Verify param: button; type: refptr_diff
|
||||
DCHECK(button.get());
|
||||
if (!button.get())
|
||||
return;
|
||||
|
||||
// Execute
|
||||
_struct->on_button_state_changed(_struct,
|
||||
CefButtonCppToC::Wrap(button));
|
||||
}
|
||||
|
||||
CefSize CefButtonDelegateCToCpp::GetPreferredSize(CefRefPtr<CefView> view) {
|
||||
cef_view_delegate_t* _struct = reinterpret_cast<cef_view_delegate_t*>(
|
||||
GetStruct());
|
||||
|
@ -34,6 +34,7 @@ class CefButtonDelegateCToCpp
|
||||
|
||||
// CefButtonDelegate methods.
|
||||
void OnButtonPressed(CefRefPtr<CefButton> button) override;
|
||||
void OnButtonStateChanged(CefRefPtr<CefButton> button) override;
|
||||
|
||||
// CefViewDelegate methods.
|
||||
CefSize GetPreferredSize(CefRefPtr<CefView> view) override;
|
||||
|
@ -73,6 +73,17 @@ void CefMenuButtonCToCpp::ShowMenu(CefRefPtr<CefMenuModel> menu_model,
|
||||
anchor_position);
|
||||
}
|
||||
|
||||
void CefMenuButtonCToCpp::TriggerMenu() {
|
||||
cef_menu_button_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, trigger_menu))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Execute
|
||||
_struct->trigger_menu(_struct);
|
||||
}
|
||||
|
||||
CefRefPtr<CefMenuButton> CefMenuButtonCToCpp::AsMenuButton() {
|
||||
cef_label_button_t* _struct = reinterpret_cast<cef_label_button_t*>(GetStruct(
|
||||
));
|
||||
|
@ -34,6 +34,7 @@ class CefMenuButtonCToCpp
|
||||
void ShowMenu(CefRefPtr<CefMenuModel> menu_model,
|
||||
const CefPoint& screen_point,
|
||||
cef_menu_anchor_position_t anchor_position) OVERRIDE;
|
||||
void TriggerMenu() OVERRIDE;
|
||||
|
||||
// CefLabelButton methods.
|
||||
CefRefPtr<CefMenuButton> AsMenuButton() OVERRIDE;
|
||||
|
@ -55,6 +55,25 @@ void CefMenuButtonDelegateCToCpp::OnButtonPressed(CefRefPtr<CefButton> button) {
|
||||
CefButtonCppToC::Wrap(button));
|
||||
}
|
||||
|
||||
void CefMenuButtonDelegateCToCpp::OnButtonStateChanged(
|
||||
CefRefPtr<CefButton> button) {
|
||||
cef_button_delegate_t* _struct = reinterpret_cast<cef_button_delegate_t*>(
|
||||
GetStruct());
|
||||
if (CEF_MEMBER_MISSING(_struct, on_button_state_changed))
|
||||
return;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Verify param: button; type: refptr_diff
|
||||
DCHECK(button.get());
|
||||
if (!button.get())
|
||||
return;
|
||||
|
||||
// Execute
|
||||
_struct->on_button_state_changed(_struct,
|
||||
CefButtonCppToC::Wrap(button));
|
||||
}
|
||||
|
||||
CefSize CefMenuButtonDelegateCToCpp::GetPreferredSize(CefRefPtr<CefView> view) {
|
||||
cef_view_delegate_t* _struct = reinterpret_cast<cef_view_delegate_t*>(
|
||||
GetStruct());
|
||||
|
@ -38,6 +38,7 @@ class CefMenuButtonDelegateCToCpp
|
||||
|
||||
// CefButtonDelegate methods.
|
||||
void OnButtonPressed(CefRefPtr<CefButton> button) override;
|
||||
void OnButtonStateChanged(CefRefPtr<CefButton> button) override;
|
||||
|
||||
// CefViewDelegate methods.
|
||||
CefSize GetPreferredSize(CefRefPtr<CefView> view) override;
|
||||
|
@ -327,4 +327,10 @@ patches = [
|
||||
'name': 'plugin_info_webkit_2015',
|
||||
'path': '../third_party/WebKit/',
|
||||
},
|
||||
{
|
||||
# Expose callbacks for mouse/keyboard events that trigger menu switching.
|
||||
# https://bitbucket.org/chromiumembedded/cef/issues/2102
|
||||
'name': 'views_menu_2102',
|
||||
'path': '../',
|
||||
},
|
||||
]
|
||||
|
147
patch/patches/views_menu_2102.patch
Normal file
147
patch/patches/views_menu_2102.patch
Normal file
@ -0,0 +1,147 @@
|
||||
diff --git ui/base/models/menu_model.h ui/base/models/menu_model.h
|
||||
index 0755f27..72db677 100644
|
||||
--- ui/base/models/menu_model.h
|
||||
+++ ui/base/models/menu_model.h
|
||||
@@ -15,6 +15,7 @@
|
||||
namespace gfx {
|
||||
class FontList;
|
||||
class Image;
|
||||
+class Point;
|
||||
}
|
||||
|
||||
namespace ui {
|
||||
@@ -115,6 +116,15 @@ class UI_BASE_EXPORT MenuModel {
|
||||
// |event_flags| is a bit mask of ui::EventFlags.
|
||||
virtual void ActivatedAt(int index, int event_flags);
|
||||
|
||||
+ // Called when the user moves the mouse outside the menu and over the owning
|
||||
+ // window.
|
||||
+ virtual void MouseOutsideMenu(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(bool is_rtl) {}
|
||||
+ virtual void UnhandledCloseSubmenu(bool is_rtl) {}
|
||||
+
|
||||
// Called when the menu is about to be shown.
|
||||
virtual void MenuWillShow() {}
|
||||
|
||||
diff --git ui/views/controls/menu/menu_controller.cc ui/views/controls/menu/menu_controller.cc
|
||||
index 79ff77c..a0582c0 100644
|
||||
--- ui/views/controls/menu/menu_controller.cc
|
||||
+++ ui/views/controls/menu/menu_controller.cc
|
||||
@@ -2254,8 +2254,13 @@ MenuItemView* MenuController::FindNextSelectableMenuItem(
|
||||
|
||||
void MenuController::OpenSubmenuChangeSelectionIfCan() {
|
||||
MenuItemView* item = pending_state_.item;
|
||||
- if (!item->HasSubmenu() || !item->enabled())
|
||||
+ if (!item->HasSubmenu() || !item->enabled() || !item->GetParentMenuItem()) {
|
||||
+ MenuItemView* submenu_item =
|
||||
+ item->GetParentMenuItem() ? item->GetParentMenuItem() : item;
|
||||
+ submenu_item->GetDelegate()->OnUnhandledOpenSubmenu(submenu_item,
|
||||
+ base::i18n::IsRTL());
|
||||
return;
|
||||
+ }
|
||||
MenuItemView* to_select = NULL;
|
||||
if (item->GetSubmenu()->GetMenuItemCount() > 0)
|
||||
to_select = FindInitialSelectableMenuItem(item, INCREMENT_SELECTION_DOWN);
|
||||
@@ -2270,8 +2275,10 @@ void MenuController::OpenSubmenuChangeSelectionIfCan() {
|
||||
void MenuController::CloseSubmenu() {
|
||||
MenuItemView* item = state_.item;
|
||||
DCHECK(item);
|
||||
- if (!item->GetParentMenuItem())
|
||||
+ if (!item->GetParentMenuItem()) {
|
||||
+ item->GetDelegate()->OnUnhandledCloseSubmenu(item, base::i18n::IsRTL());
|
||||
return;
|
||||
+ }
|
||||
if (item->HasSubmenu() && item->GetSubmenu()->IsShowing())
|
||||
SetSelection(item, SELECTION_UPDATE_IMMEDIATELY);
|
||||
else if (item->GetParentMenuItem()->GetParentMenuItem())
|
||||
diff --git ui/views/controls/menu/menu_delegate.h ui/views/controls/menu/menu_delegate.h
|
||||
index 3b7cb7f..3ad68d0 100644
|
||||
--- ui/views/controls/menu/menu_delegate.h
|
||||
+++ ui/views/controls/menu/menu_delegate.h
|
||||
@@ -229,6 +229,11 @@ class VIEWS_EXPORT MenuDelegate {
|
||||
bool* has_mnemonics,
|
||||
MenuButton** button);
|
||||
|
||||
+ // 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 OnUnhandledOpenSubmenu(MenuItemView* menu, bool is_rtl) {}
|
||||
+ virtual void OnUnhandledCloseSubmenu(MenuItemView* menu, bool is_rtl) {}
|
||||
+
|
||||
// Returns the max width menus can grow to be.
|
||||
virtual int GetMaxWidthForMenu(MenuItemView* menu);
|
||||
|
||||
diff --git ui/views/controls/menu/menu_model_adapter.cc ui/views/controls/menu/menu_model_adapter.cc
|
||||
index bc04dcb..b2ec114 100644
|
||||
--- ui/views/controls/menu/menu_model_adapter.cc
|
||||
+++ ui/views/controls/menu/menu_model_adapter.cc
|
||||
@@ -245,6 +245,49 @@ void MenuModelAdapter::SelectionChanged(MenuItemView* menu) {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
+MenuItemView* MenuModelAdapter::GetSiblingMenu(MenuItemView* menu,
|
||||
+ const gfx::Point& screen_point,
|
||||
+ MenuAnchorPosition* anchor,
|
||||
+ bool* has_mnemonics,
|
||||
+ MenuButton** button) {
|
||||
+ // Look up the menu model for this menu.
|
||||
+ const std::map<MenuItemView*, ui::MenuModel*>::const_iterator map_iterator =
|
||||
+ menu_map_.find(menu);
|
||||
+ if (map_iterator != menu_map_.end()) {
|
||||
+ map_iterator->second->MouseOutsideMenu(screen_point);
|
||||
+ return nullptr;
|
||||
+ }
|
||||
+
|
||||
+ NOTREACHED();
|
||||
+ return nullptr;
|
||||
+}
|
||||
+
|
||||
+void MenuModelAdapter::OnUnhandledOpenSubmenu(MenuItemView* menu,
|
||||
+ bool is_rtl) {
|
||||
+ // Look up the menu model for this menu.
|
||||
+ const std::map<MenuItemView*, ui::MenuModel*>::const_iterator map_iterator =
|
||||
+ menu_map_.find(menu);
|
||||
+ if (map_iterator != menu_map_.end()) {
|
||||
+ map_iterator->second->UnhandledOpenSubmenu(is_rtl);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ NOTREACHED();
|
||||
+}
|
||||
+
|
||||
+void MenuModelAdapter::OnUnhandledCloseSubmenu(MenuItemView* menu,
|
||||
+ bool is_rtl) {
|
||||
+ // Look up the menu model for this menu.
|
||||
+ const std::map<MenuItemView*, ui::MenuModel*>::const_iterator map_iterator =
|
||||
+ menu_map_.find(menu);
|
||||
+ if (map_iterator != menu_map_.end()) {
|
||||
+ map_iterator->second->UnhandledCloseSubmenu(is_rtl);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ NOTREACHED();
|
||||
+}
|
||||
+
|
||||
void MenuModelAdapter::WillShowMenu(MenuItemView* menu) {
|
||||
// Look up the menu model for this menu.
|
||||
const std::map<MenuItemView*, ui::MenuModel*>::const_iterator map_iterator =
|
||||
diff --git ui/views/controls/menu/menu_model_adapter.h ui/views/controls/menu/menu_model_adapter.h
|
||||
index c9799da..c7ecca6 100644
|
||||
--- ui/views/controls/menu/menu_model_adapter.h
|
||||
+++ ui/views/controls/menu/menu_model_adapter.h
|
||||
@@ -76,6 +76,13 @@ class VIEWS_EXPORT MenuModelAdapter : public MenuDelegate {
|
||||
bool IsCommandVisible(int id) const override;
|
||||
bool IsItemChecked(int id) const override;
|
||||
void SelectionChanged(MenuItemView* menu) override;
|
||||
+ MenuItemView* GetSiblingMenu(MenuItemView* menu,
|
||||
+ const gfx::Point& screen_point,
|
||||
+ MenuAnchorPosition* anchor,
|
||||
+ bool* has_mnemonics,
|
||||
+ MenuButton** button) override;
|
||||
+ void OnUnhandledOpenSubmenu(MenuItemView* menu, bool is_rtl) override;
|
||||
+ void OnUnhandledCloseSubmenu(MenuItemView* menu, bool is_rtl) override;
|
||||
void WillShowMenu(MenuItemView* menu) override;
|
||||
void WillHideMenu(MenuItemView* menu) override;
|
||||
void OnMenuClosed(MenuItemView* menu, MenuRunner::RunResult result) override;
|
230
tests/cefclient/browser/views_menu_bar.cc
Normal file
230
tests/cefclient/browser/views_menu_bar.cc
Normal file
@ -0,0 +1,230 @@
|
||||
// Copyright (c) 2017 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#include "tests/cefclient/browser/views_menu_bar.h"
|
||||
|
||||
#include "include/views/cef_box_layout.h"
|
||||
#include "include/views/cef_window.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
const int kMenuBarGroupId = 100;
|
||||
|
||||
} // namespace
|
||||
|
||||
ViewsMenuBar::ViewsMenuBar(Delegate* delegate,
|
||||
int menu_id_start)
|
||||
: delegate_(delegate),
|
||||
id_start_(menu_id_start),
|
||||
id_next_(menu_id_start),
|
||||
last_nav_with_keyboard_(false) {
|
||||
DCHECK(delegate_);
|
||||
DCHECK_GT(id_start_, 0);
|
||||
}
|
||||
|
||||
bool ViewsMenuBar::HasMenuId(int menu_id) const {
|
||||
return menu_id >= id_start_ && menu_id < id_next_;
|
||||
}
|
||||
|
||||
CefRefPtr<CefPanel> ViewsMenuBar::GetMenuPanel() {
|
||||
EnsureMenuPanel();
|
||||
return panel_;
|
||||
}
|
||||
|
||||
CefRefPtr<CefMenuModel> ViewsMenuBar::CreateMenuModel(const std::string& label,
|
||||
int* menu_id) {
|
||||
EnsureMenuPanel();
|
||||
|
||||
// Assign the new menu ID.
|
||||
const int new_menu_id = id_next_++;
|
||||
if (menu_id)
|
||||
*menu_id = new_menu_id;
|
||||
|
||||
// Create the new MenuModel.
|
||||
CefRefPtr<CefMenuModel> model = CefMenuModel::CreateMenuModel(this);
|
||||
models_.push_back(model);
|
||||
|
||||
// Create the new MenuButton.
|
||||
CefRefPtr<CefMenuButton> button =
|
||||
CefMenuButton::CreateMenuButton(this, label, false, false);
|
||||
button->SetID(new_menu_id);
|
||||
|
||||
// Assign a group ID to allow focus traversal between MenuButtons using the
|
||||
// arrow keys when the menu is not displayed.
|
||||
button->SetGroupID(kMenuBarGroupId);
|
||||
|
||||
// Add the new MenuButton to the Planel.
|
||||
panel_->AddChildView(button);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
CefRefPtr<CefMenuModel> ViewsMenuBar::GetMenuModel(int menu_id) const {
|
||||
if (HasMenuId(menu_id))
|
||||
return models_[menu_id - id_start_];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ViewsMenuBar::SetMenuFocusable(bool focusable) {
|
||||
if (!panel_)
|
||||
return;
|
||||
|
||||
for (int id = id_start_; id < id_next_; ++id)
|
||||
panel_->GetViewForID(id)->SetFocusable(focusable);
|
||||
|
||||
if (focusable) {
|
||||
// Give focus to the first MenuButton.
|
||||
panel_->GetViewForID(id_start_)->RequestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewsMenuBar::Reset() {
|
||||
panel_ = NULL;
|
||||
models_.clear();
|
||||
id_next_ = id_start_;
|
||||
}
|
||||
|
||||
void ViewsMenuBar::OnMenuButtonPressed(CefRefPtr<CefMenuButton> menu_button,
|
||||
const CefPoint& screen_point) {
|
||||
CefRefPtr<CefMenuModel> menu_model = GetMenuModel(menu_button->GetID());
|
||||
|
||||
// Adjust menu position left by button width.
|
||||
CefPoint point = screen_point;
|
||||
point.x -= menu_button->GetBounds().width - 4;
|
||||
|
||||
// Keep track of the current |last_nav_with_keyboard_| status and restore it
|
||||
// after displaying the new menu.
|
||||
bool cur_last_nav_with_keyboard = last_nav_with_keyboard_;
|
||||
|
||||
// May result in the previous menu being closed, in which case MenuClosed will
|
||||
// be called before the new menu is displayed.
|
||||
menu_button->ShowMenu(menu_model, point, CEF_MENU_ANCHOR_TOPLEFT);
|
||||
|
||||
last_nav_with_keyboard_ = cur_last_nav_with_keyboard;
|
||||
}
|
||||
|
||||
void ViewsMenuBar::ExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
|
||||
int command_id,
|
||||
cef_event_flags_t event_flags) {
|
||||
delegate_->MenuBarExecuteCommand(menu_model, command_id, event_flags);
|
||||
}
|
||||
|
||||
void ViewsMenuBar::MouseOutsideMenu(CefRefPtr<CefMenuModel> menu_model,
|
||||
const CefPoint& screen_point) {
|
||||
DCHECK(panel_);
|
||||
|
||||
// Retrieve the Window hosting the Panel.
|
||||
CefRefPtr<CefWindow> window = panel_->GetWindow();
|
||||
DCHECK(window);
|
||||
|
||||
// Convert the point from screen to window coordinates.
|
||||
CefPoint window_point = screen_point;
|
||||
if (!window->ConvertPointFromScreen(window_point))
|
||||
return;
|
||||
|
||||
CefRect panel_bounds = panel_->GetBounds();
|
||||
|
||||
if (last_nav_with_keyboard_) {
|
||||
// The user navigated last using the keyboard. Don't change menus using
|
||||
// mouse movements until the mouse exits and re-enters the Panel.
|
||||
if (panel_bounds.Contains(window_point))
|
||||
return;
|
||||
last_nav_with_keyboard_ = false;
|
||||
}
|
||||
|
||||
// Check that the point is inside the Panel.
|
||||
if (!panel_bounds.Contains(window_point))
|
||||
return;
|
||||
|
||||
const int active_menu_id = GetActiveMenuId();
|
||||
|
||||
// Determine which MenuButton is under the specified point.
|
||||
for (int id = id_start_; id < id_next_; ++id) {
|
||||
// Skip the currently active MenuButton.
|
||||
if (id == active_menu_id)
|
||||
continue;
|
||||
|
||||
CefRefPtr<CefView> button = panel_->GetViewForID(id);
|
||||
CefRect button_bounds = button->GetBounds();
|
||||
if (button_bounds.Contains(window_point)) {
|
||||
// Trigger the hovered MenuButton.
|
||||
TriggerMenuButton(button);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ViewsMenuBar::UnhandledOpenSubmenu(CefRefPtr<CefMenuModel> menu_model,
|
||||
bool is_rtl) {
|
||||
TriggerNextMenu(is_rtl ? 1 : -1);
|
||||
}
|
||||
|
||||
void ViewsMenuBar::UnhandledCloseSubmenu(CefRefPtr<CefMenuModel> menu_model,
|
||||
bool is_rtl) {
|
||||
TriggerNextMenu(is_rtl ? -1 : 1);
|
||||
}
|
||||
|
||||
void ViewsMenuBar::MenuClosed(CefRefPtr<CefMenuModel> menu_model) {
|
||||
// Reset |last_nav_with_keyboard_| status whenever the main menu closes.
|
||||
if (!menu_model->IsSubMenu() && last_nav_with_keyboard_)
|
||||
last_nav_with_keyboard_ = false;
|
||||
}
|
||||
|
||||
void ViewsMenuBar::EnsureMenuPanel() {
|
||||
if (panel_)
|
||||
return;
|
||||
|
||||
panel_ = CefPanel::CreatePanel(NULL);
|
||||
|
||||
// Use a horizontal box layout.
|
||||
CefBoxLayoutSettings top_panel_layout_settings;
|
||||
top_panel_layout_settings.horizontal = true;
|
||||
panel_->SetToBoxLayout(top_panel_layout_settings);
|
||||
}
|
||||
|
||||
int ViewsMenuBar::GetActiveMenuId() {
|
||||
DCHECK(panel_);
|
||||
|
||||
for (int id = id_start_; id < id_next_; ++id) {
|
||||
CefRefPtr<CefButton> button = panel_->GetViewForID(id)->AsButton();
|
||||
if (button->GetState() == CEF_BUTTON_STATE_PRESSED)
|
||||
return id;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ViewsMenuBar::TriggerNextMenu(int offset) {
|
||||
DCHECK(panel_);
|
||||
|
||||
const int active_menu_id = GetActiveMenuId();
|
||||
const int menu_count = id_next_ - id_start_;
|
||||
const int active_menu_index = active_menu_id - id_start_;
|
||||
|
||||
// Compute the modulus to avoid negative values.
|
||||
int next_menu_index = (active_menu_index + offset) % menu_count;
|
||||
if (next_menu_index < 0)
|
||||
next_menu_index += menu_count;
|
||||
|
||||
// Cancel the existing menu. MenuClosed may be called.
|
||||
panel_->GetWindow()->CancelMenu();
|
||||
|
||||
// Set status indicating that we navigated using the keyboard.
|
||||
last_nav_with_keyboard_ = true;
|
||||
|
||||
// Show the new menu.
|
||||
TriggerMenuButton(panel_->GetViewForID(id_start_ + next_menu_index));
|
||||
}
|
||||
|
||||
void ViewsMenuBar::TriggerMenuButton(CefRefPtr<CefView> button) {
|
||||
CefRefPtr<CefMenuButton> menu_button =
|
||||
button->AsButton()->AsLabelButton()->AsMenuButton();
|
||||
if (menu_button->IsFocusable())
|
||||
menu_button->RequestFocus();
|
||||
menu_button->TriggerMenu();
|
||||
}
|
||||
|
||||
} // namespace client
|
116
tests/cefclient/browser/views_menu_bar.h
Normal file
116
tests/cefclient/browser/views_menu_bar.h
Normal file
@ -0,0 +1,116 @@
|
||||
// Copyright (c) 2017 The Chromium Embedded Framework 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_TESTS_CEFCLIENT_BROWSER_VIEWS_MENU_BAR_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_VIEWS_MENU_BAR_H_
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "include/cef_menu_model.h"
|
||||
#include "include/cef_menu_model_delegate.h"
|
||||
#include "include/views/cef_menu_button.h"
|
||||
#include "include/views/cef_menu_button_delegate.h"
|
||||
#include "include/views/cef_panel.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Implements a menu bar which is composed of CefMenuButtons positioned in a
|
||||
// row with automatic switching between them via mouse/keyboard. All methods
|
||||
// must be called on the browser process UI thread.
|
||||
class ViewsMenuBar : public CefMenuButtonDelegate,
|
||||
public CefMenuModelDelegate {
|
||||
public:
|
||||
// Delegate methods will be called on the browser process UI thread.
|
||||
class Delegate {
|
||||
public:
|
||||
// Called when a menu command is selected.
|
||||
virtual void MenuBarExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
|
||||
int command_id,
|
||||
cef_event_flags_t event_flags) =0;
|
||||
|
||||
protected:
|
||||
virtual ~Delegate() {}
|
||||
};
|
||||
|
||||
// |delegate| must outlive this object.
|
||||
// |menu_id_start| is the ID for the first CefMenuButton in the bar. An ID
|
||||
// range starting with |menu_id_start| and extending for a reasonable distance
|
||||
// should be reserved in the client for MenuBar usage.
|
||||
ViewsMenuBar(Delegate* delegate,
|
||||
int menu_id_start);
|
||||
|
||||
// Returns true if |menu_id| exists in the menu bar.
|
||||
bool HasMenuId(int menu_id) const;
|
||||
|
||||
// Returns the CefPanel that represents the menu bar.
|
||||
CefRefPtr<CefPanel> GetMenuPanel();
|
||||
|
||||
// Create a new menu with the specified |label|. If |menu_id| is non-NULL it
|
||||
// will be populated with the new menu ID.
|
||||
CefRefPtr<CefMenuModel> CreateMenuModel(const std::string& label,
|
||||
int* menu_id);
|
||||
|
||||
// Returns the menu with the specified |menu_id|, or NULL if no such menu
|
||||
// exists.
|
||||
CefRefPtr<CefMenuModel> GetMenuModel(int menu_id) const;
|
||||
|
||||
// Assign or remove focus from the menu bar.
|
||||
// Focus is assigned to the menu bar by ViewsWindow::OnKeyEvent when the ALT
|
||||
// key is pressed. Focus is removed from the menu bar by ViewsWindow::OnFocus
|
||||
// when a control not in the menu bar gains focus.
|
||||
void SetMenuFocusable(bool focusable);
|
||||
|
||||
// Reset menu bar state.
|
||||
void Reset();
|
||||
|
||||
protected:
|
||||
// CefButtonDelegate methods:
|
||||
void OnButtonPressed(CefRefPtr<CefButton> button) OVERRIDE {}
|
||||
|
||||
// CefMenuButtonDelegate methods:
|
||||
void OnMenuButtonPressed(CefRefPtr<CefMenuButton> menu_button,
|
||||
const CefPoint& screen_point) OVERRIDE;
|
||||
|
||||
// CefMenuModelDelegate methods:
|
||||
void ExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
|
||||
int command_id,
|
||||
cef_event_flags_t event_flags) OVERRIDE;
|
||||
void MouseOutsideMenu(CefRefPtr<CefMenuModel> menu_model,
|
||||
const CefPoint& screen_point) OVERRIDE;
|
||||
void UnhandledOpenSubmenu(CefRefPtr<CefMenuModel> menu_model,
|
||||
bool is_rtl) OVERRIDE;
|
||||
void UnhandledCloseSubmenu(CefRefPtr<CefMenuModel> menu_model,
|
||||
bool is_rtl) OVERRIDE;
|
||||
void MenuClosed(CefRefPtr<CefMenuModel> menu_model) OVERRIDE;
|
||||
|
||||
private:
|
||||
// Creates the menu panel if it doesn't already exist.
|
||||
void EnsureMenuPanel();
|
||||
|
||||
// Returns the ID for the currently active menu, or -1 if no menu is currently
|
||||
// active.
|
||||
int GetActiveMenuId();
|
||||
|
||||
// Triggers the menu at the specified |offset| from the currently active menu.
|
||||
void TriggerNextMenu(int offset);
|
||||
|
||||
// Triggers the specified MenuButton |button|.
|
||||
void TriggerMenuButton(CefRefPtr<CefView> button);
|
||||
|
||||
Delegate* delegate_; // Not owned by this object.
|
||||
const int id_start_;
|
||||
int id_next_;
|
||||
CefRefPtr<CefPanel> panel_;
|
||||
std::vector<CefRefPtr<CefMenuModel> > models_;
|
||||
bool last_nav_with_keyboard_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(ViewsMenuBar);
|
||||
DISALLOW_COPY_AND_ASSIGN(ViewsMenuBar);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_VIEWS_MENU_BAR_H_
|
@ -34,8 +34,10 @@ enum ControlIds {
|
||||
ID_RELOAD_BUTTON,
|
||||
ID_URL_TEXTFIELD,
|
||||
ID_MENU_BUTTON,
|
||||
ID_TOP_FILE_MENU_BUTTON,
|
||||
ID_TOP_TEST_MENU_BUTTON,
|
||||
|
||||
// Reserved range of top menu button IDs.
|
||||
ID_TOP_MENU_FIRST,
|
||||
ID_TOP_MENU_LAST = ID_TOP_MENU_FIRST + 10,
|
||||
};
|
||||
|
||||
typedef std::vector<CefRefPtr<CefLabelButton> > LabelButtons;
|
||||
@ -301,31 +303,10 @@ void ViewsWindow::OnMenuButtonPressed(CefRefPtr<CefMenuButton> menu_button,
|
||||
const CefPoint& screen_point) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
DCHECK(with_controls_);
|
||||
DCHECK_EQ(ID_MENU_BUTTON, menu_button->GetID());
|
||||
|
||||
CefRefPtr<CefMenuModel> menu_model;
|
||||
cef_menu_anchor_position_t position = CEF_MENU_ANCHOR_TOPLEFT;
|
||||
|
||||
switch (menu_button->GetID()) {
|
||||
case ID_MENU_BUTTON:
|
||||
menu_model = button_menu_model_;
|
||||
position = CEF_MENU_ANCHOR_TOPRIGHT;
|
||||
break;
|
||||
case ID_TOP_FILE_MENU_BUTTON:
|
||||
menu_model = file_menu_model_;
|
||||
break;
|
||||
case ID_TOP_TEST_MENU_BUTTON:
|
||||
menu_model = test_menu_model_;
|
||||
break;
|
||||
}
|
||||
|
||||
CefPoint point = screen_point;
|
||||
if (position == CEF_MENU_ANCHOR_TOPLEFT) {
|
||||
// Adjust menu position left by button width.
|
||||
point.x -= menu_button->GetBounds().width - 4;
|
||||
}
|
||||
|
||||
if (menu_model)
|
||||
menu_button->ShowMenu(menu_model, point, position);
|
||||
menu_button->ShowMenu(button_menu_model_, screen_point,
|
||||
CEF_MENU_ANCHOR_TOPRIGHT);
|
||||
}
|
||||
|
||||
void ViewsWindow::ExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
|
||||
@ -430,8 +411,10 @@ void ViewsWindow::OnWindowDestroyed(CefRefPtr<CefWindow> window) {
|
||||
|
||||
browser_view_ = NULL;
|
||||
button_menu_model_ = NULL;
|
||||
file_menu_model_ = NULL;
|
||||
test_menu_model_ = NULL;
|
||||
if (top_menu_bar_) {
|
||||
top_menu_bar_->Reset();
|
||||
top_menu_bar_ = NULL;
|
||||
}
|
||||
window_ = NULL;
|
||||
}
|
||||
|
||||
@ -492,17 +475,21 @@ void ViewsWindow::OnFocus(CefRefPtr<CefView> view) {
|
||||
// When focus leaves the menu buttons make them unfocusable.
|
||||
if (menu_has_focus_) {
|
||||
const int view_id = view->GetID();
|
||||
if (with_top_menu_) {
|
||||
if (view_id != ID_TOP_FILE_MENU_BUTTON &&
|
||||
view_id != ID_TOP_TEST_MENU_BUTTON) {
|
||||
if (top_menu_bar_) {
|
||||
if (!top_menu_bar_->HasMenuId(view_id))
|
||||
SetMenuFocusable(false);
|
||||
}
|
||||
} else if (view_id != ID_MENU_BUTTON) {
|
||||
SetMenuFocusable(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ViewsWindow::MenuBarExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
|
||||
int command_id,
|
||||
cef_event_flags_t event_flags) {
|
||||
ExecuteCommand(menu_model, command_id, event_flags);
|
||||
}
|
||||
|
||||
ViewsWindow::ViewsWindow(Delegate* delegate,
|
||||
CefRefPtr<CefBrowserView> browser_view)
|
||||
: delegate_(delegate),
|
||||
@ -515,7 +502,9 @@ ViewsWindow::ViewsWindow(Delegate* delegate,
|
||||
CefRefPtr<CefCommandLine> command_line =
|
||||
CefCommandLine::GetGlobalCommandLine();
|
||||
frameless_ = command_line->HasSwitch(switches::kHideFrame);
|
||||
with_top_menu_ = command_line->HasSwitch(switches::kShowTopMenu);
|
||||
|
||||
if (!command_line->HasSwitch(switches::kHideTopMenu))
|
||||
top_menu_bar_ = new ViewsMenuBar(this, ID_TOP_MENU_FIRST);
|
||||
}
|
||||
|
||||
void ViewsWindow::SetBrowserView(CefRefPtr<CefBrowserView> browser_view) {
|
||||
@ -534,26 +523,13 @@ void ViewsWindow::CreateMenuModel() {
|
||||
AddTestMenuItems(test_menu);
|
||||
AddFileMenuItems(button_menu_model_, 1);
|
||||
|
||||
if (with_top_menu_) {
|
||||
// Create the top menu model.
|
||||
file_menu_model_ = CefMenuModel::CreateMenuModel(this);
|
||||
AddFileMenuItems(file_menu_model_, 0);
|
||||
test_menu_model_ = CefMenuModel::CreateMenuModel(this);
|
||||
AddTestMenuItems(test_menu_model_);
|
||||
if (top_menu_bar_) {
|
||||
// Add the menus to the top menu bar.
|
||||
AddFileMenuItems(top_menu_bar_->CreateMenuModel("File", NULL), 0);
|
||||
AddTestMenuItems(top_menu_bar_->CreateMenuModel("Tests", NULL));
|
||||
}
|
||||
}
|
||||
|
||||
CefRefPtr<CefMenuButton> ViewsWindow::CreateTopMenuButton(
|
||||
const std::string& label, int id) {
|
||||
CefRefPtr<CefMenuButton> button =
|
||||
CefMenuButton::CreateMenuButton(this, label, false, false);
|
||||
button->SetID(id);
|
||||
// Assign a group ID to allow focus traversal between top menu buttons using
|
||||
// the arrow keys.
|
||||
button->SetGroupID(1);
|
||||
return button;
|
||||
}
|
||||
|
||||
CefRefPtr<CefLabelButton> ViewsWindow::CreateBrowseButton(
|
||||
const std::string& label,
|
||||
int id) {
|
||||
@ -570,25 +546,8 @@ void ViewsWindow::AddControls() {
|
||||
CreateMenuModel();
|
||||
|
||||
CefRefPtr<CefPanel> top_menu_panel;
|
||||
if (with_top_menu_) {
|
||||
// Create the top menu buttons.
|
||||
CefRefPtr<CefMenuButton> top_file_menu_button =
|
||||
CreateTopMenuButton("File", ID_TOP_FILE_MENU_BUTTON);
|
||||
CefRefPtr<CefMenuButton> top_test_menu_button =
|
||||
CreateTopMenuButton("Test", ID_TOP_TEST_MENU_BUTTON);
|
||||
|
||||
// Create the top menu panel.
|
||||
top_menu_panel = CefPanel::CreatePanel(NULL);
|
||||
|
||||
// Use a horizontal box layout for |top_panel|.
|
||||
CefBoxLayoutSettings top_panel_layout_settings;
|
||||
top_panel_layout_settings.horizontal = true;
|
||||
CefRefPtr<CefBoxLayout> top_panel_layout =
|
||||
top_menu_panel->SetToBoxLayout(top_panel_layout_settings);
|
||||
|
||||
top_menu_panel->AddChildView(top_file_menu_button);
|
||||
top_menu_panel->AddChildView(top_test_menu_button);
|
||||
}
|
||||
if (top_menu_bar_)
|
||||
top_menu_panel = top_menu_bar_->GetMenuPanel();
|
||||
|
||||
// Create the browse buttons.
|
||||
LabelButtons browse_buttons;
|
||||
@ -677,14 +636,8 @@ void ViewsWindow::SetMenuFocusable(bool focusable) {
|
||||
if (!window_ || !with_controls_)
|
||||
return;
|
||||
|
||||
if (with_top_menu_) {
|
||||
window_->GetViewForID(ID_TOP_FILE_MENU_BUTTON)->SetFocusable(focusable);
|
||||
window_->GetViewForID(ID_TOP_TEST_MENU_BUTTON)->SetFocusable(focusable);
|
||||
|
||||
if (focusable) {
|
||||
// Give focus to top file menu button.
|
||||
window_->GetViewForID(ID_TOP_FILE_MENU_BUTTON)->RequestFocus();
|
||||
}
|
||||
if (top_menu_bar_) {
|
||||
top_menu_bar_->SetMenuFocusable(focusable);
|
||||
} else {
|
||||
window_->GetViewForID(ID_MENU_BUTTON)->SetFocusable(focusable);
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "include/views/cef_textfield_delegate.h"
|
||||
#include "include/views/cef_window.h"
|
||||
#include "include/views/cef_window_delegate.h"
|
||||
#include "tests/cefclient/browser/views_menu_bar.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
@ -29,7 +30,8 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
public CefMenuButtonDelegate,
|
||||
public CefMenuModelDelegate,
|
||||
public CefTextfieldDelegate,
|
||||
public CefWindowDelegate {
|
||||
public CefWindowDelegate,
|
||||
public ViewsMenuBar::Delegate {
|
||||
public:
|
||||
// Delegate methods will be called on the browser process UI thread.
|
||||
class Delegate {
|
||||
@ -120,6 +122,11 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
CefSize GetMinimumSize(CefRefPtr<CefView> view) OVERRIDE;
|
||||
void OnFocus(CefRefPtr<CefView> view) OVERRIDE;
|
||||
|
||||
// ViewsMenuBar::Delegate methods:
|
||||
void MenuBarExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
|
||||
int command_id,
|
||||
cef_event_flags_t event_flags) OVERRIDE;
|
||||
|
||||
private:
|
||||
// |delegate| is guaranteed to outlive this object.
|
||||
// |browser_view| may be NULL, in which case SetBrowserView() will be called.
|
||||
@ -130,8 +137,6 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
|
||||
// Create controls.
|
||||
void CreateMenuModel();
|
||||
CefRefPtr<CefMenuButton> CreateTopMenuButton(const std::string& label,
|
||||
int id);
|
||||
CefRefPtr<CefLabelButton> CreateBrowseButton(const std::string& label,
|
||||
int id);
|
||||
|
||||
@ -154,12 +159,10 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
||||
CefRefPtr<CefBrowserView> browser_view_;
|
||||
bool frameless_;
|
||||
bool with_controls_;
|
||||
bool with_top_menu_;
|
||||
CefRefPtr<CefWindow> window_;
|
||||
|
||||
CefRefPtr<CefMenuModel> button_menu_model_;
|
||||
CefRefPtr<CefMenuModel> file_menu_model_;
|
||||
CefRefPtr<CefMenuModel> test_menu_model_;
|
||||
CefRefPtr<ViewsMenuBar> top_menu_bar_;
|
||||
bool menu_has_focus_;
|
||||
|
||||
CefSize minimum_window_size_;
|
||||
|
@ -34,7 +34,7 @@ const char kFilterURL[] = "filter-url";
|
||||
const char kUseViews[] = "use-views";
|
||||
const char kHideFrame[] = "hide-frame";
|
||||
const char kHideControls[] = "hide-controls";
|
||||
const char kShowTopMenu[] = "show-top-menu";
|
||||
const char kHideTopMenu[] = "hide-top-menu";
|
||||
const char kWidevineCdmPath[] = "widevine-cdm-path";
|
||||
const char kSslClientCertificate[] = "ssl-client-certificate";
|
||||
|
||||
|
@ -28,7 +28,7 @@ extern const char kFilterURL[];
|
||||
extern const char kUseViews[];
|
||||
extern const char kHideFrame[];
|
||||
extern const char kHideControls[];
|
||||
extern const char kShowTopMenu[];
|
||||
extern const char kHideTopMenu[];
|
||||
extern const char kWidevineCdmPath[];
|
||||
extern const char kSslClientCertificate[];
|
||||
|
||||
|
Reference in New Issue
Block a user