diff --git a/cef_paths2.gypi b/cef_paths2.gypi index 0b7359706..c6ea90713 100644 --- a/cef_paths2.gypi +++ b/cef_paths2.gypi @@ -301,6 +301,8 @@ '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_style.cc', + 'tests/cefclient/browser/views_style.h', 'tests/cefclient/browser/views_window.cc', 'tests/cefclient/browser/views_window.h', 'tests/cefclient/browser/window_test_runner_views.cc', @@ -354,6 +356,8 @@ '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_style.cc', + 'tests/cefclient/browser/views_style.h', 'tests/cefclient/browser/views_window.cc', 'tests/cefclient/browser/views_window.h', 'tests/cefclient/browser/window_test_runner_gtk.cc', diff --git a/include/capi/cef_menu_model_capi.h b/include/capi/cef_menu_model_capi.h index 762aeff0a..e578abe71 100644 --- a/include/capi/cef_menu_model_capi.h +++ b/include/capi/cef_menu_model_capi.h @@ -384,6 +384,73 @@ typedef struct _cef_menu_model_t { int (CEF_CALLBACK *get_accelerator_at)(struct _cef_menu_model_t* self, int index, int* key_code, int* shift_pressed, int* ctrl_pressed, int* alt_pressed); + + /// + // Set the explicit color for |command_id| and |color_type| to |color|. + // Specify a |color| value of 0 to remove the explicit color. If no explicit + // color or default color is set for |color_type| then the system color will + // be used. Returns true (1) on success. + /// + int (CEF_CALLBACK *set_color)(struct _cef_menu_model_t* self, int command_id, + cef_menu_color_type_t color_type, cef_color_t color); + + /// + // Set the explicit color for |command_id| and |index| to |color|. Specify a + // |color| value of 0 to remove the explicit color. Specify an |index| value + // of -1 to set the default color for items that do not have an explicit color + // set. If no explicit color or default color is set for |color_type| then the + // system color will be used. Returns true (1) on success. + /// + int (CEF_CALLBACK *set_color_at)(struct _cef_menu_model_t* self, int index, + cef_menu_color_type_t color_type, cef_color_t color); + + /// + // Returns in |color| the color that was explicitly set for |command_id| and + // |color_type|. If a color was not set then 0 will be returned in |color|. + // Returns true (1) on success. + /// + int (CEF_CALLBACK *get_color)(struct _cef_menu_model_t* self, int command_id, + cef_menu_color_type_t color_type, cef_color_t* color); + + /// + // Returns in |color| the color that was explicitly set for |command_id| and + // |color_type|. Specify an |index| value of -1 to return the default color in + // |color|. If a color was not set then 0 will be returned in |color|. Returns + // true (1) on success. + /// + int (CEF_CALLBACK *get_color_at)(struct _cef_menu_model_t* self, int index, + cef_menu_color_type_t color_type, cef_color_t* color); + + /// + // Sets the font list for the specified |command_id|. If |font_list| is NULL + // the system font will be used. Returns true (1) on success. The format is + // ",[STYLES] ", where: - FONT_FAMILY_LIST is a comma- + // separated list of font family names, - STYLES is an optional space- + // separated list of style names (case-sensitive + // "Bold" and "Italic" are supported), and + // - SIZE is an integer font size in pixels with the suffix "px". + // + // Here are examples of valid font description strings: - "Arial, Helvetica, + // Bold Italic 14px" - "Arial, 14px" + /// + int (CEF_CALLBACK *set_font_list)(struct _cef_menu_model_t* self, + int command_id, const cef_string_t* font_list); + + /// + // Sets the font list for the specified |index|. Specify an |index| value of + // -1 to set the default font. If |font_list| is NULL the system font will be + // used. Returns true (1) on success. The format is + // ",[STYLES] ", where: - FONT_FAMILY_LIST is a comma- + // separated list of font family names, - STYLES is an optional space- + // separated list of style names (case-sensitive + // "Bold" and "Italic" are supported), and + // - SIZE is an integer font size in pixels with the suffix "px". + // + // Here are examples of valid font description strings: - "Arial, Helvetica, + // Bold Italic 14px" - "Arial, 14px" + /// + int (CEF_CALLBACK *set_font_list_at)(struct _cef_menu_model_t* self, + int index, const cef_string_t* font_list); } cef_menu_model_t; diff --git a/include/cef_menu_model.h b/include/cef_menu_model.h index c0a034013..b039119ac 100644 --- a/include/cef_menu_model.h +++ b/include/cef_menu_model.h @@ -411,6 +411,85 @@ class CefMenuModel : public virtual CefBaseRefCounted { bool& shift_pressed, bool& ctrl_pressed, bool& alt_pressed) =0; + + /// + // Set the explicit color for |command_id| and |color_type| to |color|. + // Specify a |color| value of 0 to remove the explicit color. If no explicit + // color or default color is set for |color_type| then the system color will + // be used. Returns true on success. + /// + /*--cef()--*/ + virtual bool SetColor(int command_id, + cef_menu_color_type_t color_type, + cef_color_t color) =0; + + /// + // Set the explicit color for |command_id| and |index| to |color|. Specify a + // |color| value of 0 to remove the explicit color. Specify an |index| value + // of -1 to set the default color for items that do not have an explicit + // color set. If no explicit color or default color is set for |color_type| + // then the system color will be used. Returns true on success. + /// + /*--cef()--*/ + virtual bool SetColorAt(int index, + cef_menu_color_type_t color_type, + cef_color_t color) =0; + + /// + // Returns in |color| the color that was explicitly set for |command_id| and + // |color_type|. If a color was not set then 0 will be returned in |color|. + // Returns true on success. + /// + /*--cef()--*/ + virtual bool GetColor(int command_id, + cef_menu_color_type_t color_type, + cef_color_t& color) =0; + + /// + // Returns in |color| the color that was explicitly set for |command_id| and + // |color_type|. Specify an |index| value of -1 to return the default color + // in |color|. If a color was not set then 0 will be returned in |color|. + // Returns true on success. + /// + /*--cef()--*/ + virtual bool GetColorAt(int index, + cef_menu_color_type_t color_type, + cef_color_t& color) =0; + + /// + // Sets the font list for the specified |command_id|. If |font_list| is empty + // the system font will be used. Returns true on success. The format is + // ",[STYLES] ", where: + // - FONT_FAMILY_LIST is a comma-separated list of font family names, + // - STYLES is an optional space-separated list of style names (case-sensitive + // "Bold" and "Italic" are supported), and + // - SIZE is an integer font size in pixels with the suffix "px". + // + // Here are examples of valid font description strings: + // - "Arial, Helvetica, Bold Italic 14px" + // - "Arial, 14px" + /// + /*--cef(optional_param=font_list)--*/ + virtual bool SetFontList(int command_id, + const CefString& font_list) =0; + + /// + // Sets the font list for the specified |index|. Specify an |index| value of + // -1 to set the default font. If |font_list| is empty the system font will + // be used. Returns true on success. The format is + // ",[STYLES] ", where: + // - FONT_FAMILY_LIST is a comma-separated list of font family names, + // - STYLES is an optional space-separated list of style names (case-sensitive + // "Bold" and "Italic" are supported), and + // - SIZE is an integer font size in pixels with the suffix "px". + // + // Here are examples of valid font description strings: + // - "Arial, Helvetica, Bold Italic 14px" + // - "Arial, 14px" + /// + /*--cef(optional_param=font_list)--*/ + virtual bool SetFontListAt(int index, + const CefString& font_list) =0; }; #endif // CEF_INCLUDE_CEF_MENU_MODEL_H_ diff --git a/include/internal/cef_types.h b/include/internal/cef_types.h index 01ef7d1ae..47c6eb5ee 100644 --- a/include/internal/cef_types.h +++ b/include/internal/cef_types.h @@ -2732,6 +2732,19 @@ typedef enum { CEF_MENU_ANCHOR_BOTTOMCENTER, } cef_menu_anchor_position_t; +/// +// Supported color types for menu items. +/// +typedef enum { + CEF_MENU_COLOR_TEXT, + CEF_MENU_COLOR_TEXT_HOVERED, + CEF_MENU_COLOR_TEXT_ACCELERATOR, + CEF_MENU_COLOR_TEXT_ACCELERATOR_HOVERED, + CEF_MENU_COLOR_BACKGROUND, + CEF_MENU_COLOR_BACKGROUND_HOVERED, + CEF_MENU_COLOR_COUNT, +} cef_menu_color_type_t; + // Supported SSL version values. See net/ssl/ssl_connection_status_flags.h // for more information. typedef enum { diff --git a/libcef/browser/menu_model_impl.cc b/libcef/browser/menu_model_impl.cc index 696d45a85..9dc455211 100644 --- a/libcef/browser/menu_model_impl.cc +++ b/libcef/browser/menu_model_impl.cc @@ -19,6 +19,10 @@ namespace { const int kSeparatorId = -1; +const int kInvalidGroupId = -1; +const int kInvalidCommandId = -1; +const int kDefaultIndex = -1; +const int kInvalidIndex = -2; // A simple MenuModel implementation that delegates to CefMenuModelImpl. class CefSimpleMenuModel : public ui::MenuModel { @@ -73,6 +77,10 @@ class CefSimpleMenuModel : public ui::MenuModel { return false; } + const gfx::FontList* GetLabelFontListAt(int index) const override { + return impl_->GetLabelFontListAt(index); + } + bool GetAcceleratorAt(int index, ui::Accelerator* accelerator) const override { int key_code = 0; @@ -151,6 +159,24 @@ class CefSimpleMenuModel : public ui::MenuModel { impl_->UnhandledCloseSubmenu(is_rtl); } + bool GetTextColor(int index, + bool is_hovered, + SkColor* override_color) const override { + return impl_->GetTextColor(index, false, is_hovered, override_color); + } + + bool GetMinorTextColor(int index, + bool is_hovered, + SkColor* override_color) const override { + return impl_->GetTextColor(index, true, is_hovered, override_color); + } + + bool GetBackgroundColor(int index, + bool is_hovered, + SkColor* override_color) const override { + return impl_->GetBackgroundColor(index, is_hovered, override_color); + } + void MenuWillShow() override { impl_->MenuWillShow(); } @@ -175,6 +201,22 @@ class CefSimpleMenuModel : public ui::MenuModel { DISALLOW_COPY_AND_ASSIGN(CefSimpleMenuModel); }; +cef_menu_color_type_t GetMenuColorType(bool is_text, + bool is_accelerator, + bool is_hovered) { + if (is_text) { + if (is_accelerator) { + return is_hovered ? CEF_MENU_COLOR_TEXT_ACCELERATOR_HOVERED : + CEF_MENU_COLOR_TEXT_ACCELERATOR; + } + return is_hovered ? CEF_MENU_COLOR_TEXT_HOVERED : CEF_MENU_COLOR_TEXT; + } + + DCHECK(!is_accelerator); + return is_hovered ? CEF_MENU_COLOR_BACKGROUND_HOVERED : + CEF_MENU_COLOR_BACKGROUND; +} + } // namespace // static @@ -198,15 +240,7 @@ struct CefMenuModelImpl::Item { : type_(type), command_id_(command_id), label_(label), - group_id_(group_id), - enabled_(true), - visible_(true), - checked_(false), - has_accelerator_(false), - key_code_(0), - shift_pressed_(false), - ctrl_pressed_(false), - alt_pressed_(false) { + group_id_(group_id) { } // Basic information. @@ -217,16 +251,20 @@ struct CefMenuModelImpl::Item { CefRefPtr submenu_; // State information. - bool enabled_; - bool visible_; - bool checked_; + bool enabled_ = true; + bool visible_ = true; + bool checked_ = false; // Accelerator information. - bool has_accelerator_; - int key_code_; - bool shift_pressed_; - bool ctrl_pressed_; - bool alt_pressed_; + bool has_accelerator_ = false; + int key_code_ = 0; + bool shift_pressed_ = false; + bool ctrl_pressed_ = false; + bool alt_pressed_ = false; + + cef_color_t colors_[CEF_MENU_COLOR_COUNT] = {0}; + gfx::FontList font_list_; + bool has_font_list_ = false; }; @@ -270,7 +308,8 @@ bool CefMenuModelImpl::AddSeparator() { if (!VerifyContext()) return false; - AppendItem(Item(MENUITEMTYPE_SEPARATOR, kSeparatorId, CefString(), -1)); + AppendItem(Item(MENUITEMTYPE_SEPARATOR, kSeparatorId, CefString(), + kInvalidGroupId)); return true; } @@ -278,7 +317,8 @@ bool CefMenuModelImpl::AddItem(int command_id, const CefString& label) { if (!VerifyContext()) return false; - AppendItem(Item(MENUITEMTYPE_COMMAND, command_id, label, -1)); + AppendItem(Item(MENUITEMTYPE_COMMAND, command_id, label, + kInvalidGroupId)); return true; } @@ -286,7 +326,7 @@ bool CefMenuModelImpl::AddCheckItem(int command_id, const CefString& label) { if (!VerifyContext()) return false; - AppendItem(Item(MENUITEMTYPE_CHECK, command_id, label, -1)); + AppendItem(Item(MENUITEMTYPE_CHECK, command_id, label, kInvalidGroupId)); return true; } @@ -304,7 +344,7 @@ CefRefPtr CefMenuModelImpl::AddSubMenu(int command_id, if (!VerifyContext()) return NULL; - Item item(MENUITEMTYPE_SUBMENU, command_id, label, -1); + Item item(MENUITEMTYPE_SUBMENU, command_id, label, kInvalidGroupId); item.submenu_ = new CefMenuModelImpl(delegate_, menu_model_delegate_, true); AppendItem(item); return item.submenu_.get(); @@ -314,8 +354,9 @@ bool CefMenuModelImpl::InsertSeparatorAt(int index) { if (!VerifyContext()) return false; - InsertItemAt(Item(MENUITEMTYPE_SEPARATOR, kSeparatorId, CefString(), -1), - index); + InsertItemAt(Item(MENUITEMTYPE_SEPARATOR, kSeparatorId, CefString(), + kInvalidGroupId), + index); return true; } @@ -324,7 +365,8 @@ bool CefMenuModelImpl::InsertItemAt(int index, int command_id, if (!VerifyContext()) return false; - InsertItemAt(Item(MENUITEMTYPE_COMMAND, command_id, label, -1), index); + InsertItemAt(Item(MENUITEMTYPE_COMMAND, command_id, label, kInvalidGroupId), + index); return true; } @@ -333,7 +375,8 @@ bool CefMenuModelImpl::InsertCheckItemAt(int index, int command_id, if (!VerifyContext()) return false; - InsertItemAt(Item(MENUITEMTYPE_CHECK, command_id, label, -1), index); + InsertItemAt(Item(MENUITEMTYPE_CHECK, command_id, label, kInvalidGroupId), + index); return true; } @@ -342,7 +385,7 @@ bool CefMenuModelImpl::InsertRadioItemAt(int index, int command_id, if (!VerifyContext()) return false; - InsertItemAt(Item(MENUITEMTYPE_RADIO, command_id, label, -1), index); + InsertItemAt(Item(MENUITEMTYPE_RADIO, command_id, label, group_id), index); return true; } @@ -351,7 +394,7 @@ CefRefPtr CefMenuModelImpl::InsertSubMenuAt( if (!VerifyContext()) return NULL; - Item item(MENUITEMTYPE_SUBMENU, command_id, label, -1); + Item item(MENUITEMTYPE_SUBMENU, command_id, label, kInvalidGroupId); item.submenu_ = new CefMenuModelImpl(delegate_, menu_model_delegate_, true); InsertItemAt(item, index); return item.submenu_.get(); @@ -374,23 +417,23 @@ bool CefMenuModelImpl::RemoveAt(int index) { int CefMenuModelImpl::GetIndexOf(int command_id) { if (!VerifyContext()) - return -1; + return kInvalidIndex; for (ItemVector::iterator i = items_.begin(); i != items_.end(); ++i) { if ((*i).command_id_ == command_id) { return static_cast(std::distance(items_.begin(), i)); } } - return -1; + return kInvalidIndex; } int CefMenuModelImpl::GetCommandIdAt(int index) { if (!VerifyContext()) - return -1; + return kInvalidCommandId; if (index >= 0 && index < static_cast(items_.size())) return items_[index].command_id_; - return -1; + return kInvalidCommandId; } bool CefMenuModelImpl::SetCommandIdAt(int index, int command_id) { @@ -451,11 +494,11 @@ int CefMenuModelImpl::GetGroupId(int command_id) { int CefMenuModelImpl::GetGroupIdAt(int index) { if (!VerifyContext()) - return -1; + return kInvalidGroupId; if (index >= 0 && index < static_cast(items_.size())) return items_[index].group_id_; - return -1; + return kInvalidGroupId; } bool CefMenuModelImpl::SetGroupId(int command_id, int group_id) { @@ -656,6 +699,95 @@ bool CefMenuModelImpl::GetAcceleratorAt(int index, int& key_code, return false; } +bool CefMenuModelImpl::SetColor(int command_id, + cef_menu_color_type_t color_type, + cef_color_t color) { + return SetColorAt(GetIndexOf(command_id), color_type, color); +} + +bool CefMenuModelImpl::SetColorAt(int index, + cef_menu_color_type_t color_type, + cef_color_t color) { + if (!VerifyContext()) + return false; + + if (color_type < 0 || color_type >= CEF_MENU_COLOR_COUNT) + return false; + + if (index == kDefaultIndex) { + default_colors_[color_type] = color; + return true; + } + + if (index >= 0 && index < static_cast(items_.size())) { + Item& item = items_[index]; + item.colors_[color_type] = color; + return true; + } + + return false; +} + +bool CefMenuModelImpl::GetColor(int command_id, + cef_menu_color_type_t color_type, + cef_color_t& color) { + return GetColorAt(GetIndexOf(command_id), color_type, color); +} + +bool CefMenuModelImpl::GetColorAt(int index, + cef_menu_color_type_t color_type, + cef_color_t& color) { + if (!VerifyContext()) + return false; + + if (color_type < 0 || color_type >= CEF_MENU_COLOR_COUNT) + return false; + + if (index == kDefaultIndex) { + color = default_colors_[color_type]; + return true; + } + + if (index >= 0 && index < static_cast(items_.size())) { + Item& item = items_[index]; + color = item.colors_[color_type]; + return true; + } + + return false; +} + +bool CefMenuModelImpl::SetFontList(int command_id, const CefString& font_list) { + return SetFontListAt(GetIndexOf(command_id), font_list); +} + +bool CefMenuModelImpl::SetFontListAt(int index, const CefString& font_list) { + if (!VerifyContext()) + return false; + + if (index == kDefaultIndex) { + if (font_list.empty()) { + has_default_font_list_ = false; + } else { + default_font_list_ = gfx::FontList(font_list); + has_default_font_list_ = true; + } + return true; + } + + if (index >= 0 && index < static_cast(items_.size())) { + Item& item = items_[index]; + if (font_list.empty()) { + item.has_font_list_ = false; + } else { + item.font_list_ = gfx::FontList(font_list); + item.has_font_list_ = true; + } + return true; + } + return false; +} + void CefMenuModelImpl::ActivatedAt(int index, cef_event_flags_t event_flags) { if (!VerifyContext()) return; @@ -700,6 +832,57 @@ void CefMenuModelImpl::UnhandledCloseSubmenu(bool is_rtl) { base::Bind(&CefMenuModelImpl::OnUnhandledCloseSubmenu, this, is_rtl)); } +bool CefMenuModelImpl::GetTextColor(int index, + bool is_accelerator, + bool is_hovered, + SkColor* override_color) const { + if (index >= 0 && index < static_cast(items_.size())) { + const Item& item = items_[index]; + if (!item.enabled_) { + // Use accelerator color for disabled item text. + is_accelerator = true; + } + + const cef_menu_color_type_t color_type = + GetMenuColorType(true, is_accelerator, is_hovered); + if (item.colors_[color_type] != 0) { + *override_color = item.colors_[color_type]; + return true; + } + } + + const cef_menu_color_type_t color_type = + GetMenuColorType(true, is_accelerator, is_hovered); + if (default_colors_[color_type] != 0) { + *override_color = default_colors_[color_type]; + return true; + } + + return false; +} + +bool CefMenuModelImpl::GetBackgroundColor(int index, + bool is_hovered, + SkColor* override_color) const { + const cef_menu_color_type_t color_type = + GetMenuColorType(false, false, is_hovered); + + if (index >= 0 && index < static_cast(items_.size())) { + const Item& item = items_[index]; + if (item.colors_[color_type] != 0) { + *override_color = item.colors_[color_type]; + return true; + } + } + + if (default_colors_[color_type] != 0) { + *override_color = default_colors_[color_type]; + return true; + } + + return false; +} + void CefMenuModelImpl::MenuWillShow() { if (!VerifyContext()) return; @@ -737,6 +920,18 @@ base::string16 CefMenuModelImpl::GetFormattedLabelAt(int index) { return label; } +const gfx::FontList* CefMenuModelImpl::GetLabelFontListAt(int index) const { + if (index >= 0 && index < static_cast(items_.size())) { + const Item& item = items_[index]; + if (item.has_font_list_) + return &item.font_list_; + } + + if (has_default_font_list_) + return &default_font_list_; + return nullptr; +} + bool CefMenuModelImpl::VerifyRefCount() { if (!VerifyContext()) return false; diff --git a/libcef/browser/menu_model_impl.h b/libcef/browser/menu_model_impl.h index ab07ee82e..7efd6c720 100644 --- a/libcef/browser/menu_model_impl.h +++ b/libcef/browser/menu_model_impl.h @@ -14,6 +14,7 @@ #include "base/threading/platform_thread.h" #include "ui/base/models/menu_model.h" +#include "ui/gfx/font_list.h" namespace content { struct MenuItem; @@ -123,15 +124,37 @@ class CefMenuModelImpl : public CefMenuModel { bool& shift_pressed, bool& ctrl_pressed, bool& alt_pressed) override; bool GetAcceleratorAt(int index, int& key_code, bool& shift_pressed, bool& ctrl_pressed, bool& alt_pressed) override; + bool SetColor(int command_id, + cef_menu_color_type_t color_type, + cef_color_t color) override; + bool SetColorAt(int index, + cef_menu_color_type_t color_type, + cef_color_t color) override; + bool GetColor(int command_id, + cef_menu_color_type_t color_type, + cef_color_t& color) override; + bool GetColorAt(int index, + cef_menu_color_type_t color_type, + cef_color_t& color) override; + bool SetFontList(int command_id, const CefString& font_list) override; + bool SetFontListAt(int index, const CefString& font_list) override; // 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); + bool GetTextColor(int index, + bool is_accelerator, + bool is_hovered, + SkColor* override_color) const; + bool GetBackgroundColor(int index, + bool is_hovered, + SkColor* override_color) const; void MenuWillShow(); void MenuWillClose(); base::string16 GetFormattedLabelAt(int index); + const gfx::FontList* GetLabelFontListAt(int index) const; // Verify that only a single reference exists to all CefMenuModelImpl objects. bool VerifyRefCount(); @@ -182,6 +205,11 @@ class CefMenuModelImpl : public CefMenuModel { ItemVector items_; std::unique_ptr model_; + // Style information. + cef_color_t default_colors_[CEF_MENU_COLOR_COUNT] = {0}; + gfx::FontList default_font_list_; + bool has_default_font_list_ = false; + bool auto_notify_menu_closed_ = true; IMPLEMENT_REFCOUNTING(CefMenuModelImpl); diff --git a/libcef/browser/views/button_view.h b/libcef/browser/views/button_view.h index 40913b245..b64c015e0 100644 --- a/libcef/browser/views/button_view.h +++ b/libcef/browser/views/button_view.h @@ -57,6 +57,13 @@ CEF_BUTTON_VIEW_T void CEF_BUTTON_VIEW_D::ButtonPressed( views::Button* sender, const ui::Event& event) { if (ParentClass::cef_delegate()) ParentClass::cef_delegate()->OnButtonPressed(GetCefButton()); + if (ParentClass::ink_drop_mode() != views::CustomButton::InkDropMode::OFF && + !ParentClass::IsFocusable()) { + // When ink drop is enabled for non-focusable buttons the ink drop state + // does not get reset properly on click, so we do it here explicitly. + ParentClass::AnimateInkDrop(views::InkDropState::HIDDEN, + ui::LocatedEvent::FromIfValid(&event)); + } } #endif // CEF_LIBCEF_BROWSER_VIEWS_BUTTON_VIEW_H_ diff --git a/libcef/browser/views/menu_button_view.cc b/libcef/browser/views/menu_button_view.cc index 0de13fa94..8d402ae31 100644 --- a/libcef/browser/views/menu_button_view.cc +++ b/libcef/browser/views/menu_button_view.cc @@ -5,6 +5,7 @@ #include "libcef/browser/views/menu_button_view.h" #include "ui/gfx/canvas.h" +#include "ui/views/controls/menu/menu_config.h" CefMenuButtonView::CefMenuButtonView( CefMenuButtonDelegate* cef_delegate) @@ -17,6 +18,9 @@ void CefMenuButtonView::Initialize() { SetDrawStringsFlags(IsFocusable() ? gfx::Canvas::SHOW_PREFIX : gfx::Canvas::HIDE_PREFIX); + + // Use the same default font as MenuItemView. + SetFontList(views::MenuConfig::instance().font_list); } CefRefPtr CefMenuButtonView::GetCefMenuButton() const { diff --git a/libcef_dll/cpptoc/menu_model_cpptoc.cc b/libcef_dll/cpptoc/menu_model_cpptoc.cc index 277b59f0c..67f688690 100644 --- a/libcef_dll/cpptoc/menu_model_cpptoc.cc +++ b/libcef_dll/cpptoc/menu_model_cpptoc.cc @@ -994,6 +994,136 @@ int CEF_CALLBACK menu_model_get_accelerator_at(struct _cef_menu_model_t* self, return _retval; } +int CEF_CALLBACK menu_model_set_color(struct _cef_menu_model_t* self, + int command_id, cef_menu_color_type_t color_type, cef_color_t color) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->SetColor( + command_id, + color_type, + color); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_set_color_at(struct _cef_menu_model_t* self, + int index, cef_menu_color_type_t color_type, cef_color_t color) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->SetColorAt( + index, + color_type, + color); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_get_color(struct _cef_menu_model_t* self, + int command_id, cef_menu_color_type_t color_type, cef_color_t* color) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: color; type: simple_byref + DCHECK(color); + if (!color) + return 0; + + // Translate param: color; type: simple_byref + cef_color_t colorVal = color?*color:0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->GetColor( + command_id, + color_type, + colorVal); + + // Restore param: color; type: simple_byref + if (color) + *color = colorVal; + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_get_color_at(struct _cef_menu_model_t* self, + int index, cef_menu_color_type_t color_type, cef_color_t* color) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: color; type: simple_byref + DCHECK(color); + if (!color) + return 0; + + // Translate param: color; type: simple_byref + cef_color_t colorVal = color?*color:0; + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->GetColorAt( + index, + color_type, + colorVal); + + // Restore param: color; type: simple_byref + if (color) + *color = colorVal; + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_set_font_list(struct _cef_menu_model_t* self, + int command_id, const cef_string_t* font_list) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Unverified params: font_list + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->SetFontList( + command_id, + CefString(font_list)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK menu_model_set_font_list_at(struct _cef_menu_model_t* self, + int index, const cef_string_t* font_list) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Unverified params: font_list + + // Execute + bool _retval = CefMenuModelCppToC::Get(self)->SetFontListAt( + index, + CefString(font_list)); + + // Return type: bool + return _retval; +} + } // namespace @@ -1050,6 +1180,12 @@ CefMenuModelCppToC::CefMenuModelCppToC() { GetStruct()->remove_accelerator_at = menu_model_remove_accelerator_at; GetStruct()->get_accelerator = menu_model_get_accelerator; GetStruct()->get_accelerator_at = menu_model_get_accelerator_at; + GetStruct()->set_color = menu_model_set_color; + GetStruct()->set_color_at = menu_model_set_color_at; + GetStruct()->get_color = menu_model_get_color; + GetStruct()->get_color_at = menu_model_get_color_at; + GetStruct()->set_font_list = menu_model_set_font_list; + GetStruct()->set_font_list_at = menu_model_set_font_list_at; } template<> CefRefPtr CefCppToCRefCountedset_color(_struct, + command_id, + color_type, + color); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::SetColorAt(int index, cef_menu_color_type_t color_type, + cef_color_t color) { + cef_menu_model_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, set_color_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = _struct->set_color_at(_struct, + index, + color_type, + color); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::GetColor(int command_id, + cef_menu_color_type_t color_type, cef_color_t& color) { + cef_menu_model_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, get_color)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = _struct->get_color(_struct, + command_id, + color_type, + &color); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::GetColorAt(int index, cef_menu_color_type_t color_type, + cef_color_t& color) { + cef_menu_model_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, get_color_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = _struct->get_color_at(_struct, + index, + color_type, + &color); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::SetFontList(int command_id, + const CefString& font_list) { + cef_menu_model_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, set_font_list)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: font_list + + // Execute + int _retval = _struct->set_font_list(_struct, + command_id, + font_list.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefMenuModelCToCpp::SetFontListAt(int index, const CefString& font_list) { + cef_menu_model_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, set_font_list_at)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: font_list + + // Execute + int _retval = _struct->set_font_list_at(_struct, + index, + font_list.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + // CONSTRUCTOR - Do not edit by hand. diff --git a/libcef_dll/ctocpp/menu_model_ctocpp.h b/libcef_dll/ctocpp/menu_model_ctocpp.h index baea2d41b..4baa75f0a 100644 --- a/libcef_dll/ctocpp/menu_model_ctocpp.h +++ b/libcef_dll/ctocpp/menu_model_ctocpp.h @@ -90,6 +90,16 @@ class CefMenuModelCToCpp bool& ctrl_pressed, bool& alt_pressed) OVERRIDE; bool GetAcceleratorAt(int index, int& key_code, bool& shift_pressed, bool& ctrl_pressed, bool& alt_pressed) OVERRIDE; + bool SetColor(int command_id, cef_menu_color_type_t color_type, + cef_color_t color) OVERRIDE; + bool SetColorAt(int index, cef_menu_color_type_t color_type, + cef_color_t color) OVERRIDE; + bool GetColor(int command_id, cef_menu_color_type_t color_type, + cef_color_t& color) OVERRIDE; + bool GetColorAt(int index, cef_menu_color_type_t color_type, + cef_color_t& color) OVERRIDE; + bool SetFontList(int command_id, const CefString& font_list) OVERRIDE; + bool SetFontListAt(int index, const CefString& font_list) OVERRIDE; }; #endif // CEF_LIBCEF_DLL_CTOCPP_MENU_MODEL_CTOCPP_H_ diff --git a/patch/patches/views_menu_2102.patch b/patch/patches/views_menu_2102.patch index 63d091560..086def634 100644 --- a/patch/patches/views_menu_2102.patch +++ b/patch/patches/views_menu_2102.patch @@ -1,5 +1,5 @@ diff --git ui/base/models/menu_model.h ui/base/models/menu_model.h -index 0755f27..72db677 100644 +index 0755f27..76ad6d6 100644 --- ui/base/models/menu_model.h +++ ui/base/models/menu_model.h @@ -15,6 +15,7 @@ @@ -10,7 +10,7 @@ index 0755f27..72db677 100644 } namespace ui { -@@ -115,6 +116,15 @@ class UI_BASE_EXPORT MenuModel { +@@ -115,6 +116,30 @@ class UI_BASE_EXPORT MenuModel { // |event_flags| is a bit mask of ui::EventFlags. virtual void ActivatedAt(int index, int event_flags); @@ -22,6 +22,21 @@ index 0755f27..72db677 100644 + // true if the menu is displaying a right-to-left language. + virtual void UnhandledOpenSubmenu(bool is_rtl) {} + virtual void UnhandledCloseSubmenu(bool is_rtl) {} ++ ++ // Override the text/background color of a given menu item dependent on the ++ // |index| and its |is_hovered| state. Returns true if it chooses to override ++ // the color. ++ virtual bool GetTextColor(int index, ++ bool is_hovered, ++ SkColor* override_color) const { return false; } ++ virtual bool GetMinorTextColor(int index, ++ bool is_hovered, ++ SkColor* override_color) const ++ { return false; } ++ virtual bool GetBackgroundColor(int index, ++ bool is_hovered, ++ SkColor* override_color) const ++ { return false; } + // Called when the menu is about to be shown. virtual void MenuWillShow() {} @@ -231,10 +246,25 @@ index 79ff77c..a0582c0 100644 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 +index 3b7cb7f..7481553 100644 --- ui/views/controls/menu/menu_delegate.h +++ ui/views/controls/menu/menu_delegate.h -@@ -229,6 +229,11 @@ class VIEWS_EXPORT MenuDelegate { +@@ -87,6 +87,14 @@ class VIEWS_EXPORT MenuDelegate { + bool is_hovered, + SkColor* override_color) const; + ++ // Override the minor text color of a given menu item dependent on the ++ // |command_id| and its |is_hovered| state. Returns true if it chooses to ++ // override the color. ++ virtual bool GetMinorTextColor(int command_id, ++ bool is_hovered, ++ SkColor* override_color) const ++ { return false; } ++ + // Override the background color of a given menu item dependent on the + // |command_id| and its |is_hovered| state. Returns true if it chooses to + // override the color. +@@ -229,6 +237,11 @@ class VIEWS_EXPORT MenuDelegate { bool* has_mnemonics, MenuButton** button); @@ -246,11 +276,44 @@ index 3b7cb7f..3ad68d0 100644 // Returns the max width menus can grow to be. virtual int GetMaxWidthForMenu(MenuItemView* menu); +diff --git ui/views/controls/menu/menu_item_view.cc ui/views/controls/menu/menu_item_view.cc +index b4129049..a23670a 100644 +--- ui/views/controls/menu/menu_item_view.cc ++++ ui/views/controls/menu/menu_item_view.cc +@@ -871,6 +871,17 @@ void MenuItemView::PaintMinorText(gfx::Canvas* canvas, + if (minor_text.empty()) + return; + ++ SkColor text_color; ++ ++ MenuDelegate *delegate = GetDelegate(); ++ if (!delegate || !delegate->GetMinorTextColor(GetCommand(), ++ render_selection, ++ &text_color)) { ++ text_color = GetNativeTheme()->GetSystemColor(render_selection ? ++ ui::NativeTheme::kColorId_SelectedMenuItemForegroundColor : ++ ui::NativeTheme::kColorId_MenuItemSubtitleColor); ++ } ++ + int available_height = height() - GetTopMargin() - GetBottomMargin(); + int max_accel_width = + parent_menu_item_->GetSubmenu()->max_minor_text_width(); +@@ -889,9 +900,7 @@ void MenuItemView::PaintMinorText(gfx::Canvas* canvas, + canvas->DrawStringRectWithFlags( + minor_text, + GetFontList(), +- GetNativeTheme()->GetSystemColor(render_selection ? +- ui::NativeTheme::kColorId_SelectedMenuItemForegroundColor : +- ui::NativeTheme::kColorId_MenuItemSubtitleColor), ++ text_color, + accel_bounds, + flags); + } diff --git ui/views/controls/menu/menu_model_adapter.cc ui/views/controls/menu/menu_model_adapter.cc -index bc04dcb..b2ec114 100644 +index bc04dcb..d786a0b 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) { +@@ -245,6 +245,88 @@ void MenuModelAdapter::SelectionChanged(MenuItemView* menu) { NOTREACHED(); } @@ -296,15 +359,54 @@ index bc04dcb..b2ec114 100644 + + NOTREACHED(); +} ++ ++bool MenuModelAdapter::GetForegroundColor(int command_id, ++ bool is_hovered, ++ SkColor* override_color) const { ++ ui::MenuModel* model = menu_model_; ++ int index = 0; ++ if (ui::MenuModel::GetModelAndIndexForCommandId(command_id, &model, &index)) ++ return model->GetTextColor(index, is_hovered, override_color); ++ ++ NOTREACHED(); ++ return false; ++} ++ ++bool MenuModelAdapter::GetMinorTextColor(int command_id, ++ bool is_hovered, ++ SkColor* override_color) const { ++ ui::MenuModel* model = menu_model_; ++ int index = 0; ++ if (ui::MenuModel::GetModelAndIndexForCommandId(command_id, &model, &index)) ++ return model->GetMinorTextColor(index, is_hovered, override_color); ++ ++ NOTREACHED(); ++ return false; ++} ++ ++bool MenuModelAdapter::GetBackgroundColor(int command_id, ++ bool is_hovered, ++ SkColor* override_color) const { ++ if (command_id == -1) ++ return menu_model_->GetBackgroundColor(-1, is_hovered, override_color); ++ ++ ui::MenuModel* model = menu_model_; ++ int index = 0; ++ if (ui::MenuModel::GetModelAndIndexForCommandId(command_id, &model, &index)) ++ return model->GetBackgroundColor(index, is_hovered, override_color); ++ ++ NOTREACHED(); ++ return false; ++} + void MenuModelAdapter::WillShowMenu(MenuItemView* menu) { // Look up the menu model for this menu. const std::map::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 +index c9799da..827f786 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 { +@@ -76,6 +76,22 @@ class VIEWS_EXPORT MenuModelAdapter : public MenuDelegate { bool IsCommandVisible(int id) const override; bool IsItemChecked(int id) const override; void SelectionChanged(MenuItemView* menu) override; @@ -315,6 +417,31 @@ index c9799da..c7ecca6 100644 + MenuButton** button) override; + void OnUnhandledOpenSubmenu(MenuItemView* menu, bool is_rtl) override; + void OnUnhandledCloseSubmenu(MenuItemView* menu, bool is_rtl) override; ++ bool GetForegroundColor(int command_id, ++ bool is_hovered, ++ SkColor* override_color) const override; ++ bool GetMinorTextColor(int command_id, ++ bool is_hovered, ++ SkColor* override_color) const override; ++ bool GetBackgroundColor(int command_id, ++ bool is_hovered, ++ SkColor* override_color) const override; void WillShowMenu(MenuItemView* menu) override; void WillHideMenu(MenuItemView* menu) override; void OnMenuClosed(MenuItemView* menu, MenuRunner::RunResult result) override; +diff --git ui/views/controls/menu/menu_scroll_view_container.cc ui/views/controls/menu/menu_scroll_view_container.cc +index 455d289..f5f7419 100644 +--- ui/views/controls/menu/menu_scroll_view_container.cc ++++ ui/views/controls/menu/menu_scroll_view_container.cc +@@ -184,6 +184,11 @@ MenuScrollViewContainer::MenuScrollViewContainer(SubmenuView* content_view) + scroll_view_ = new MenuScrollView(content_view); + AddChildView(scroll_view_); + ++ SkColor override_color; ++ MenuDelegate* delegate = content_view_->GetMenuItem()->GetDelegate(); ++ if (delegate && delegate->GetBackgroundColor(-1, false, &override_color)) ++ set_background(views::Background::CreateSolidBackground(override_color)); ++ + arrow_ = BubbleBorderTypeFromAnchor( + content_view_->GetMenuItem()->GetMenuController()->GetAnchorPosition()); + diff --git a/tests/cefclient/browser/client_handler.cc b/tests/cefclient/browser/client_handler.cc index c073050a3..2b1db1638 100644 --- a/tests/cefclient/browser/client_handler.cc +++ b/tests/cefclient/browser/client_handler.cc @@ -325,6 +325,9 @@ void ClientHandler::OnBeforeContextMenu( // Test context menu features. BuildTestMenu(model); } + + if (delegate_) + delegate_->OnBeforeContextMenu(model); } bool ClientHandler::OnContextMenuCommand( diff --git a/tests/cefclient/browser/client_handler.h b/tests/cefclient/browser/client_handler.h index dee559931..26c7e814a 100644 --- a/tests/cefclient/browser/client_handler.h +++ b/tests/cefclient/browser/client_handler.h @@ -38,7 +38,8 @@ class ClientHandler : public CefClient, public CefRequestHandler { public: // Implement this interface to receive notification of ClientHandler - // events. The methods of this class will be called on the main thread. + // events. The methods of this class will be called on the main thread unless + // otherwise indicated. class Delegate { public: // Called when the browser is created. @@ -74,6 +75,9 @@ class ClientHandler : public CefClient, // Set focus to the next/previous control. virtual void OnTakeFocus(bool next) {} + // Called on the UI thread before a context menu is displayed. + virtual void OnBeforeContextMenu(CefRefPtr model) {} + protected: virtual ~Delegate() {} }; diff --git a/tests/cefclient/browser/main_context_impl.cc b/tests/cefclient/browser/main_context_impl.cc index 55b0349ef..b826992e2 100644 --- a/tests/cefclient/browser/main_context_impl.cc +++ b/tests/cefclient/browser/main_context_impl.cc @@ -33,7 +33,7 @@ cef_color_t ParseColor(const std::string& color) { return CefColorSetARGB(255, 255, 255, 255); // Use the default color. - return 0U; + return 0; } } // namespace @@ -44,7 +44,7 @@ MainContextImpl::MainContextImpl(CefRefPtr command_line, terminate_when_all_windows_closed_(terminate_when_all_windows_closed), initialized_(false), shutdown_(false), - background_color_(CefColorSetARGB(255, 255, 255, 255)), + background_color_(0), use_views_(false) { DCHECK(command_line_.get()); @@ -54,12 +54,6 @@ MainContextImpl::MainContextImpl(CefRefPtr command_line, if (main_url_.empty()) main_url_ = kDefaultUrl; - if (command_line_->HasSwitch(switches::kBackgroundColor)) { - // Parse the background color value. - background_color_ = - ParseColor(command_line_->GetSwitchValue(switches::kBackgroundColor)); - } - // Whether windowless (off-screen) rendering will be used. use_windowless_rendering_ = command_line_->HasSwitch(switches::kOffScreenRenderingEnabled); @@ -81,8 +75,19 @@ MainContextImpl::MainContextImpl(CefRefPtr command_line, } #endif // defined(OS_WIN) || defined(OS_LINUX) + if (command_line_->HasSwitch(switches::kBackgroundColor)) { + // Parse the background color value. + background_color_ = + ParseColor(command_line_->GetSwitchValue(switches::kBackgroundColor)); + } + + if (!use_views_ && background_color_ == 0) { + // Set an explicit background color when not using Views. + background_color_ = CefColorSetARGB(255, 255, 255, 255); + } + const std::string& cdm_path = - command_line_->GetSwitchValue(switches::kWidevineCdmPath); + command_line_->GetSwitchValue(switches::kWidevineCdmPath); if (!cdm_path.empty()) { // Register the Widevine CDM at the specified path. See comments in // cef_web_plugin.h for details. It's safe to call this method before @@ -135,7 +140,8 @@ void MainContextImpl::PopulateSettings(CefSettings* settings) { if (use_windowless_rendering_) settings->windowless_rendering_enabled = true; - settings->background_color = background_color_; + if (background_color_ != 0) + settings->background_color = background_color_; } void MainContextImpl::PopulateBrowserSettings(CefBrowserSettings* settings) { @@ -150,7 +156,8 @@ void MainContextImpl::PopulateOsrSettings(OsrRenderer::Settings* settings) { command_line_->HasSwitch(switches::kTransparentPaintingEnabled); settings->show_update_rect = command_line_->HasSwitch(switches::kShowUpdateRect); - settings->background_color = background_color_; + if (background_color_ != 0) + settings->background_color = background_color_; } RootWindowManager* MainContextImpl::GetRootWindowManager() { diff --git a/tests/cefclient/browser/root_window_views.cc b/tests/cefclient/browser/root_window_views.cc index 540679944..41efc35c7 100644 --- a/tests/cefclient/browser/root_window_views.cc +++ b/tests/cefclient/browser/root_window_views.cc @@ -341,6 +341,12 @@ void RootWindowViews::OnTakeFocus(bool next) { window_->TakeFocus(next); } +void RootWindowViews::OnBeforeContextMenu(CefRefPtr model) { + CEF_REQUIRE_UI_THREAD(); + if (window_) + window_->OnBeforeContextMenu(model); +} + void RootWindowViews::CreateClientHandler(const std::string& url) { DCHECK(!client_handler_); diff --git a/tests/cefclient/browser/root_window_views.h b/tests/cefclient/browser/root_window_views.h index a184f6b0c..e649041c5 100644 --- a/tests/cefclient/browser/root_window_views.h +++ b/tests/cefclient/browser/root_window_views.h @@ -74,6 +74,7 @@ class RootWindowViews : public RootWindow, void OnSetDraggableRegions( const std::vector& regions) OVERRIDE; void OnTakeFocus(bool next) OVERRIDE; + void OnBeforeContextMenu(CefRefPtr model) OVERRIDE; private: void CreateClientHandler(const std::string& url); diff --git a/tests/cefclient/browser/views_menu_bar.cc b/tests/cefclient/browser/views_menu_bar.cc index 20b4937a6..b01e46bd3 100644 --- a/tests/cefclient/browser/views_menu_bar.cc +++ b/tests/cefclient/browser/views_menu_bar.cc @@ -6,6 +6,7 @@ #include "include/views/cef_box_layout.h" #include "include/views/cef_window.h" +#include "tests/cefclient/browser/views_style.h" namespace client { @@ -71,12 +72,14 @@ CefRefPtr ViewsMenuBar::CreateMenuModel(const CefString& label, // Create the new MenuModel. CefRefPtr model = CefMenuModel::CreateMenuModel(this); + views_style::ApplyTo(model); models_.push_back(model); // Create the new MenuButton. CefRefPtr button = CefMenuButton::CreateMenuButton(this, label, false, false); button->SetID(new_menu_id); + views_style::ApplyTo(button.get()); button->SetInkDropEnabled(true); // Assign a group ID to allow focus traversal between MenuButtons using the @@ -236,6 +239,7 @@ void ViewsMenuBar::EnsureMenuPanel() { return; panel_ = CefPanel::CreatePanel(NULL); + views_style::ApplyTo(panel_); // Use a horizontal box layout. CefBoxLayoutSettings top_panel_layout_settings; diff --git a/tests/cefclient/browser/views_style.cc b/tests/cefclient/browser/views_style.cc new file mode 100644 index 000000000..999deba20 --- /dev/null +++ b/tests/cefclient/browser/views_style.cc @@ -0,0 +1,105 @@ +// 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_style.h" + +#include "tests/cefclient/browser/main_context.h" + +namespace client { + +namespace views_style { + +namespace { + +cef_color_t g_background_color = 0; +cef_color_t g_background_hover_color = 0; +cef_color_t g_text_color = 0; + +int GetShade(int component) { + return (component < 127) ? component + 75 : component - 75; +} + +void MaybeInitialize() { + static bool initialized = false; + if (initialized) + return; + + g_background_color = MainContext::Get()->GetBackgroundColor(); + if (g_background_color != 0) { + // Use a slightly modified shade of the background color for hover. + g_background_hover_color = CefColorSetARGB(255, + GetShade(CefColorGetR(g_background_color)), + GetShade(CefColorGetG(g_background_color)), + GetShade(CefColorGetB(g_background_color))); + + // Invert the background color for text. + g_text_color = CefColorSetARGB(255, + 255 - CefColorGetR(g_background_color), + 255 - CefColorGetG(g_background_color), + 255 - CefColorGetB(g_background_color)); + } + + initialized = true; +} + +} // namespace + +bool IsSet() { + MaybeInitialize(); + return g_background_color != 0; +} + +void ApplyTo(CefRefPtr panel) { + if (!IsSet()) + return; + + panel->SetBackgroundColor(g_background_color); +} + +void ApplyTo(CefRefPtr label_button) { + if (!IsSet()) + return; + + // All text except disabled gets the same color. + label_button->SetEnabledTextColors(g_text_color); + label_button->SetTextColor(CEF_BUTTON_STATE_DISABLED, + g_background_hover_color); + + label_button->SetBackgroundColor(g_background_color); +} + +void ApplyTo(CefRefPtr textfield) { + if (!IsSet()) + return; + + textfield->SetBackgroundColor(g_background_color); + textfield->SetTextColor(g_text_color); +} + +void ApplyTo(CefRefPtr menu_model) { + if (!IsSet()) + return; + + // All text except non-hovered accelerator gets the same color. + menu_model->SetColorAt(-1, CEF_MENU_COLOR_TEXT, g_text_color); + menu_model->SetColorAt(-1, CEF_MENU_COLOR_TEXT_HOVERED, g_text_color); + menu_model->SetColorAt(-1, CEF_MENU_COLOR_TEXT_ACCELERATOR, + g_background_hover_color); + menu_model->SetColorAt(-1, CEF_MENU_COLOR_TEXT_ACCELERATOR_HOVERED, + g_text_color); + + menu_model->SetColorAt(-1, CEF_MENU_COLOR_BACKGROUND, g_background_color); + menu_model->SetColorAt(-1, CEF_MENU_COLOR_BACKGROUND_HOVERED, + g_background_hover_color); + + // Recursively color sub-menus. + for (int i = 0; i < menu_model->GetCount(); ++i) { + if (menu_model->GetTypeAt(i) == MENUITEMTYPE_SUBMENU) + ApplyTo(menu_model->GetSubMenuAt(i)); + } +} + +} // namespace views_style + +} // namespace client diff --git a/tests/cefclient/browser/views_style.h b/tests/cefclient/browser/views_style.h new file mode 100644 index 000000000..0d32f2cba --- /dev/null +++ b/tests/cefclient/browser/views_style.h @@ -0,0 +1,31 @@ +// 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_STYLE_H_ +#define CEF_TESTS_CEFCLIENT_BROWSER_VIEWS_STYLE_H_ +#pragma once + +#include "include/cef_menu_model.h" +#include "include/views/cef_label_button.h" +#include "include/views/cef_panel.h" +#include "include/views/cef_textfield.h" + +namespace client { + +namespace views_style { + +// Returns true if a style is set. +bool IsSet(); + +// Apply style to views objects. +void ApplyTo(CefRefPtr panel); +void ApplyTo(CefRefPtr label_button); +void ApplyTo(CefRefPtr textfield); +void ApplyTo(CefRefPtr menu_model); + +} // namespace views_style + +} // namespace client + +#endif // CEF_TESTS_CEFCLIENT_BROWSER_VIEWS_STYLE_H_ diff --git a/tests/cefclient/browser/views_window.cc b/tests/cefclient/browser/views_window.cc index cfdf06129..459a10a6f 100644 --- a/tests/cefclient/browser/views_window.cc +++ b/tests/cefclient/browser/views_window.cc @@ -11,8 +11,8 @@ #include "include/views/cef_box_layout.h" #include "include/wrapper/cef_helpers.h" #include "include/cef_app.h" -#include "tests/cefclient/browser/main_context.h" #include "tests/cefclient/browser/resource.h" +#include "tests/cefclient/browser/views_style.h" #include "tests/shared/browser/resource_util.h" #include "tests/shared/common/client_switches.h" @@ -28,6 +28,7 @@ namespace { // Control IDs for Views in the top-level Window. enum ControlIds { ID_WINDOW = 1, + ID_BROWSER_VIEW, ID_BACK_BUTTON, ID_FORWARD_BUTTON, ID_STOP_BUTTON, @@ -81,11 +82,12 @@ void AddTestMenuItems(CefRefPtr test_menu) { test_menu->AddItem(ID_TESTS_OTHER_TESTS, "Other Tests"); } -void AddFileMenuItems(CefRefPtr file_menu, int offset) { +void AddFileMenuItems(CefRefPtr file_menu) { file_menu->AddItem(ID_QUIT, "E&xit"); // Show the accelerator shortcut text in the menu. - file_menu->SetAcceleratorAt(offset, 'X', false, false, true); + file_menu->SetAcceleratorAt(file_menu->GetCount() - 1, + 'X', false, false, true); } } // namespace @@ -243,6 +245,12 @@ void ViewsWindow::TakeFocus(bool next) { window_->GetViewForID(ID_URL_TEXTFIELD)->RequestFocus(); } +void ViewsWindow::OnBeforeContextMenu(CefRefPtr model) { + CEF_REQUIRE_UI_THREAD(); + + views_style::ApplyTo(model); +} + bool ViewsWindow::OnPopupBrowserViewCreated( CefRefPtr browser_view, CefRefPtr popup_browser_view, @@ -380,7 +388,7 @@ void ViewsWindow::OnWindowCreated(CefRefPtr window) { } // Set the background color for regions that are not obscured by other Views. - window_->SetBackgroundColor(MainContext::Get()->GetBackgroundColor()); + views_style::ApplyTo(window_.get()); if (with_controls_) { // Add the BrowserView and other controls to the Window. @@ -452,8 +460,18 @@ bool ViewsWindow::OnKeyEvent(CefRefPtr window, return false; if (event.type == KEYEVENT_RAWKEYDOWN && event.windows_key_code == VK_MENU) { - // ALT key is pressed. Make the menu buttons focusable. - SetMenuFocusable(true); + // ALT key is pressed. + int last_focused_view = last_focused_view_; + bool menu_had_focus = menu_has_focus_; + + // Toggle menu button focusable. + SetMenuFocusable(!menu_has_focus_); + + if (menu_had_focus && last_focused_view != 0) { + // Restore focus to the view that was previously focused. + window_->GetViewForID(last_focused_view)->RequestFocus(); + } + return true; } @@ -475,9 +493,16 @@ CefSize ViewsWindow::GetMinimumSize(CefRefPtr view) { void ViewsWindow::OnFocus(CefRefPtr view) { CEF_REQUIRE_UI_THREAD(); + const int view_id = view->GetID(); + + // Keep track of the non-menu view that was last focused. + if (last_focused_view_ != view_id && + (!top_menu_bar_ || !top_menu_bar_->HasMenuId(view_id))) { + last_focused_view_ = view_id; + } + // When focus leaves the menu buttons make them unfocusable. if (menu_has_focus_) { - const int view_id = view->GetID(); if (top_menu_bar_) { if (!top_menu_bar_->HasMenuId(view_id)) SetMenuFocusable(false); @@ -497,7 +522,8 @@ ViewsWindow::ViewsWindow(Delegate* delegate, CefRefPtr browser_view) : delegate_(delegate), with_controls_(false), - menu_has_focus_(false) { + menu_has_focus_(false), + last_focused_view_(false) { DCHECK(delegate_); if (browser_view) SetBrowserView(browser_view); @@ -506,8 +532,9 @@ ViewsWindow::ViewsWindow(Delegate* delegate, CefCommandLine::GetGlobalCommandLine(); frameless_ = command_line->HasSwitch(switches::kHideFrame); - if (!command_line->HasSwitch(switches::kHideTopMenu)) + if (!command_line->HasSwitch(switches::kHideTopMenu)) { top_menu_bar_ = new ViewsMenuBar(this, ID_TOP_MENU_FIRST); + } } void ViewsWindow::SetBrowserView(CefRefPtr browser_view) { @@ -516,6 +543,7 @@ void ViewsWindow::SetBrowserView(CefRefPtr browser_view) { DCHECK(browser_view->IsValid()); DCHECK(!browser_view->IsAttached()); browser_view_ = browser_view; + browser_view_->SetID(ID_BROWSER_VIEW); } void ViewsWindow::CreateMenuModel() { @@ -523,12 +551,13 @@ void ViewsWindow::CreateMenuModel() { button_menu_model_ = CefMenuModel::CreateMenuModel(this); CefRefPtr test_menu = button_menu_model_->AddSubMenu(0, "&Tests"); + views_style::ApplyTo(button_menu_model_); AddTestMenuItems(test_menu); - AddFileMenuItems(button_menu_model_, 1); + AddFileMenuItems(button_menu_model_); if (top_menu_bar_) { // Add the menus to the top menu bar. - AddFileMenuItems(top_menu_bar_->CreateMenuModel("&File", NULL), 0); + AddFileMenuItems(top_menu_bar_->CreateMenuModel("&File", NULL)); AddTestMenuItems(top_menu_bar_->CreateMenuModel("&Tests", NULL)); } } @@ -536,11 +565,23 @@ void ViewsWindow::CreateMenuModel() { CefRefPtr ViewsWindow::CreateBrowseButton( const std::string& label, int id) { + // The default framed button image resources (IDR_BUTTON_*) look pretty bad + // with non-default background colors, so we'll use frameless buttons with + // ink drop when a background color is specified. + const bool with_frame = !views_style::IsSet(); + CefRefPtr button = - CefLabelButton::CreateLabelButton(this, label, true); + CefLabelButton::CreateLabelButton(this, label, with_frame); button->SetID(id); button->SetEnabled(false); // Disabled by default. button->SetFocusable(false); // Don't give focus to the button. + + if (!with_frame) { + views_style::ApplyTo(button); + button->SetInkDropEnabled(true); + button->SetHorizontalAlignment(CEF_HORIZONTAL_ALIGNMENT_CENTER); + } + return button; } @@ -563,12 +604,14 @@ void ViewsWindow::AddControls() { CefRefPtr url_textfield = CefTextfield::CreateTextfield(this); url_textfield->SetID(ID_URL_TEXTFIELD); url_textfield->SetEnabled(false); // Disabled by default. + views_style::ApplyTo(url_textfield); // Create the menu button. CefRefPtr menu_button = CefMenuButton::CreateMenuButton(this, CefString(), false, false); menu_button->SetID(ID_MENU_BUTTON); menu_button->SetImage(CEF_BUTTON_STATE_NORMAL, LoadImageIcon("menu_icon")); + views_style::ApplyTo(menu_button.get()); menu_button->SetInkDropEnabled(true); // Override the default minimum size. menu_button->SetMinimumSize(CefSize(0, 0)); @@ -587,6 +630,7 @@ void ViewsWindow::AddControls() { top_panel->AddChildView(browse_buttons[i]); top_panel->AddChildView(url_textfield); top_panel->AddChildView(menu_button); + views_style::ApplyTo(top_panel); // Allow |url_textfield| to grow and fill any remaining space. top_panel_layout->SetFlexForView(url_textfield, 1); diff --git a/tests/cefclient/browser/views_window.h b/tests/cefclient/browser/views_window.h index 3302bfc5a..de9852c2c 100644 --- a/tests/cefclient/browser/views_window.h +++ b/tests/cefclient/browser/views_window.h @@ -86,6 +86,7 @@ class ViewsWindow : public CefBrowserViewDelegate, bool canGoForward); void SetDraggableRegions(const std::vector& regions); void TakeFocus(bool next); + void OnBeforeContextMenu(CefRefPtr model); // CefBrowserViewDelegate methods: bool OnPopupBrowserViewCreated( @@ -164,6 +165,7 @@ class ViewsWindow : public CefBrowserViewDelegate, CefRefPtr button_menu_model_; CefRefPtr top_menu_bar_; bool menu_has_focus_; + int last_focused_view_; CefSize minimum_window_size_; diff --git a/tests/ceftests/views/button_unittest.cc b/tests/ceftests/views/button_unittest.cc index b78025da4..35a7f2a56 100644 --- a/tests/ceftests/views/button_unittest.cc +++ b/tests/ceftests/views/button_unittest.cc @@ -393,6 +393,79 @@ class TestMenuButtonDelegate : public CefMenuButtonDelegate, CefRefPtr model = CefMenuModel::CreateMenuModel(this); model->AddItem(kMenuItemID, kMenuItemLabel); + // Verify color accessors. + for (int i = 0; i < CEF_MENU_COLOR_COUNT; ++i) { + cef_menu_color_type_t color_type = static_cast(i); + cef_color_t color_out; + cef_color_t color = CefColorSetARGB(255, 255, 255, i); + + // No color set yet. + color_out = 1; + EXPECT_TRUE(model->GetColor(kMenuItemID, color_type, color_out)); + EXPECT_EQ(0U, color_out); + color_out = 1; + EXPECT_TRUE(model->GetColorAt(0, color_type, color_out)); + EXPECT_EQ(0U, color_out); + color_out = 1; + EXPECT_TRUE(model->GetColorAt(-1, color_type, color_out)); + EXPECT_EQ(0U, color_out); + + // Set the default color. + EXPECT_TRUE(model->SetColorAt(-1, color_type, color)); + color_out = 1; + EXPECT_TRUE(model->GetColorAt(-1, color_type, color_out)); + EXPECT_EQ(color, color_out); + + // Clear the default color. + EXPECT_TRUE(model->SetColorAt(-1, color_type, 0)); + color_out = 1; + EXPECT_TRUE(model->GetColorAt(-1, color_type, color_out)); + EXPECT_EQ(0U, color_out); + + // Set the index color. + EXPECT_TRUE(model->SetColorAt(0, color_type, color)); + color_out = 1; + EXPECT_TRUE(model->GetColorAt(0, color_type, color_out)); + EXPECT_EQ(color, color_out); + + // Clear the index color. + EXPECT_TRUE(model->SetColorAt(0, color_type, 0)); + color_out = 1; + EXPECT_TRUE(model->GetColorAt(0, color_type, color_out)); + EXPECT_EQ(0U, color_out); + + // Set the ID color. + EXPECT_TRUE(model->SetColor(kMenuItemID, color_type, color)); + color_out = 1; + EXPECT_TRUE(model->GetColor(kMenuItemID, color_type, color_out)); + EXPECT_EQ(color, color_out); + + // Clear the ID color. + EXPECT_TRUE(model->SetColor(kMenuItemID, color_type, 0)); + color_out = 1; + EXPECT_TRUE(model->GetColor(kMenuItemID, color_type, color_out)); + EXPECT_EQ(0U, color_out); + + // Index/ID doesn't exist. + EXPECT_FALSE(model->SetColorAt(4, color_type, color)); + EXPECT_FALSE(model->SetColor(4, color_type, color)); + color_out = 1; + EXPECT_FALSE(model->GetColorAt(4, color_type, color_out)); + EXPECT_FALSE(model->GetColor(4, color_type, color_out)); + EXPECT_EQ(1U, color_out); + } + + // Verify font accessors. + const std::string& font = "Tahoma, 12px"; + EXPECT_TRUE(model->SetFontListAt(0, font)); + EXPECT_TRUE(model->SetFontListAt(0, CefString())); + EXPECT_TRUE(model->SetFontList(kMenuItemID, font)); + EXPECT_TRUE(model->SetFontList(kMenuItemID, CefString())); + + // Index/ID doesn't exist. + EXPECT_FALSE(model->SetFontListAt(4, font)); + EXPECT_FALSE(model->SetFontList(4, font)); + // Wait a bit before trying to click the menu item. CefPostDelayedTask(TID_UI, base::Bind(ClickMenuItem, menu_button), kClickDelayMS);