2121#include " content/nw/src/api/menu/menu.h"
2222
2323#include " base/values.h"
24+ #include " content/nw/src/api/dispatcher_host.h"
2425#include " content/nw/src/api/menuitem/menuitem.h"
2526#include " content/nw/src/browser/native_window_win.h"
2627#include " content/nw/src/nw_shell.h"
2728#include " content/public/browser/web_contents.h"
2829#include " content/public/browser/web_contents_view.h"
30+ #include " skia/ext/image_operations.h"
31+ #include " ui/gfx/gdi_util.h"
32+ #include " ui/gfx/icon_util.h"
2933#include " ui/views/controls/menu/menu_2.h"
3034#include " ui/views/widget/widget.h"
3135
36+ namespace {
37+
38+ HBITMAP GetNativeBitmapFromSkBitmap (const SkBitmap& bitmap) {
39+ int width = bitmap.width ();
40+ int height = bitmap.height ();
41+
42+ BITMAPV4HEADER native_bitmap_header;
43+ gfx::CreateBitmapV4Header (width, height, &native_bitmap_header);
44+
45+ HDC dc = ::GetDC (NULL );
46+ void * bits;
47+ HBITMAP native_bitmap = ::CreateDIBSection (dc,
48+ reinterpret_cast <BITMAPINFO *>(&native_bitmap_header),
49+ DIB_RGB_COLORS ,
50+ &bits,
51+ NULL ,
52+ 0 );
53+ DCHECK (native_bitmap);
54+ ::ReleaseDC (NULL , dc);
55+ bitmap.copyPixelsTo (bits, width * height * 4 , width * 4 );
56+ return native_bitmap;
57+ }
58+
59+ } // namespace
60+
61+
62+ namespace ui {
63+
64+ NwMenuModel::NwMenuModel (Delegate* delegate) : SimpleMenuModel(delegate) {
65+ }
66+
67+ bool NwMenuModel::HasIcons () const {
68+ // Always return false, see the comment about |NwMenuModel|.
69+ return false ;
70+ }
71+
72+ } // namespace ui
73+
3274namespace api {
3375
76+ // The width of the icon for the menuitem
77+ static const int kIconWidth = 16 ;
78+ // The height of the icon for the menuitem
79+ static const int kIconHeight = 16 ;
80+
3481void Menu::Create (const base::DictionaryValue& option) {
3582 is_menu_modified_ = true ;
3683 menu_delegate_.reset (new MenuDelegate (dispatcher_host ()));
37- menu_model_.reset (new ui::SimpleMenuModel (menu_delegate_.get ()));
84+ menu_model_.reset (new ui::NwMenuModel (menu_delegate_.get ()));
3885 menu_.reset (new views::NativeMenuWin (menu_model_.get (), NULL ));
3986
4087 std::string type;
@@ -43,6 +90,9 @@ void Menu::Create(const base::DictionaryValue& option) {
4390}
4491
4592void Menu::Destroy () {
93+ for (size_t index = 0 ; index < icon_bitmaps_.size (); ++index) {
94+ ::DeleteObject (icon_bitmaps_[index]);
95+ }
4696}
4797
4898void Menu::Append (MenuItem* menu_item) {
@@ -90,10 +140,49 @@ void Menu::Popup(int x, int y, content::Shell* shell) {
90140 views::Menu2::ALIGN_TOPLEFT );
91141}
92142
93- void Menu::Rebuild () {
143+ void Menu::Rebuild (const gfx::NativeMenu *parent_menu ) {
94144 if (is_menu_modified_) {
95145 // Refresh menu before show.
96146 menu_->Rebuild ();
147+ for (size_t index = 0 ; index < icon_bitmaps_.size (); ++index) {
148+ ::DeleteObject (icon_bitmaps_[index]);
149+ }
150+ icon_bitmaps_.clear ();
151+
152+ gfx::NativeMenu native_menu = parent_menu == NULL ?
153+ menu_->GetNativeMenu () : *parent_menu;
154+
155+ int first_item_index =
156+ menu_model_->GetFirstItemIndex (native_menu);
157+ for (int menu_index = first_item_index;
158+ menu_index < first_item_index + menu_model_->GetItemCount ();
159+ ++menu_index) {
160+ int model_index = menu_index - first_item_index;
161+ int command_id = menu_model_->GetCommandIdAt (model_index);
162+
163+ if (menu_model_->GetTypeAt (model_index) == ui::MenuModel::TYPE_COMMAND ||
164+ menu_model_->GetTypeAt (model_index) == ui::MenuModel::TYPE_SUBMENU ) {
165+ gfx::Image icon;
166+ menu_model_->GetIconAt (model_index, &icon);
167+ if (!icon.IsEmpty ()) {
168+ SkBitmap resized_bitmap =
169+ skia::ImageOperations::Resize (*icon.ToSkBitmap (),
170+ skia::ImageOperations::RESIZE_GOOD ,
171+ kIconWidth ,
172+ kIconHeight );
173+ HBITMAP icon_bitmap = GetNativeBitmapFromSkBitmap (resized_bitmap);
174+ ::SetMenuItemBitmaps (native_menu, command_id, MF_BYCOMMAND ,
175+ icon_bitmap, icon_bitmap);
176+ icon_bitmaps_.push_back (icon_bitmap);
177+ }
178+ }
179+
180+ MenuItem* item = dispatcher_host ()->GetApiObject <MenuItem>(command_id);
181+ if (item != NULL && item->submenu_ ) {
182+ item->submenu_ ->Rebuild (&native_menu);
183+ }
184+ }
185+
97186 is_menu_modified_ = false ;
98187 }
99188}
0 commit comments