Index: chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk2.cc |
diff --git a/chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk2.cc b/chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk2.cc |
deleted file mode 100644 |
index 56d8fd138acd8c7c6a65d10623ea7eca937292d1..0000000000000000000000000000000000000000 |
--- a/chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk2.cc |
+++ /dev/null |
@@ -1,316 +0,0 @@ |
-// Copyright 2013 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 "chrome/browser/ui/libgtkui/x11_input_method_context_impl_gtk2.h" |
- |
-#include <gdk/gdk.h> |
-#include <gdk/gdkkeysyms.h> |
-#include <gdk/gdkx.h> |
-#include <stddef.h> |
- |
-#include <gtk/gtk.h> |
- |
-#include <X11/X.h> |
-#include <X11/Xlib.h> |
- |
-#include "base/message_loop/message_loop.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "ui/base/ime/composition_text.h" |
-#include "ui/base/ime/composition_text_util_pango.h" |
-#include "ui/base/ime/text_input_client.h" |
-#include "ui/events/event.h" |
-#include "ui/events/keycodes/keyboard_code_conversion_x.h" |
-#include "ui/gfx/x/x11_types.h" |
- |
-namespace libgtkui { |
- |
-X11InputMethodContextImplGtk2::X11InputMethodContextImplGtk2( |
- ui::LinuxInputMethodContextDelegate* delegate, |
- bool is_simple) |
- : delegate_(delegate), |
- gtk_context_(NULL), |
- gdk_last_set_client_window_(NULL) { |
- CHECK(delegate_); |
- |
- ResetXModifierKeycodesCache(); |
- |
- gtk_context_ = |
- is_simple ? gtk_im_context_simple_new() : gtk_im_multicontext_new(); |
- |
- g_signal_connect(gtk_context_, "commit", G_CALLBACK(OnCommitThunk), this); |
- g_signal_connect(gtk_context_, "preedit-changed", |
- G_CALLBACK(OnPreeditChangedThunk), this); |
- g_signal_connect(gtk_context_, "preedit-end", G_CALLBACK(OnPreeditEndThunk), |
- this); |
- g_signal_connect(gtk_context_, "preedit-start", |
- G_CALLBACK(OnPreeditStartThunk), this); |
- // TODO(shuchen): Handle operations on surrounding text. |
- // "delete-surrounding" and "retrieve-surrounding" signals should be |
- // handled. |
-} |
- |
-X11InputMethodContextImplGtk2::~X11InputMethodContextImplGtk2() { |
- if (gtk_context_) { |
- g_object_unref(gtk_context_); |
- gtk_context_ = NULL; |
- } |
-} |
- |
-// Overriden from ui::LinuxInputMethodContext |
- |
-bool X11InputMethodContextImplGtk2::DispatchKeyEvent( |
- const ui::KeyEvent& key_event) { |
- if (!key_event.HasNativeEvent() || !gtk_context_) |
- return false; |
- |
- // Translate a XKeyEvent to a GdkEventKey. |
- GdkEvent* event = GdkEventFromNativeEvent(key_event.native_event()); |
- if (!event) { |
- LOG(ERROR) << "Cannot translate a XKeyEvent to a GdkEvent."; |
- return false; |
- } |
- |
- if (event->key.window != gdk_last_set_client_window_) { |
- gtk_im_context_set_client_window(gtk_context_, event->key.window); |
- gdk_last_set_client_window_ = event->key.window; |
- } |
- |
- // Convert the last known caret bounds relative to the screen coordinates |
- // to a GdkRectangle relative to the client window. |
- gint x = 0; |
- gint y = 0; |
- gdk_window_get_origin(event->key.window, &x, &y); |
- GdkRectangle rect = {last_caret_bounds_.x() - x, |
- last_caret_bounds_.y() - y, |
- last_caret_bounds_.width(), |
- last_caret_bounds_.height()}; |
- gtk_im_context_set_cursor_location(gtk_context_, &rect); |
- |
- const bool handled = |
- gtk_im_context_filter_keypress(gtk_context_, &event->key); |
- gdk_event_free(event); |
- return handled; |
-} |
- |
-void X11InputMethodContextImplGtk2::Reset() { |
- gtk_im_context_reset(gtk_context_); |
-} |
- |
-void X11InputMethodContextImplGtk2::Focus() { |
- gtk_im_context_focus_in(gtk_context_); |
-} |
- |
-void X11InputMethodContextImplGtk2::Blur() { |
- gtk_im_context_focus_out(gtk_context_); |
-} |
- |
-void X11InputMethodContextImplGtk2::SetCursorLocation(const gfx::Rect& rect) { |
- // Remember the caret bounds so that we can set the cursor location later. |
- // gtk_im_context_set_cursor_location() takes the location relative to the |
- // client window, which is unknown at this point. So we'll call |
- // gtk_im_context_set_cursor_location() later in ProcessKeyEvent() where |
- // (and only where) we know the client window. |
- last_caret_bounds_ = rect; |
-} |
- |
-// private: |
- |
-void X11InputMethodContextImplGtk2::ResetXModifierKeycodesCache() { |
- modifier_keycodes_.clear(); |
- meta_keycodes_.clear(); |
- super_keycodes_.clear(); |
- hyper_keycodes_.clear(); |
- |
- Display* display = gfx::GetXDisplay(); |
- gfx::XScopedPtr<XModifierKeymap, |
- gfx::XObjectDeleter<XModifierKeymap, int, XFreeModifiermap>> |
- modmap(XGetModifierMapping(display)); |
- int min_keycode = 0; |
- int max_keycode = 0; |
- int keysyms_per_keycode = 1; |
- XDisplayKeycodes(display, &min_keycode, &max_keycode); |
- gfx::XScopedPtr<KeySym[]> keysyms( |
- XGetKeyboardMapping(display, min_keycode, max_keycode - min_keycode + 1, |
- &keysyms_per_keycode)); |
- for (int i = 0; i < 8 * modmap->max_keypermod; ++i) { |
- const int keycode = modmap->modifiermap[i]; |
- if (!keycode) |
- continue; |
- modifier_keycodes_.insert(keycode); |
- |
- if (!keysyms) |
- continue; |
- for (int j = 0; j < keysyms_per_keycode; ++j) { |
- switch (keysyms[(keycode - min_keycode) * keysyms_per_keycode + j]) { |
- case XK_Meta_L: |
- case XK_Meta_R: |
- meta_keycodes_.push_back(keycode); |
- break; |
- case XK_Super_L: |
- case XK_Super_R: |
- super_keycodes_.push_back(keycode); |
- break; |
- case XK_Hyper_L: |
- case XK_Hyper_R: |
- hyper_keycodes_.push_back(keycode); |
- break; |
- } |
- } |
- } |
-} |
- |
-GdkEvent* X11InputMethodContextImplGtk2::GdkEventFromNativeEvent( |
- const base::NativeEvent& native_event) { |
- XEvent xkeyevent; |
- if (native_event->type == GenericEvent) { |
- // If this is an XI2 key event, build a matching core X event, to avoid |
- // having two cases for every use. |
- ui::InitXKeyEventFromXIDeviceEvent(*native_event, &xkeyevent); |
- } else { |
- DCHECK(native_event->type == KeyPress || native_event->type == KeyRelease); |
- xkeyevent.xkey = native_event->xkey; |
- } |
- XKeyEvent& xkey = xkeyevent.xkey; |
- |
- // Get a GdkDisplay. |
- GdkDisplay* display = gdk_x11_lookup_xdisplay(xkey.display); |
- if (!display) { |
- // Fall back to the default display. |
- display = gdk_display_get_default(); |
- } |
- if (!display) { |
- LOG(ERROR) << "Cannot get a GdkDisplay for a key event."; |
- return NULL; |
- } |
- // Get a keysym and group. |
- KeySym keysym = NoSymbol; |
- guint8 keyboard_group = 0; |
- XLookupString(&xkey, NULL, 0, &keysym, NULL); |
- GdkKeymap* keymap = gdk_keymap_get_for_display(display); |
- GdkKeymapKey* keys = NULL; |
- guint* keyvals = NULL; |
- gint n_entries = 0; |
- if (keymap && |
- gdk_keymap_get_entries_for_keycode(keymap, xkey.keycode, |
- &keys, &keyvals, &n_entries)) { |
- for (gint i = 0; i < n_entries; ++i) { |
- if (keyvals[i] == keysym) { |
- keyboard_group = keys[i].group; |
- break; |
- } |
- } |
- } |
- g_free(keys); |
- keys = NULL; |
- g_free(keyvals); |
- keyvals = NULL; |
- // Get a GdkWindow. |
-#if GTK_CHECK_VERSION(2,24,0) |
- GdkWindow* window = gdk_x11_window_lookup_for_display(display, xkey.window); |
-#else |
- GdkWindow* window = gdk_window_lookup_for_display(display, xkey.window); |
-#endif |
- if (window) |
- g_object_ref(window); |
- else |
-#if GTK_CHECK_VERSION(2,24,0) |
- window = gdk_x11_window_foreign_new_for_display(display, xkey.window); |
-#else |
- window = gdk_window_foreign_new_for_display(display, xkey.window); |
-#endif |
- if (!window) { |
- LOG(ERROR) << "Cannot get a GdkWindow for a key event."; |
- return NULL; |
- } |
- |
- // Create a GdkEvent. |
- GdkEventType event_type = xkey.type == KeyPress ? |
- GDK_KEY_PRESS : GDK_KEY_RELEASE; |
- GdkEvent* event = gdk_event_new(event_type); |
- event->key.type = event_type; |
- event->key.window = window; |
- // GdkEventKey and XKeyEvent share the same definition for time and state. |
- event->key.send_event = xkey.send_event; |
- event->key.time = xkey.time; |
- event->key.state = xkey.state; |
- event->key.keyval = keysym; |
- event->key.length = 0; |
- event->key.string = NULL; |
- event->key.hardware_keycode = xkey.keycode; |
- event->key.group = keyboard_group; |
- event->key.is_modifier = IsKeycodeModifierKey(xkey.keycode); |
- |
- char keybits[32] = {0}; |
- XQueryKeymap(xkey.display, keybits); |
- if (IsAnyOfKeycodesPressed(meta_keycodes_, keybits, sizeof keybits * 8)) |
- event->key.state |= GDK_META_MASK; |
- if (IsAnyOfKeycodesPressed(super_keycodes_, keybits, sizeof keybits * 8)) |
- event->key.state |= GDK_SUPER_MASK; |
- if (IsAnyOfKeycodesPressed(hyper_keycodes_, keybits, sizeof keybits * 8)) |
- event->key.state |= GDK_HYPER_MASK; |
- |
- return event; |
-} |
- |
-bool X11InputMethodContextImplGtk2::IsKeycodeModifierKey( |
- unsigned int keycode) const { |
- return modifier_keycodes_.find(keycode) != modifier_keycodes_.end(); |
-} |
- |
-bool X11InputMethodContextImplGtk2::IsAnyOfKeycodesPressed( |
- const std::vector<int>& keycodes, |
- const char* keybits, |
- int num_keys) const { |
- for (size_t i = 0; i < keycodes.size(); ++i) { |
- const int keycode = keycodes[i]; |
- if (keycode < 0 || num_keys <= keycode) |
- continue; |
- if (keybits[keycode / 8] & 1 << (keycode % 8)) |
- return true; |
- } |
- return false; |
-} |
- |
-// GtkIMContext event handlers. |
- |
-void X11InputMethodContextImplGtk2::OnCommit(GtkIMContext* context, |
- gchar* text) { |
- if (context != gtk_context_) |
- return; |
- |
- delegate_->OnCommit(base::UTF8ToUTF16(text)); |
-} |
- |
-void X11InputMethodContextImplGtk2::OnPreeditChanged(GtkIMContext* context) { |
- if (context != gtk_context_) |
- return; |
- |
- gchar* str = NULL; |
- PangoAttrList* attrs = NULL; |
- gint cursor_pos = 0; |
- gtk_im_context_get_preedit_string(context, &str, &attrs, &cursor_pos); |
- ui::CompositionText composition_text; |
- ui::ExtractCompositionTextFromGtkPreedit(str, attrs, cursor_pos, |
- &composition_text); |
- g_free(str); |
- pango_attr_list_unref(attrs); |
- |
- delegate_->OnPreeditChanged(composition_text); |
-} |
- |
-void X11InputMethodContextImplGtk2::OnPreeditEnd(GtkIMContext* context) { |
- if (context != gtk_context_) |
- return; |
- |
- delegate_->OnPreeditEnd(); |
-} |
- |
-void X11InputMethodContextImplGtk2::OnPreeditStart(GtkIMContext* context) { |
- if (context != gtk_context_) |
- return; |
- |
- delegate_->OnPreeditStart(); |
-} |
- |
-} // namespace libgtkui |