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? |
Elliot Glaysher
2014/03/26 21:42:41
piman, do you have any thoughts on what this is su
piman
2014/03/26 23:44:26
My reading of it:
GDK installs in the core keymap
|
+ 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 |