summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsuzhe@chromium.org <suzhe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-24 07:58:08 +0000
committersuzhe@chromium.org <suzhe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-24 07:58:08 +0000
commit51552aae65a96d19e1adcbf6fe760f102b53a8bf (patch)
tree13002d427575989063b09e190b39b8e0decd7485
parentdcd3de72cb870e3b70fdeadbb43acbbc35fc11ae (diff)
downloadchromium_src-51552aae65a96d19e1adcbf6fe760f102b53a8bf.zip
chromium_src-51552aae65a96d19e1adcbf6fe760f102b53a8bf.tar.gz
chromium_src-51552aae65a96d19e1adcbf6fe760f102b53a8bf.tar.bz2
[Linux] Implement input methods context menu.
BUG=31008 TEST=Right click in the content area, there will be an "Input Method" submenu. Review URL: http://codereview.chromium.org/549100 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@36977 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/app/chrome_dll_resource.h3
-rw-r--r--chrome/app/generated_resources.grd6
-rw-r--r--chrome/browser/gtk/menu_gtk.cc65
-rw-r--r--chrome/browser/renderer_host/gtk_im_context_wrapper.cc19
-rw-r--r--chrome/browser/renderer_host/gtk_im_context_wrapper.h8
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.cc4
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.h7
-rw-r--r--chrome/browser/tab_contents/render_view_context_menu.cc8
-rw-r--r--chrome/browser/tab_contents/render_view_context_menu_gtk.cc9
9 files changed, 97 insertions, 32 deletions
diff --git a/chrome/app/chrome_dll_resource.h b/chrome/app/chrome_dll_resource.h
index d0eb82f..b1351c5 100644
--- a/chrome/app/chrome_dll_resource.h
+++ b/chrome/app/chrome_dll_resource.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -250,6 +250,7 @@
#define IDC_HISTORY_MENU 46000 // OSX only
#define IDC_HISTORY_MENU_VISITED 46100 // OSX only
#define IDC_HISTORY_MENU_CLOSED 46200 // OSX only
+#define IDC_INPUT_METHODS_MENU 46300 // Linux only
// Custom context menu entries
#define IDC_CONTENT_CONTEXT_CUSTOM_FIRST 47000
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 2670712..3ca3859 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -495,6 +495,9 @@ each locale. -->
<message name="IDS_CONTENT_CONTEXT_ADDSEARCHENGINE" desc="The name of the Add as Search Engine command in the content area context menu">
Add as search en&amp;gine...
</message>
+ <message name="IDS_CONTENT_CONTEXT_INPUT_METHODS_MENU" desc="The name of the input method submenu in the content area context menu">
+ Input &amp;methods
+ </message>
</if>
<if expr="pp_ifdef('use_titlecase')">
<message name="IDS_CONTENT_CONTEXT_BACK" desc="In Title Case: The name of the Back command in the content area context menu">
@@ -671,6 +674,9 @@ each locale. -->
<message name="IDS_CONTENT_CONTEXT_ADDSEARCHENGINE" desc="In Title Case: The name of the Add as Search Engine command in the content area context menu">
Add As Search En&amp;gine...
</message>
+ <message name="IDS_CONTENT_CONTEXT_INPUT_METHODS_MENU" desc="In Title Case: The name of the input method submenu in the content area context menu">
+ Input &amp;Methods
+ </message>
</if>
<!-- On quick look, I didn't find any uses of this, is it stale? -->
diff --git a/chrome/browser/gtk/menu_gtk.cc b/chrome/browser/gtk/menu_gtk.cc
index 75b96cb..b987a1e 100644
--- a/chrome/browser/gtk/menu_gtk.cc
+++ b/chrome/browser/gtk/menu_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -20,6 +20,40 @@ using gtk_util::ConvertAcceleratorsFromWindowsStyle;
bool MenuGtk::block_activation_ = false;
+namespace {
+
+// Sets the ID of a menu item.
+void SetMenuItemID(GtkWidget* menu_item, int menu_id) {
+ DCHECK(menu_id >= 0);
+
+ // Add 1 to the menu_id to avoid setting zero (null) to "menu-id".
+ g_object_set_data(G_OBJECT(menu_item), "menu-id",
+ GINT_TO_POINTER(menu_id + 1));
+}
+
+// Gets the ID of a menu item.
+// Returns true if the menu item has an ID.
+bool GetMenuItemID(GtkWidget* menu_item, int* menu_id) {
+ const MenuCreateMaterial* data =
+ reinterpret_cast<const MenuCreateMaterial*>(
+ g_object_get_data(G_OBJECT(menu_item), "menu-data"));
+
+ if (data) {
+ *menu_id = data->id;
+ return true;
+ }
+
+ gpointer id_ptr = g_object_get_data(G_OBJECT(menu_item), "menu-id");
+ if (id_ptr != NULL) {
+ *menu_id = GPOINTER_TO_INT(id_ptr) - 1;
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace
+
MenuGtk::MenuGtk(MenuGtk::Delegate* delegate,
const MenuCreateMaterial* menu_data)
: delegate_(delegate),
@@ -109,9 +143,7 @@ void MenuGtk::AppendMenuItem(int command_id, GtkWidget* menu_item) {
void MenuGtk::AppendMenuItemToMenu(int command_id,
GtkWidget* menu_item,
GtkWidget* menu) {
- g_object_set_data(G_OBJECT(menu_item), "menu-id",
- reinterpret_cast<void*>(command_id));
-
+ SetMenuItemID(menu_item, command_id);
g_signal_connect(G_OBJECT(menu_item), "activate",
G_CALLBACK(OnMenuItemActivated), this);
@@ -333,17 +365,9 @@ void MenuGtk::OnMenuItemActivated(GtkMenuItem* menuitem, MenuGtk* menu) {
return;
}
- const MenuCreateMaterial* data =
- reinterpret_cast<const MenuCreateMaterial*>(
- g_object_get_data(G_OBJECT(menuitem), "menu-data"));
-
int id;
- if (data) {
- id = data->id;
- } else {
- id = reinterpret_cast<intptr_t>(g_object_get_data(G_OBJECT(menuitem),
- "menu-id"));
- }
+ if (!GetMenuItemID(GTK_WIDGET(menuitem), &id))
+ return;
menus::MenuModel* model =
reinterpret_cast<menus::MenuModel*>(
@@ -462,18 +486,11 @@ void MenuGtk::SetMenuItemInfo(GtkWidget* widget, gpointer userdata) {
return;
}
- MenuGtk* menu = reinterpret_cast<MenuGtk*>(userdata);
int id;
- const MenuCreateMaterial* data =
- reinterpret_cast<const MenuCreateMaterial*>(
- g_object_get_data(G_OBJECT(widget), "menu-data"));
- if (data) {
- id = data->id;
- } else {
- id = reinterpret_cast<intptr_t>(g_object_get_data(G_OBJECT(widget),
- "menu-id"));
- }
+ if (!GetMenuItemID(widget, &id))
+ return;
+ MenuGtk* menu = reinterpret_cast<MenuGtk*>(userdata);
menus::MenuModel* model =
reinterpret_cast<menus::MenuModel*>(
g_object_get_data(G_OBJECT(widget), "model"));
diff --git a/chrome/browser/renderer_host/gtk_im_context_wrapper.cc b/chrome/browser/renderer_host/gtk_im_context_wrapper.cc
index 90cc00c..e2b2ded 100644
--- a/chrome/browser/renderer_host/gtk_im_context_wrapper.cc
+++ b/chrome/browser/renderer_host/gtk_im_context_wrapper.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -8,13 +8,18 @@
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
+#include "app/l10n_util.h"
#include "base/gfx/rect.h"
#include "base/logging.h"
#include "base/string_util.h"
+#include "chrome/app/chrome_dll_resource.h"
+#include "chrome/common/gtk_util.h"
#include "chrome/common/native_web_keyboard_event.h"
#include "chrome/common/render_messages.h"
+#include "chrome/browser/gtk/menu_gtk.h"
#include "chrome/browser/renderer_host/render_widget_host.h"
#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
+#include "grit/generated_resources.h"
GtkIMContextWrapper::GtkIMContextWrapper(RenderWidgetHostViewGtk* host_view)
: host_view_(host_view),
@@ -247,6 +252,18 @@ void GtkIMContextWrapper::OnFocusOut() {
host_view_->GetRenderWidgetHost()->ImeSetInputMode(false);
}
+void GtkIMContextWrapper::AppendInputMethodsContextMenu(MenuGtk* menu) {
+ std::string label = gtk_util::ConvertAcceleratorsFromWindowsStyle(
+ l10n_util::GetStringUTF8(IDS_CONTENT_CONTEXT_INPUT_METHODS_MENU));
+ GtkWidget* menuitem = gtk_menu_item_new_with_mnemonic(label.c_str());
+ GtkWidget* submenu = gtk_menu_new();
+ gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
+ gtk_im_multicontext_append_menuitems(GTK_IM_MULTICONTEXT(context_),
+ GTK_MENU_SHELL(submenu));
+ menu->AppendSeparator();
+ menu->AppendMenuItem(IDC_INPUT_METHODS_MENU, menuitem);
+}
+
bool GtkIMContextWrapper::NeedCommitByForwardingCharEvent() {
// If there is no composition text and has only one character to be
// committed, then the character will be send to webkit as a Char event
diff --git a/chrome/browser/renderer_host/gtk_im_context_wrapper.h b/chrome/browser/renderer_host/gtk_im_context_wrapper.h
index 86ff0f0..7c6094f 100644
--- a/chrome/browser/renderer_host/gtk_im_context_wrapper.h
+++ b/chrome/browser/renderer_host/gtk_im_context_wrapper.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -14,8 +14,9 @@ namespace gfx {
class Rect;
}
-class RenderWidgetHostViewGtk;
+class MenuGtk;
class NativeWebKeyboardEvent;
+class RenderWidgetHostViewGtk;
typedef struct _GtkIMContext GtkIMContext;
typedef struct _GtkWidget GtkWidget;
@@ -43,6 +44,8 @@ class GtkIMContextWrapper {
void OnFocusIn();
void OnFocusOut();
+ void AppendInputMethodsContextMenu(MenuGtk* menu);
+
private:
// Check if a text needs commit by forwarding a char event instead of
// by confirming as a composition text.
@@ -169,5 +172,4 @@ class GtkIMContextWrapper {
DISALLOW_COPY_AND_ASSIGN(GtkIMContextWrapper);
};
-
#endif // CHROME_BROWSER_RENDERER_HOST_GTK_IM_CONTEXT_WRAPPER_H_
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
index 3ada2eb..d7a7ff2 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
@@ -602,6 +602,10 @@ void RenderWidgetHostViewGtk::ShowingContextMenu(bool showing) {
is_showing_context_menu_ = showing;
}
+void RenderWidgetHostViewGtk::AppendInputMethodsContextMenu(MenuGtk* menu) {
+ im_context_->AppendInputMethodsContextMenu(menu);
+}
+
BackingStore* RenderWidgetHostViewGtk::AllocBackingStore(
const gfx::Size& size) {
if (gpu_view_host_.get())
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.h b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
index f05f7fe..f44a92b 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -23,6 +23,7 @@ class RenderWidgetHost;
class GpuViewHost;
class GtkIMContextWrapper;
class GtkKeyBindingsHandler;
+class MenuGtk;
class NativeWebKeyboardEvent;
typedef struct _GtkClipboard GtkClipboard;
@@ -82,6 +83,10 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView {
// RenderWidgetHost::ForwardEditCommandsForNextKeyEvent().
void ForwardKeyboardEvent(const NativeWebKeyboardEvent& event);
+ // Appends the input methods context menu to the specified |menu| object as a
+ // submenu.
+ void AppendInputMethodsContextMenu(MenuGtk* menu);
+
private:
friend class RenderWidgetHostViewGtkWidget;
diff --git a/chrome/browser/tab_contents/render_view_context_menu.cc b/chrome/browser/tab_contents/render_view_context_menu.cc
index 4bb701f..4be28b5 100644
--- a/chrome/browser/tab_contents/render_view_context_menu.cc
+++ b/chrome/browser/tab_contents/render_view_context_menu.cc
@@ -509,6 +509,14 @@ bool RenderViewContextMenu::IsItemCommandEnabled(int id) const {
case IDC_CHECK_SPELLING_OF_THIS_FIELD:
return profile_->GetPrefs()->GetBoolean(prefs::kEnableSpellCheck);
+#if defined(OS_LINUX)
+ // Enable the input methods context menu if the content is editable.
+ // TODO(suzhe): It should not be enabled in password boxes. Anyway,
+ // it's not a big issue.
+ case IDC_INPUT_METHODS_MENU:
+ return params_.is_editable;
+#endif
+
case IDS_CONTENT_CONTEXT_SAVEFRAMEAS:
case IDS_CONTENT_CONTEXT_PRINTFRAME:
case IDS_CONTENT_CONTEXT_ADDSEARCHENGINE: // Not implemented.
diff --git a/chrome/browser/tab_contents/render_view_context_menu_gtk.cc b/chrome/browser/tab_contents/render_view_context_menu_gtk.cc
index f8c4617..470173b 100644
--- a/chrome/browser/tab_contents/render_view_context_menu_gtk.cc
+++ b/chrome/browser/tab_contents/render_view_context_menu_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -7,7 +7,7 @@
#include <gtk/gtk.h>
#include "base/string_util.h"
-#include "chrome/browser/renderer_host/render_widget_host_view.h"
+#include "chrome/browser/renderer_host/render_widget_host_view_gtk.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "webkit/glue/context_menu.h"
@@ -26,6 +26,11 @@ RenderViewContextMenuGtk::~RenderViewContextMenuGtk() {
void RenderViewContextMenuGtk::DoInit() {
DoneMakingMenu(&menu_);
gtk_menu_.reset(new MenuGtk(this, menu_.data()));
+
+ RenderWidgetHostViewGtk* rwhv = static_cast<RenderWidgetHostViewGtk*>(
+ source_tab_contents_->render_widget_host_view());
+ if (rwhv)
+ rwhv->AppendInputMethodsContextMenu(gtk_menu_.get());
}
void RenderViewContextMenuGtk::Popup(const gfx::Point& point) {