summaryrefslogtreecommitdiffstats
path: root/content/browser/renderer_host/gtk_key_bindings_handler.cc
diff options
context:
space:
mode:
authorerg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-23 18:10:18 +0000
committererg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-23 18:10:18 +0000
commit3c56b38d2055b16592d499ea4933c27cbb0fd809 (patch)
tree82c593ce4c84e4d0c538d10cd89da3f001ac67c7 /content/browser/renderer_host/gtk_key_bindings_handler.cc
parent03eb9d27a79f876a039ca30eba54d1155ab5500b (diff)
downloadchromium_src-3c56b38d2055b16592d499ea4933c27cbb0fd809.zip
chromium_src-3c56b38d2055b16592d499ea4933c27cbb0fd809.tar.gz
chromium_src-3c56b38d2055b16592d499ea4933c27cbb0fd809.tar.bz2
content: Move render_widget_host_view_gtk to content/ try 2.
This was r97750, which was reverted at r97756. This patch, in addition to all the other things it did, marks OwnedWidgetGtk for export and moves it to the ui:: namespace. Original list of things this patch does: - OwnedWidgetGtk now goes in ui/base/gtk/ - TruncateString moved from l10n_util:: to ui:: - GtkIMContextWrapper has part of its code split into chrome/ (IDC using code goes in RenderViewContextMenu) and the rest go in content/ (gtk using code goes with GtkIMContextWrapper). - gtk_key_bindings_handler[_unittest] now goes in content, as it's a utility class to RenderWidgetHostGtk. BUG=93804 TEST=existing unit tests Original Review URL: http://codereview.chromium.org/7669040 Review URL: http://codereview.chromium.org/7708021 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@97889 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser/renderer_host/gtk_key_bindings_handler.cc')
-rw-r--r--content/browser/renderer_host/gtk_key_bindings_handler.cc325
1 files changed, 325 insertions, 0 deletions
diff --git a/content/browser/renderer_host/gtk_key_bindings_handler.cc b/content/browser/renderer_host/gtk_key_bindings_handler.cc
new file mode 100644
index 0000000..94e3234
--- /dev/null
+++ b/content/browser/renderer_host/gtk_key_bindings_handler.cc
@@ -0,0 +1,325 @@
+// Copyright (c) 2011 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.
+
+#include "content/browser/renderer_host/gtk_key_bindings_handler.h"
+
+#include <gdk/gdkkeysyms.h>
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/string_util.h"
+#include "content/common/native_web_keyboard_event.h"
+
+GtkKeyBindingsHandler::GtkKeyBindingsHandler(GtkWidget* parent_widget)
+ : handler_(CreateNewHandler()) {
+ DCHECK(GTK_IS_FIXED(parent_widget));
+ // We need add the |handler_| object into gtk widget hierarchy, so that
+ // gtk_bindings_activate_event() can find correct display and keymaps from
+ // the |handler_| object.
+ gtk_fixed_put(GTK_FIXED(parent_widget), handler_.get(), -1, -1);
+}
+
+GtkKeyBindingsHandler::~GtkKeyBindingsHandler() {
+ handler_.Destroy();
+}
+
+bool GtkKeyBindingsHandler::Match(const NativeWebKeyboardEvent& wke,
+ EditCommands* edit_commands) {
+ if (wke.type == WebKit::WebInputEvent::Char || !wke.os_event)
+ return false;
+
+ edit_commands_.clear();
+ // If this key event matches a predefined key binding, corresponding signal
+ // will be emitted.
+ gtk_bindings_activate_event(GTK_OBJECT(handler_.get()), wke.os_event);
+
+ bool matched = !edit_commands_.empty();
+ if (edit_commands)
+ edit_commands->swap(edit_commands_);
+ return matched;
+}
+
+GtkWidget* GtkKeyBindingsHandler::CreateNewHandler() {
+ Handler* handler =
+ static_cast<Handler*>(g_object_new(HandlerGetType(), NULL));
+
+ handler->owner = this;
+
+ // We don't need to show the |handler| object on screen, so set its size to
+ // zero.
+ gtk_widget_set_size_request(GTK_WIDGET(handler), 0, 0);
+
+ // Prevents it from handling any events by itself.
+ gtk_widget_set_sensitive(GTK_WIDGET(handler), FALSE);
+ gtk_widget_set_events(GTK_WIDGET(handler), 0);
+ gtk_widget_set_can_focus(GTK_WIDGET(handler), TRUE);
+
+#if !GTK_CHECK_VERSION(2, 14, 0)
+ // "move-focus", "move-viewport", "select-all" and "toggle-cursor-visible"
+ // have no corresponding virtual methods. Prior to glib 2.18 (gtk 2.14),
+ // there is no way to override the default class handler of a signal.
+ // So we need hook these signal explicitly.
+ g_signal_connect(handler, "move-focus", G_CALLBACK(MoveFocus), NULL);
+ g_signal_connect(handler, "move-viewport", G_CALLBACK(MoveViewport), NULL);
+ g_signal_connect(handler, "select-all", G_CALLBACK(SelectAll), NULL);
+ g_signal_connect(handler, "toggle-cursor-visible",
+ G_CALLBACK(ToggleCursorVisible), NULL);
+#endif
+ return GTK_WIDGET(handler);
+}
+
+void GtkKeyBindingsHandler::EditCommandMatched(
+ const std::string& name, const std::string& value) {
+ edit_commands_.push_back(EditCommand(name, value));
+}
+
+void GtkKeyBindingsHandler::HandlerInit(Handler *self) {
+ self->owner = NULL;
+}
+
+void GtkKeyBindingsHandler::HandlerClassInit(HandlerClass *klass) {
+ GtkTextViewClass* text_view_class = GTK_TEXT_VIEW_CLASS(klass);
+ GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
+
+ // Overrides all virtual methods related to editor key bindings.
+ text_view_class->backspace = BackSpace;
+ text_view_class->copy_clipboard = CopyClipboard;
+ text_view_class->cut_clipboard = CutClipboard;
+ text_view_class->delete_from_cursor = DeleteFromCursor;
+ text_view_class->insert_at_cursor = InsertAtCursor;
+ text_view_class->move_cursor = MoveCursor;
+ text_view_class->paste_clipboard = PasteClipboard;
+ text_view_class->set_anchor = SetAnchor;
+ text_view_class->toggle_overwrite = ToggleOverwrite;
+ widget_class->show_help = ShowHelp;
+
+#if GTK_CHECK_VERSION(2, 14, 0)
+ // "move-focus", "move-viewport", "select-all" and "toggle-cursor-visible"
+ // have no corresponding virtual methods. Since glib 2.18 (gtk 2.14),
+ // g_signal_override_class_handler() is introduced to override a signal
+ // handler.
+ g_signal_override_class_handler("move-focus",
+ G_TYPE_FROM_CLASS(klass),
+ G_CALLBACK(MoveFocus));
+
+ g_signal_override_class_handler("move-viewport",
+ G_TYPE_FROM_CLASS(klass),
+ G_CALLBACK(MoveViewport));
+
+ g_signal_override_class_handler("select-all",
+ G_TYPE_FROM_CLASS(klass),
+ G_CALLBACK(SelectAll));
+
+ g_signal_override_class_handler("toggle-cursor-visible",
+ G_TYPE_FROM_CLASS(klass),
+ G_CALLBACK(ToggleCursorVisible));
+#endif
+}
+
+GType GtkKeyBindingsHandler::HandlerGetType() {
+ static volatile gsize type_id_volatile = 0;
+ if (g_once_init_enter(&type_id_volatile)) {
+ GType type_id = g_type_register_static_simple(
+ GTK_TYPE_TEXT_VIEW,
+ g_intern_static_string("GtkKeyBindingsHandler"),
+ sizeof(HandlerClass),
+ reinterpret_cast<GClassInitFunc>(HandlerClassInit),
+ sizeof(Handler),
+ reinterpret_cast<GInstanceInitFunc>(HandlerInit),
+ static_cast<GTypeFlags>(0));
+ g_once_init_leave(&type_id_volatile, type_id);
+ }
+ return type_id_volatile;
+}
+
+GtkKeyBindingsHandler* GtkKeyBindingsHandler::GetHandlerOwner(
+ GtkTextView* text_view) {
+ Handler* handler = G_TYPE_CHECK_INSTANCE_CAST(
+ text_view, HandlerGetType(), Handler);
+ DCHECK(handler);
+ return handler->owner;
+}
+
+void GtkKeyBindingsHandler::BackSpace(GtkTextView* text_view) {
+ GetHandlerOwner(text_view)->EditCommandMatched("DeleteBackward", "");
+}
+
+void GtkKeyBindingsHandler::CopyClipboard(GtkTextView* text_view) {
+ GetHandlerOwner(text_view)->EditCommandMatched("Copy", "");
+}
+
+void GtkKeyBindingsHandler::CutClipboard(GtkTextView* text_view) {
+ GetHandlerOwner(text_view)->EditCommandMatched("Cut", "");
+}
+
+void GtkKeyBindingsHandler::DeleteFromCursor(
+ GtkTextView* text_view, GtkDeleteType type, gint count) {
+ if (!count)
+ return;
+
+ const char *commands[3] = { NULL, NULL, NULL };
+ switch (type) {
+ case GTK_DELETE_CHARS:
+ commands[0] = (count > 0 ? "DeleteForward" : "DeleteBackward");
+ break;
+ case GTK_DELETE_WORD_ENDS:
+ commands[0] = (count > 0 ? "DeleteWordForward" : "DeleteWordBackward");
+ break;
+ case GTK_DELETE_WORDS:
+ if (count > 0) {
+ commands[0] = "MoveWordForward";
+ commands[1] = "DeleteWordBackward";
+ } else {
+ commands[0] = "MoveWordBackward";
+ commands[1] = "DeleteWordForward";
+ }
+ break;
+ case GTK_DELETE_DISPLAY_LINES:
+ commands[0] = "MoveToBeginningOfLine";
+ commands[1] = "DeleteToEndOfLine";
+ break;
+ case GTK_DELETE_DISPLAY_LINE_ENDS:
+ commands[0] = (count > 0 ? "DeleteToEndOfLine" :
+ "DeleteToBeginningOfLine");
+ break;
+ case GTK_DELETE_PARAGRAPH_ENDS:
+ commands[0] = (count > 0 ? "DeleteToEndOfParagraph" :
+ "DeleteToBeginningOfParagraph");
+ break;
+ case GTK_DELETE_PARAGRAPHS:
+ commands[0] = "MoveToBeginningOfParagraph";
+ commands[1] = "DeleteToEndOfParagraph";
+ break;
+ default:
+ // GTK_DELETE_WHITESPACE has no corresponding editor command.
+ return;
+ }
+
+ GtkKeyBindingsHandler* owner = GetHandlerOwner(text_view);
+ if (count < 0)
+ count = -count;
+ for (; count > 0; --count) {
+ for (const char* const* p = commands; *p; ++p)
+ owner->EditCommandMatched(*p, "");
+ }
+}
+
+void GtkKeyBindingsHandler::InsertAtCursor(GtkTextView* text_view,
+ const gchar* str) {
+ if (str && *str)
+ GetHandlerOwner(text_view)->EditCommandMatched("InsertText", str);
+}
+
+void GtkKeyBindingsHandler::MoveCursor(
+ GtkTextView* text_view, GtkMovementStep step, gint count,
+ gboolean extend_selection) {
+ if (!count)
+ return;
+
+ std::string command;
+ switch (step) {
+ case GTK_MOVEMENT_LOGICAL_POSITIONS:
+ command = (count > 0 ? "MoveForward" : "MoveBackward");
+ break;
+ case GTK_MOVEMENT_VISUAL_POSITIONS:
+ command = (count > 0 ? "MoveRight" : "MoveLeft");
+ break;
+ case GTK_MOVEMENT_WORDS:
+ command = (count > 0 ? "MoveWordForward" : "MoveWordBackward");
+ break;
+ case GTK_MOVEMENT_DISPLAY_LINES:
+ command = (count > 0 ? "MoveDown" : "MoveUp");
+ break;
+ case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
+ command = (count > 0 ? "MoveToEndOfLine" : "MoveToBeginningOfLine");
+ break;
+ case GTK_MOVEMENT_PARAGRAPH_ENDS:
+ command = (count > 0 ? "MoveToEndOfParagraph" :
+ "MoveToBeginningOfParagraph");
+ break;
+ case GTK_MOVEMENT_PAGES:
+ command = (count > 0 ? "MovePageDown" : "MovePageUp");
+ break;
+ case GTK_MOVEMENT_BUFFER_ENDS:
+ command = (count > 0 ? "MoveToEndOfDocument" :
+ "MoveToBeginningOfDocument");
+ break;
+ default:
+ // GTK_MOVEMENT_PARAGRAPHS and GTK_MOVEMENT_HORIZONTAL_PAGES have
+ // no corresponding editor commands.
+ return;
+ }
+
+ GtkKeyBindingsHandler* owner = GetHandlerOwner(text_view);
+ if (extend_selection)
+ command.append("AndModifySelection");
+ if (count < 0)
+ count = -count;
+ for (; count > 0; --count)
+ owner->EditCommandMatched(command, "");
+}
+
+void GtkKeyBindingsHandler::MoveViewport(
+ GtkTextView* text_view, GtkScrollStep step, gint count) {
+ // Not supported by webkit.
+#if !GTK_CHECK_VERSION(2, 14, 0)
+ // Before gtk 2.14.0, there is no way to override a non-virtual default signal
+ // handler, so we need stop the signal emission explicitly to prevent the
+ // default handler from being executed.
+ g_signal_stop_emission_by_name(text_view, "move-viewport");
+#endif
+}
+
+void GtkKeyBindingsHandler::PasteClipboard(GtkTextView* text_view) {
+ GetHandlerOwner(text_view)->EditCommandMatched("Paste", "");
+}
+
+void GtkKeyBindingsHandler::SelectAll(GtkTextView* text_view, gboolean select) {
+ if (select)
+ GetHandlerOwner(text_view)->EditCommandMatched("SelectAll", "");
+ else
+ GetHandlerOwner(text_view)->EditCommandMatched("Unselect", "");
+#if !GTK_CHECK_VERSION(2, 14, 0)
+ // Before gtk 2.14.0, there is no way to override a non-virtual default signal
+ // handler, so we need stop the signal emission explicitly to prevent the
+ // default handler from being executed.
+ g_signal_stop_emission_by_name(text_view, "select-all");
+#endif
+}
+
+void GtkKeyBindingsHandler::SetAnchor(GtkTextView* text_view) {
+ GetHandlerOwner(text_view)->EditCommandMatched("SetMark", "");
+}
+
+void GtkKeyBindingsHandler::ToggleCursorVisible(GtkTextView* text_view) {
+ // Not supported by webkit.
+#if !GTK_CHECK_VERSION(2, 14, 0)
+ // Before gtk 2.14.0, there is no way to override a non-virtual default signal
+ // handler, so we need stop the signal emission explicitly to prevent the
+ // default handler from being executed.
+ g_signal_stop_emission_by_name(text_view, "toggle-cursor-visible");
+#endif
+}
+
+void GtkKeyBindingsHandler::ToggleOverwrite(GtkTextView* text_view) {
+ // Not supported by webkit.
+}
+
+gboolean GtkKeyBindingsHandler::ShowHelp(GtkWidget* widget,
+ GtkWidgetHelpType arg1) {
+ // Just for disabling the default handler.
+ return FALSE;
+}
+
+void GtkKeyBindingsHandler::MoveFocus(GtkWidget* widget,
+ GtkDirectionType arg1) {
+ // Just for disabling the default handler.
+#if !GTK_CHECK_VERSION(2, 14, 0)
+ // Before gtk 2.14.0, there is no way to override a non-virtual default signal
+ // handler, so we need stop the signal emission explicitly to prevent the
+ // default handler from being executed.
+ g_signal_stop_emission_by_name(widget, "move-focus");
+#endif
+}