win: Respond to events of window menu.
authorCheng Zhao <zcbenz@gmail.com>
Thu, 3 Oct 2013 15:34:42 +0000 (23:34 +0800)
committerCheng Zhao <zcbenz@gmail.com>
Thu, 3 Oct 2013 15:34:42 +0000 (23:34 +0800)
browser/native_window_win.cc
browser/native_window_win.h
browser/ui/win/menu_2.h
browser/ui/win/native_menu_win.cc
browser/ui/win/native_menu_win.h

index 57c5edf..4bacb0b 100644 (file)
@@ -7,6 +7,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "browser/ui/win/menu_2.h"
+#include "browser/ui/win/native_menu_win.h"
 #include "common/draggable_region.h"
 #include "common/options_switches.h"
 #include "content/public/browser/native_web_keyboard_event.h"
@@ -17,6 +18,7 @@
 #include "ui/gfx/path.h"
 #include "ui/views/controls/webview/webview.h"
 #include "ui/views/widget/widget.h"
+#include "ui/views/widget/native_widget_win.h"
 #include "ui/views/window/client_view.h"
 #include "ui/views/window/native_frame_view.h"
 
@@ -27,6 +29,35 @@ namespace {
 const int kResizeInsideBoundsSize = 5;
 const int kResizeAreaCornerSize = 16;
 
+// Wrapper of NativeWidgetWin to handle WM_MENUCOMMAND messages, which are
+// triggered by window menus.
+class MenuCommandNativeWidget : public views::NativeWidgetWin {
+ public:
+  explicit MenuCommandNativeWidget(NativeWindowWin* delegate)
+      : views::NativeWidgetWin(delegate->window()),
+        delegate_(delegate) {}
+  virtual ~MenuCommandNativeWidget() {}
+
+ protected:
+  virtual bool PreHandleMSG(UINT message,
+                            WPARAM w_param,
+                            LPARAM l_param,
+                            LRESULT* result) OVERRIDE {
+    if (message == WM_MENUCOMMAND) {
+      delegate_->OnMenuCommand(w_param, reinterpret_cast<HMENU>(l_param));
+      *result = 0;
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+ private:
+  NativeWindowWin* delegate_;
+
+  DISALLOW_COPY_AND_ASSIGN(MenuCommandNativeWidget);
+};
+
 class NativeWindowClientView : public views::ClientView {
  public:
   NativeWindowClientView(views::Widget* widget,
@@ -174,6 +205,7 @@ NativeWindowWin::NativeWindowWin(content::WebContents* web_contents,
       resizable_(true) {
   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
   params.delegate = this;
+  params.native_widget = new MenuCommandNativeWidget(this);
   params.remove_standard_frame = !has_frame_;
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   window_->set_frame_type(views::Widget::FRAME_TYPE_FORCE_NATIVE);
@@ -326,6 +358,11 @@ gfx::NativeWindow NativeWindowWin::GetNativeWindow() {
   return window_->GetNativeView();
 }
 
+void NativeWindowWin::OnMenuCommand(int position, HMENU menu) {
+  DCHECK(menu_);
+  menu_->wrapper()->OnMenuCommand(position, menu);
+}
+
 void NativeWindowWin::SetMenu(ui::MenuModel* menu_model) {
   menu_.reset(new atom::Menu2(menu_model, true));
   ::SetMenu(GetNativeWindow(), menu_->GetNativeMenu());
index e5cdad1..a4406fc 100644 (file)
@@ -66,9 +66,12 @@ class NativeWindowWin : public NativeWindow,
   virtual bool IsKiosk() OVERRIDE;
   virtual gfx::NativeWindow GetNativeWindow() OVERRIDE;
 
+  void OnMenuCommand(int position, HMENU menu);
+
   // Set the native window menu.
   void SetMenu(ui::MenuModel* menu_model);
 
+  views::Widget* window() const { return window_.get(); }
   SkRegion* draggable_region() { return draggable_region_.get(); }
 
  protected:
index 8877cda..67a80e2 100644 (file)
@@ -77,6 +77,7 @@ class Menu2 {
 
   // Accessors.
   ui::MenuModel* model() const { return model_; }
+  NativeMenuWin* wrapper() const { return wrapper_.get(); }
 
   // Sets the minimum width of the menu.
   void SetMinimumWidth(int width);
index f4c2369..5a9bf64 100644 (file)
@@ -92,6 +92,20 @@ class NativeMenuWin::MenuHostWindow {
     DestroyWindow(hwnd_);
   }
 
+  // Called when the user selects a specific item.
+  void OnMenuCommand(int position, HMENU menu) {
+    NativeMenuWin* menu_win = GetNativeMenuWinFromHMENU(menu);
+    ui::MenuModel* model = menu_win->model_;
+    NativeMenuWin* root_menu = menu_win;
+    while (root_menu->parent_)
+      root_menu = root_menu->parent_;
+
+    // Only notify the model if it didn't already send out notification.
+    // See comment in MenuMessageHook for details.
+    if (root_menu->menu_action_ == MENU_ACTION_NONE)
+      model->ActivatedAt(position);
+  }
+
   HWND hwnd() const { return hwnd_; }
 
  private:
@@ -146,20 +160,6 @@ class NativeMenuWin::MenuHostWindow {
     return reinterpret_cast<NativeMenuWin::ItemData*>(item_data);
   }
 
-  // Called when the user selects a specific item.
-  void OnMenuCommand(int position, HMENU menu) {
-    NativeMenuWin* menu_win = GetNativeMenuWinFromHMENU(menu);
-    ui::MenuModel* model = menu_win->model_;
-    NativeMenuWin* root_menu = menu_win;
-    while (root_menu->parent_)
-      root_menu = root_menu->parent_;
-
-    // Only notify the model if it didn't already send out notification.
-    // See comment in MenuMessageHook for details.
-    if (root_menu->menu_action_ == MENU_ACTION_NONE)
-      model->ActivatedAt(position);
-  }
-
   // Called as the user moves their mouse or arrows through the contents of the
   // menu.
   void OnMenuSelect(WPARAM w_param, HMENU menu) {
@@ -529,6 +529,10 @@ void NativeMenuWin::SetMinimumWidth(int width) {
   NOTIMPLEMENTED();
 }
 
+void NativeMenuWin::OnMenuCommand(int position, HMENU menu) {
+  host_window_->OnMenuCommand(position, menu);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // NativeMenuWin, private:
 
index 078bfac..b74c654 100644 (file)
@@ -56,6 +56,9 @@ class NativeMenuWin {
   void RemoveMenuListener(views::MenuListener* listener);
   void SetMinimumWidth(int width);
 
+  // Called by user to generate a menu command event.
+  void OnMenuCommand(int position, HMENU menu);
+
   // Flag to create a window menu instead of popup menu.
   void set_create_as_window_menu(bool flag) { create_as_window_menu_ = flag; }
   bool create_as_window_menu() const { return create_as_window_menu_; }