diff --git a/browser/native_window_gtk.cc b/browser/native_window_gtk.cc index b686ceb317e5..c2b3fca25d77 100644 --- a/browser/native_window_gtk.cc +++ b/browser/native_window_gtk.cc @@ -4,6 +4,7 @@ #include "browser/native_window_gtk.h" +#include "base/stl_util.h" #include "base/values.h" #include "browser/ui/gtk/gtk_window_util.h" #include "common/draggable_region.h" @@ -11,6 +12,8 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_view.h" #include "content/public/common/renderer_preferences.h" +#include "ui/base/accelerators/platform_accelerator_gtk.h" +#include "ui/base/models/simple_menu_model.h" #include "ui/base/x/x11_util.h" #include "ui/gfx/gtk_util.h" #include "ui/gfx/rect.h" @@ -57,6 +60,8 @@ NativeWindowGtk::NativeWindowGtk(content::WebContents* web_contents, G_CALLBACK(OnWindowDeleteEventThunk), this); g_signal_connect(window_, "focus-out-event", G_CALLBACK(OnFocusOutThunk), this); + g_signal_connect(window_, "key-press-event", + G_CALLBACK(OnKeyPressThunk), this); if (!has_frame_) { gtk_window_set_decorated(window_, false); @@ -260,6 +265,7 @@ void NativeWindowGtk::SetMenu(ui::MenuModel* menu_model) { menu_.reset(new ::MenuGtk(this, menu_model, true)); gtk_box_pack_start(GTK_BOX(vbox_), menu_->widget(), FALSE, FALSE, 0); gtk_box_reorder_child(GTK_BOX(vbox_), menu_->widget(), 0); + RegisterAccelerators(); } void NativeWindowGtk::UpdateDraggableRegions( @@ -287,6 +293,36 @@ void NativeWindowGtk::UpdateDraggableRegions( draggable_region_ = draggable_region; } +void NativeWindowGtk::RegisterAccelerators() { + accelerator_table_.clear(); + GenerateAcceleratorTable(); +} + +void NativeWindowGtk::GenerateAcceleratorTable() { + DCHECK(menu_); + ui::SimpleMenuModel* model = static_cast( + menu_->model()); + FillAcceleratorTable(&accelerator_table_, model); +} + +void NativeWindowGtk::FillAcceleratorTable(AcceleratorTable* table, + ui::MenuModel* model) { + int count = model->GetItemCount(); + for (int i = 0; i < count; ++i) { + ui::MenuModel::ItemType type = model->GetTypeAt(i); + if (type == ui::MenuModel::TYPE_SUBMENU) { + ui::MenuModel* submodel = model->GetSubmenuModelAt(i); + FillAcceleratorTable(table, submodel); + } else { + ui::Accelerator accelerator; + if (model->GetAcceleratorAt(i, &accelerator)) { + MenuItem item = { i, model }; + (*table)[accelerator] = item; + } + } + } +} + void NativeWindowGtk::SetWebKitColorStyle() { content::RendererPreferences* prefs = GetWebContents()->GetMutableRendererPrefs(); @@ -428,6 +464,18 @@ gboolean NativeWindowGtk::OnButtonPress(GtkWidget* widget, return FALSE; } +gboolean NativeWindowGtk::OnKeyPress(GtkWidget* widget, GdkEventKey* event) { + ui::Accelerator accelerator = ui::AcceleratorForGdkKeyCodeAndModifier( + event->keyval, static_cast(event->state)); + if (ContainsKey(accelerator_table_, accelerator)) { + const MenuItem& item = accelerator_table_[accelerator]; + item.model->ActivatedAt(item.position); + return TRUE; + } else { + return FALSE; + } +} + // static NativeWindow* NativeWindow::Create(content::WebContents* web_contents, base::DictionaryValue* options) { diff --git a/browser/native_window_gtk.h b/browser/native_window_gtk.h index 209cba969599..3d5176e96297 100644 --- a/browser/native_window_gtk.h +++ b/browser/native_window_gtk.h @@ -10,6 +10,7 @@ #include "browser/native_window.h" #include "browser/ui/gtk/menu_gtk.h" #include "third_party/skia/include/core/SkRegion.h" +#include "ui/base/accelerators/accelerator.h" #include "ui/base/gtk/gtk_signal.h" #include "ui/gfx/size.h" @@ -66,6 +67,19 @@ class NativeWindowGtk : public NativeWindow, const std::vector& regions) OVERRIDE; private: + typedef struct { int position; ui::MenuModel* model; } MenuItem; + typedef std::map AcceleratorTable; + + // Register accelerators supported by the menu model. + void RegisterAccelerators(); + + // Generate a table that contains memu model's accelerators and command ids. + void GenerateAcceleratorTable(); + + // Helper to fill the accelerator table from the model. + void FillAcceleratorTable(AcceleratorTable* table, + ui::MenuModel* model); + // Set WebKit's style from current theme. void SetWebKitColorStyle(); @@ -82,11 +96,16 @@ class NativeWindowGtk : public NativeWindow, CHROMEGTK_CALLBACK_1(NativeWindowGtk, gboolean, OnFocusOut, GdkEventFocus*); CHROMEGTK_CALLBACK_1(NativeWindowGtk, gboolean, OnWindowState, GdkEventWindowState*); + + // Mouse move and mouse button press callbacks. CHROMEGTK_CALLBACK_1(NativeWindowGtk, gboolean, OnMouseMoveEvent, GdkEventMotion*); CHROMEGTK_CALLBACK_1(NativeWindowGtk, gboolean, OnButtonPress, GdkEventButton*); + // Key press event callback. + CHROMEGTK_CALLBACK_1(NativeWindowGtk, gboolean, OnKeyPress, GdkEventKey*); + GtkWindow* window_; GtkWidget* vbox_; @@ -110,6 +129,9 @@ class NativeWindowGtk : public NativeWindow, // The window menu. scoped_ptr menu_; + // Map from accelerator to menu item's command id. + AcceleratorTable accelerator_table_; + DISALLOW_COPY_AND_ASSIGN(NativeWindowGtk); }; diff --git a/browser/ui/gtk/menu_gtk.h b/browser/ui/gtk/menu_gtk.h index 70ea2bd33c2a..45d073fd1ae7 100644 --- a/browser/ui/gtk/menu_gtk.h +++ b/browser/ui/gtk/menu_gtk.h @@ -130,6 +130,7 @@ class MenuGtk { gpointer userdata); GtkWidget* widget() const { return menu_; } + ui::MenuModel* model() const { return model_;} // Updates all the enabled/checked states and the dynamic labels. void UpdateMenu();