| Index: chrome/browser/ui/libgtk2ui/x11_input_method_context_impl_gtk2.cc
|
| diff --git a/chrome/browser/ui/libgtk2ui/x11_input_method_context_impl_gtk2.cc b/chrome/browser/ui/libgtk2ui/x11_input_method_context_impl_gtk2.cc
|
| deleted file mode 100644
|
| index 617f7c565d3fee20470aeca60172201daa8c77f4..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/ui/libgtk2ui/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/libgtk2ui/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 libgtk2ui {
|
| -
|
| -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 libgtk2ui
|
|
|