| Index: chrome/browser/ui/libgtk2ui/gtk2_key_bindings_handler.cc
|
| diff --git a/content/browser/renderer_host/gtk_key_bindings_handler.cc b/chrome/browser/ui/libgtk2ui/gtk2_key_bindings_handler.cc
|
| similarity index 63%
|
| copy from content/browser/renderer_host/gtk_key_bindings_handler.cc
|
| copy to chrome/browser/ui/libgtk2ui/gtk2_key_bindings_handler.cc
|
| index 3830364a0e8ff1b979306e06f5f6341d0fb58396..88a6da3a734a8fc8c2fe6c18408022f8a767a8f2 100644
|
| --- a/content/browser/renderer_host/gtk_key_bindings_handler.cc
|
| +++ b/chrome/browser/ui/libgtk2ui/gtk2_key_bindings_handler.cc
|
| @@ -2,40 +2,54 @@
|
| // 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 "chrome/browser/ui/libgtk2ui/gtk2_key_bindings_handler.h"
|
|
|
| #include <gdk/gdkkeysyms.h>
|
| +#include <X11/Xlib.h>
|
| +#include <X11/XKBlib.h>
|
|
|
| #include <string>
|
|
|
| #include "base/logging.h"
|
| #include "base/strings/string_util.h"
|
| +#include "chrome/browser/ui/libgtk2ui/gtk2_util.h"
|
| #include "content/public/browser/native_web_keyboard_event.h"
|
| -
|
| -namespace content {
|
| -
|
| -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);
|
| +#include "ui/base/x/x11_util.h"
|
| +#include "ui/events/event.h"
|
| +
|
| +namespace libgtk2ui {
|
| +
|
| +Gtk2KeyBindingsHandler::Gtk2KeyBindingsHandler()
|
| + : fake_window_(gtk_offscreen_window_new()),
|
| + handler_(CreateNewHandler()),
|
| + has_xkb_(false) {
|
| + gtk_container_add(GTK_CONTAINER(fake_window_), handler_.get());
|
| +
|
| + int opcode, event, error;
|
| + int major = XkbMajorVersion;
|
| + int minor = XkbMinorVersion;
|
| + if (XkbQueryExtension(gfx::GetXDisplay(), &opcode, &event, &error,
|
| + &major, &minor))
|
| + has_xkb_ = true;
|
| }
|
|
|
| -GtkKeyBindingsHandler::~GtkKeyBindingsHandler() {
|
| +Gtk2KeyBindingsHandler::~Gtk2KeyBindingsHandler() {
|
| handler_.Destroy();
|
| + gtk_widget_destroy(fake_window_);
|
| }
|
|
|
| -bool GtkKeyBindingsHandler::Match(const NativeWebKeyboardEvent& wke,
|
| - EditCommands* edit_commands) {
|
| +bool Gtk2KeyBindingsHandler::Match(const content::NativeWebKeyboardEvent& wke,
|
| + content::EditCommands* edit_commands) {
|
| if (wke.type == blink::WebInputEvent::Char || !wke.os_event)
|
| return false;
|
|
|
| + GdkEventKey gdk_event;
|
| + BuildGdkEventKeyFromXEvent(wke.os_event->native_event(), &gdk_event);
|
| +
|
| 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->key);
|
| + gtk_bindings_activate_event(GTK_OBJECT(handler_.get()), &gdk_event);
|
|
|
| bool matched = !edit_commands_.empty();
|
| if (edit_commands)
|
| @@ -43,7 +57,7 @@ bool GtkKeyBindingsHandler::Match(const NativeWebKeyboardEvent& wke,
|
| return matched;
|
| }
|
|
|
| -GtkWidget* GtkKeyBindingsHandler::CreateNewHandler() {
|
| +GtkWidget* Gtk2KeyBindingsHandler::CreateNewHandler() {
|
| Handler* handler =
|
| static_cast<Handler*>(g_object_new(HandlerGetType(), NULL));
|
|
|
| @@ -61,16 +75,57 @@ GtkWidget* GtkKeyBindingsHandler::CreateNewHandler() {
|
| return GTK_WIDGET(handler);
|
| }
|
|
|
| -void GtkKeyBindingsHandler::EditCommandMatched(
|
| +void Gtk2KeyBindingsHandler::EditCommandMatched(
|
| const std::string& name, const std::string& value) {
|
| - edit_commands_.push_back(EditCommand(name, value));
|
| + edit_commands_.push_back(content::EditCommand(name, value));
|
| +}
|
| +
|
| +void Gtk2KeyBindingsHandler::BuildGdkEventKeyFromXEvent(
|
| + const base::NativeEvent& xevent,
|
| + GdkEventKey* gdk_event) {
|
| + GdkKeymap *keymap = gdk_keymap_get_for_display(gdk_display_get_default());
|
| + GdkModifierType consumed, state;
|
| +
|
| + gdk_event->type = xevent->xany.type == KeyPress ?
|
| + GDK_KEY_PRESS : GDK_KEY_RELEASE;
|
| + gdk_event->time = xevent->xkey.time;
|
| + gdk_event->state = static_cast<GdkModifierType>(xevent->xkey.state);
|
| + gdk_event->hardware_keycode = xevent->xkey.keycode;
|
| +
|
| + if (has_xkb_) {
|
| + gdk_event->group = XkbGroupForCoreState(xevent->xkey.state);
|
| + } else {
|
| + // TODO(erg): I don't understand what this is for. I read through parts of
|
| + // gdkevent-x11.c. Just calling XkbGroupForCoreState() if we have XKB is
|
| + // simple enough, but I don't understand X11 input handling enough to know
|
| + // what this is for, and reading through what GDK does to try to calculate
|
| + // this was not enlightening.
|
| + //
|
| + // Also, does anyone actually have servers that don't support XKB at this
|
| + // point?
|
| + NOTIMPLEMENTED();
|
| + gdk_event->group = 0;
|
| + }
|
| +
|
| + gdk_event->keyval = GDK_VoidSymbol;
|
| + gdk_keymap_translate_keyboard_state(
|
| + keymap,
|
| + gdk_event->hardware_keycode,
|
| + static_cast<GdkModifierType>(gdk_event->state),
|
| + gdk_event->group,
|
| + &gdk_event->keyval,
|
| + NULL, NULL, &consumed);
|
| +
|
| + state = static_cast<GdkModifierType>(gdk_event->state & ~consumed);
|
| + gdk_keymap_add_virtual_modifiers(keymap, &state);
|
| + gdk_event->state |= state;
|
| }
|
|
|
| -void GtkKeyBindingsHandler::HandlerInit(Handler *self) {
|
| +void Gtk2KeyBindingsHandler::HandlerInit(Handler *self) {
|
| self->owner = NULL;
|
| }
|
|
|
| -void GtkKeyBindingsHandler::HandlerClassInit(HandlerClass *klass) {
|
| +void Gtk2KeyBindingsHandler::HandlerClassInit(HandlerClass *klass) {
|
| GtkTextViewClass* text_view_class = GTK_TEXT_VIEW_CLASS(klass);
|
| GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
|
|
|
| @@ -107,12 +162,12 @@ void GtkKeyBindingsHandler::HandlerClassInit(HandlerClass *klass) {
|
| G_CALLBACK(ToggleCursorVisible));
|
| }
|
|
|
| -GType GtkKeyBindingsHandler::HandlerGetType() {
|
| +GType Gtk2KeyBindingsHandler::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"),
|
| + g_intern_static_string("Gtk2KeyBindingsHandler"),
|
| sizeof(HandlerClass),
|
| reinterpret_cast<GClassInitFunc>(HandlerClassInit),
|
| sizeof(Handler),
|
| @@ -123,7 +178,7 @@ GType GtkKeyBindingsHandler::HandlerGetType() {
|
| return type_id_volatile;
|
| }
|
|
|
| -GtkKeyBindingsHandler* GtkKeyBindingsHandler::GetHandlerOwner(
|
| +Gtk2KeyBindingsHandler* Gtk2KeyBindingsHandler::GetHandlerOwner(
|
| GtkTextView* text_view) {
|
| Handler* handler = G_TYPE_CHECK_INSTANCE_CAST(
|
| text_view, HandlerGetType(), Handler);
|
| @@ -131,20 +186,20 @@ GtkKeyBindingsHandler* GtkKeyBindingsHandler::GetHandlerOwner(
|
| return handler->owner;
|
| }
|
|
|
| -void GtkKeyBindingsHandler::BackSpace(GtkTextView* text_view) {
|
| +void Gtk2KeyBindingsHandler::BackSpace(GtkTextView* text_view) {
|
| GetHandlerOwner(text_view)
|
| ->EditCommandMatched("DeleteBackward", std::string());
|
| }
|
|
|
| -void GtkKeyBindingsHandler::CopyClipboard(GtkTextView* text_view) {
|
| +void Gtk2KeyBindingsHandler::CopyClipboard(GtkTextView* text_view) {
|
| GetHandlerOwner(text_view)->EditCommandMatched("Copy", std::string());
|
| }
|
|
|
| -void GtkKeyBindingsHandler::CutClipboard(GtkTextView* text_view) {
|
| +void Gtk2KeyBindingsHandler::CutClipboard(GtkTextView* text_view) {
|
| GetHandlerOwner(text_view)->EditCommandMatched("Cut", std::string());
|
| }
|
|
|
| -void GtkKeyBindingsHandler::DeleteFromCursor(
|
| +void Gtk2KeyBindingsHandler::DeleteFromCursor(
|
| GtkTextView* text_view, GtkDeleteType type, gint count) {
|
| if (!count)
|
| return;
|
| @@ -187,7 +242,7 @@ void GtkKeyBindingsHandler::DeleteFromCursor(
|
| return;
|
| }
|
|
|
| - GtkKeyBindingsHandler* owner = GetHandlerOwner(text_view);
|
| + Gtk2KeyBindingsHandler* owner = GetHandlerOwner(text_view);
|
| if (count < 0)
|
| count = -count;
|
| for (; count > 0; --count) {
|
| @@ -196,13 +251,13 @@ void GtkKeyBindingsHandler::DeleteFromCursor(
|
| }
|
| }
|
|
|
| -void GtkKeyBindingsHandler::InsertAtCursor(GtkTextView* text_view,
|
| - const gchar* str) {
|
| +void Gtk2KeyBindingsHandler::InsertAtCursor(GtkTextView* text_view,
|
| + const gchar* str) {
|
| if (str && *str)
|
| GetHandlerOwner(text_view)->EditCommandMatched("InsertText", str);
|
| }
|
|
|
| -void GtkKeyBindingsHandler::MoveCursor(
|
| +void Gtk2KeyBindingsHandler::MoveCursor(
|
| GtkTextView* text_view, GtkMovementStep step, gint count,
|
| gboolean extend_selection) {
|
| if (!count)
|
| @@ -242,7 +297,7 @@ void GtkKeyBindingsHandler::MoveCursor(
|
| return;
|
| }
|
|
|
| - GtkKeyBindingsHandler* owner = GetHandlerOwner(text_view);
|
| + Gtk2KeyBindingsHandler* owner = GetHandlerOwner(text_view);
|
| if (extend_selection)
|
| command.append("AndModifySelection");
|
| if (count < 0)
|
| @@ -251,43 +306,44 @@ void GtkKeyBindingsHandler::MoveCursor(
|
| owner->EditCommandMatched(command, std::string());
|
| }
|
|
|
| -void GtkKeyBindingsHandler::MoveViewport(
|
| +void Gtk2KeyBindingsHandler::MoveViewport(
|
| GtkTextView* text_view, GtkScrollStep step, gint count) {
|
| // Not supported by webkit.
|
| }
|
|
|
| -void GtkKeyBindingsHandler::PasteClipboard(GtkTextView* text_view) {
|
| +void Gtk2KeyBindingsHandler::PasteClipboard(GtkTextView* text_view) {
|
| GetHandlerOwner(text_view)->EditCommandMatched("Paste", std::string());
|
| }
|
|
|
| -void GtkKeyBindingsHandler::SelectAll(GtkTextView* text_view, gboolean select) {
|
| +void Gtk2KeyBindingsHandler::SelectAll(GtkTextView* text_view,
|
| + gboolean select) {
|
| if (select)
|
| GetHandlerOwner(text_view)->EditCommandMatched("SelectAll", std::string());
|
| else
|
| GetHandlerOwner(text_view)->EditCommandMatched("Unselect", std::string());
|
| }
|
|
|
| -void GtkKeyBindingsHandler::SetAnchor(GtkTextView* text_view) {
|
| +void Gtk2KeyBindingsHandler::SetAnchor(GtkTextView* text_view) {
|
| GetHandlerOwner(text_view)->EditCommandMatched("SetMark", std::string());
|
| }
|
|
|
| -void GtkKeyBindingsHandler::ToggleCursorVisible(GtkTextView* text_view) {
|
| +void Gtk2KeyBindingsHandler::ToggleCursorVisible(GtkTextView* text_view) {
|
| // Not supported by webkit.
|
| }
|
|
|
| -void GtkKeyBindingsHandler::ToggleOverwrite(GtkTextView* text_view) {
|
| +void Gtk2KeyBindingsHandler::ToggleOverwrite(GtkTextView* text_view) {
|
| // Not supported by webkit.
|
| }
|
|
|
| -gboolean GtkKeyBindingsHandler::ShowHelp(GtkWidget* widget,
|
| - GtkWidgetHelpType arg1) {
|
| +gboolean Gtk2KeyBindingsHandler::ShowHelp(GtkWidget* widget,
|
| + GtkWidgetHelpType arg1) {
|
| // Just for disabling the default handler.
|
| return FALSE;
|
| }
|
|
|
| -void GtkKeyBindingsHandler::MoveFocus(GtkWidget* widget,
|
| - GtkDirectionType arg1) {
|
| +void Gtk2KeyBindingsHandler::MoveFocus(GtkWidget* widget,
|
| + GtkDirectionType arg1) {
|
| // Just for disabling the default handler.
|
| }
|
|
|
| -} // namespace content
|
| +} // namespace libgtk2ui
|
|
|