21
21
#include " content/nw/src/api/menu/menu.h"
22
22
23
23
#include " base/values.h"
24
+ #include " content/nw/src/api/dispatcher_host.h"
24
25
#include " content/nw/src/api/menuitem/menuitem.h"
25
26
#include " content/nw/src/browser/native_window_win.h"
26
27
#include " content/nw/src/nw_shell.h"
27
28
#include " content/public/browser/web_contents.h"
28
29
#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"
29
33
#include " ui/views/controls/menu/menu_2.h"
30
34
#include " ui/views/widget/widget.h"
31
35
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
+
32
74
namespace api {
33
75
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
+
34
81
void Menu::Create (const base::DictionaryValue& option) {
35
82
is_menu_modified_ = true ;
36
83
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 ()));
38
85
menu_.reset (new views::NativeMenuWin (menu_model_.get (), NULL ));
39
86
40
87
std::string type;
@@ -43,6 +90,9 @@ void Menu::Create(const base::DictionaryValue& option) {
43
90
}
44
91
45
92
void Menu::Destroy () {
93
+ for (size_t index = 0 ; index < icon_bitmaps_.size (); ++index) {
94
+ ::DeleteObject (icon_bitmaps_[index]);
95
+ }
46
96
}
47
97
48
98
void Menu::Append (MenuItem* menu_item) {
@@ -90,10 +140,49 @@ void Menu::Popup(int x, int y, content::Shell* shell) {
90
140
views::Menu2::ALIGN_TOPLEFT);
91
141
}
92
142
93
- void Menu::Rebuild () {
143
+ void Menu::Rebuild (const gfx::NativeMenu *parent_menu ) {
94
144
if (is_menu_modified_) {
95
145
// Refresh menu before show.
96
146
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
+
97
186
is_menu_modified_ = false ;
98
187
}
99
188
}
0 commit comments