summaryrefslogtreecommitdiffstats
path: root/views/ime
diff options
context:
space:
mode:
authoroshima@google.com <oshima@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-12 01:00:00 +0000
committeroshima@google.com <oshima@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-12 01:00:00 +0000
commit45510d9022d636a163762b67bf36a35b1c36cd3a (patch)
treedfaefde0ac5bebd02183fc0e08c0b91118105d09 /views/ime
parent33c90eba54629044ddde7cc3aad60b4318d7688a (diff)
downloadchromium_src-45510d9022d636a163762b67bf36a35b1c36cd3a.zip
chromium_src-45510d9022d636a163762b67bf36a35b1c36cd3a.tar.gz
chromium_src-45510d9022d636a163762b67bf36a35b1c36cd3a.tar.bz2
Add input method support for views and integrate ibus input framework
BUG=none TEST=tested on Linux desktop oshima landed for penghuang Review URL: http://codereview.chromium.org/6480036 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@74709 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/ime')
-rw-r--r--views/ime/ibus_ime_context.cc398
-rw-r--r--views/ime/ime_context.cc88
-rw-r--r--views/ime/ime_context.h240
3 files changed, 726 insertions, 0 deletions
diff --git a/views/ime/ibus_ime_context.cc b/views/ime/ibus_ime_context.cc
new file mode 100644
index 0000000..130d863
--- /dev/null
+++ b/views/ime/ibus_ime_context.cc
@@ -0,0 +1,398 @@
+// 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 <ibus.h>
+
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+#include "gfx/rect.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/gtk/gtk_signal.h"
+#include "ui/base/keycodes/keyboard_code_conversion_gtk.h"
+#include "views/events/event.h"
+#include "views/ime/ime_context.h"
+
+namespace {
+
+class IBusIMEContext;
+
+struct ProcessKeyEventData {
+ ProcessKeyEventData(IBusIMEContext* context,
+ const views::KeyEvent& event)
+ : context(context),
+ event(event.type(), event.key_code(), event.flags()) {
+ }
+
+ IBusIMEContext* context;
+ views::KeyEvent event;
+};
+
+// Implements IMEContext to integrate ibus input method framework
+class IBusIMEContext : public views::IMEContext {
+ public:
+ explicit IBusIMEContext(views::View* view);
+ virtual ~IBusIMEContext();
+
+ // views::IMEContext implementations:
+ virtual void Focus();
+ virtual void Blur();
+ virtual void Reset();
+ virtual bool FilterKeyEvent(const views::KeyEvent& event);
+ virtual void SetCursorLocation(const gfx::Rect& caret_rect);
+ virtual void SetSurrounding(const string16& text, int cursor_pos);
+
+ private:
+ void CreateContext();
+ void DestroyContext();
+
+ // Event handlers for IBusBus:
+ CHROMEG_CALLBACK_0(IBusIMEContext, void, OnConnected, IBusBus*);
+ CHROMEG_CALLBACK_0(IBusIMEContext, void, OnDisconnected, IBusBus*);
+
+ // Event handlers for IBusIMEContext:
+ CHROMEG_CALLBACK_1(IBusIMEContext, void, OnCommitText,
+ IBusInputContext*, IBusText*);
+ CHROMEG_CALLBACK_3(IBusIMEContext, void, OnForwardKeyEvent,
+ IBusInputContext*, guint, guint, guint);
+ CHROMEG_CALLBACK_3(IBusIMEContext, void, OnUpdatePreeditText,
+ IBusInputContext*, IBusText*, guint, gboolean);
+ CHROMEG_CALLBACK_0(IBusIMEContext, void, OnShowPreeditText,
+ IBusInputContext*);
+ CHROMEG_CALLBACK_0(IBusIMEContext, void, OnHidePreeditText,
+ IBusInputContext*);
+ CHROMEG_CALLBACK_0(IBusIMEContext, void, OnEnable, IBusInputContext*);
+ CHROMEG_CALLBACK_0(IBusIMEContext, void, OnDisable, IBusInputContext*);
+ CHROMEG_CALLBACK_0(IBusIMEContext, void, OnDestroy, IBusInputContext*);
+
+ static void ProcessKeyEventDone(IBusInputContext* context,
+ GAsyncResult* res,
+ ProcessKeyEventData *data);
+
+ IBusInputContext* context_;
+ bool is_focused_;
+ gfx::Rect caret_rect_;
+
+ static IBusBus* bus_;
+
+ DISALLOW_COPY_AND_ASSIGN(IBusIMEContext);
+};
+
+IBusBus* IBusIMEContext::bus_ = NULL;
+
+IBusIMEContext::IBusIMEContext(views::View* view)
+ : views::IMEContext(view),
+ context_(NULL),
+ is_focused_(false) {
+ // init ibus
+ if (!bus_) {
+ ibus_init();
+ bus_ = ibus_bus_new();
+ }
+
+ // connect bus signals
+ g_signal_connect(bus_,
+ "connected",
+ G_CALLBACK(OnConnectedThunk),
+ this);
+ g_signal_connect(bus_,
+ "disconnected",
+ G_CALLBACK(OnDisconnectedThunk),
+ this);
+
+ if (ibus_bus_is_connected(bus_))
+ CreateContext();
+}
+
+IBusIMEContext::~IBusIMEContext() {
+ // disconnect bus signals
+ g_signal_handlers_disconnect_by_func(bus_,
+ reinterpret_cast<gpointer>(OnConnectedThunk), this);
+ g_signal_handlers_disconnect_by_func(bus_,
+ reinterpret_cast<gpointer>(OnDisconnectedThunk), this);
+
+ DestroyContext();
+}
+
+void IBusIMEContext::Focus() {
+ if (is_focused_)
+ return;
+ is_focused_ = true;
+
+ if (context_)
+ ibus_input_context_focus_in(context_);
+}
+
+void IBusIMEContext::Blur() {
+ if (!is_focused_)
+ return;
+
+ is_focused_ = false;
+
+ if (context_)
+ ibus_input_context_focus_out(context_);
+}
+
+void IBusIMEContext::Reset() {
+ if (context_)
+ ibus_input_context_reset(context_);
+}
+
+bool IBusIMEContext::FilterKeyEvent(const views::KeyEvent& event) {
+ guint keyval = ui::GdkKeyCodeForWindowsKeyCode(event.key_code(),
+ event.IsShiftDown() ^ event.IsCapsLockDown());
+
+ if (context_) {
+ guint modifiers = 0;
+
+ if (event.type() == ui::ET_KEY_RELEASED)
+ modifiers |= IBUS_RELEASE_MASK;
+
+ if (event.IsShiftDown())
+ modifiers |= IBUS_SHIFT_MASK;
+ if (event.IsControlDown())
+ modifiers |= IBUS_CONTROL_MASK;
+ if (event.IsAltDown())
+ modifiers |= IBUS_MOD1_MASK;
+ if (event.IsCapsLockDown())
+ modifiers |= IBUS_LOCK_MASK;
+
+ ibus_input_context_process_key_event(context_,
+ keyval, 0, modifiers,
+ -1,
+ NULL,
+ reinterpret_cast<GAsyncReadyCallback>(ProcessKeyEventDone),
+ new ProcessKeyEventData(this, event));
+ return true;
+ }
+
+ return false;
+}
+
+void IBusIMEContext::SetCursorLocation(const gfx::Rect& caret_rect) {
+ if (context_ && caret_rect_ != caret_rect) {
+ caret_rect_ = caret_rect;
+ ibus_input_context_set_cursor_location(context_,
+ caret_rect_.x(),
+ caret_rect_.y(),
+ caret_rect_.width(),
+ caret_rect_.height());
+ }
+}
+
+void IBusIMEContext::SetSurrounding(const string16& text,
+ int cursor_pos) {
+ // TODO(penghuang) support surrounding
+}
+
+void IBusIMEContext::CreateContext() {
+ DCHECK(bus_ != NULL);
+ DCHECK(ibus_bus_is_connected(bus_));
+
+ context_ = ibus_bus_create_input_context(bus_, "chrome");
+
+ // connect input context signals
+ g_signal_connect(context_,
+ "commit-text",
+ G_CALLBACK(OnCommitTextThunk),
+ this);
+ g_signal_connect(context_,
+ "forward-key-event",
+ G_CALLBACK(OnForwardKeyEventThunk),
+ this);
+ g_signal_connect(context_,
+ "update-preedit-text",
+ G_CALLBACK(OnUpdatePreeditTextThunk),
+ this);
+ g_signal_connect(context_,
+ "show-preedit-text",
+ G_CALLBACK(OnShowPreeditTextThunk),
+ this);
+ g_signal_connect(context_,
+ "hide-preedit-text",
+ G_CALLBACK(OnHidePreeditTextThunk),
+ this);
+ g_signal_connect(context_,
+ "enabled",
+ G_CALLBACK(OnEnableThunk),
+ this);
+ g_signal_connect(context_,
+ "disabled",
+ G_CALLBACK(OnDisableThunk),
+ this);
+ g_signal_connect(context_,
+ "destroy",
+ G_CALLBACK(OnDestroyThunk),
+ this);
+
+ guint32 caps = IBUS_CAP_PREEDIT_TEXT |
+ IBUS_CAP_FOCUS |
+ IBUS_CAP_SURROUNDING_TEXT;
+ ibus_input_context_set_capabilities(context_, caps);
+
+ if (is_focused_)
+ ibus_input_context_focus_in(context_);
+
+ ibus_input_context_set_cursor_location(context_,
+ caret_rect_.x(),
+ caret_rect_.y(),
+ caret_rect_.width(),
+ caret_rect_.height());
+}
+
+void IBusIMEContext::DestroyContext() {
+ if (!context_)
+ return;
+
+ ibus_proxy_destroy(reinterpret_cast<IBusProxy *>(context_));
+
+ DCHECK(!context_);
+}
+
+void IBusIMEContext::OnConnected(IBusBus *bus) {
+ DCHECK(bus_ == bus);
+ DCHECK(ibus_bus_is_connected(bus_));
+
+ if (context_)
+ DestroyContext();
+ CreateContext();
+}
+
+void IBusIMEContext::OnDisconnected(IBusBus *bus) {
+}
+
+void IBusIMEContext::OnCommitText(IBusInputContext *context,
+ IBusText* text) {
+ DCHECK(context_ == context);
+ views::IMEContext::CommitText(UTF8ToUTF16(text->text));
+}
+
+void IBusIMEContext::OnForwardKeyEvent(IBusInputContext *context,
+ guint keyval,
+ guint keycode,
+ guint state) {
+ DCHECK(context_ == context);
+
+ int flags = 0;
+
+ if (state & IBUS_LOCK_MASK)
+ flags |= ui::EF_CAPS_LOCK_DOWN;
+ if (state & IBUS_CONTROL_MASK)
+ flags |= ui::EF_CONTROL_DOWN;
+ if (state & IBUS_SHIFT_MASK)
+ flags |= ui::EF_SHIFT_DOWN;
+ if (state & IBUS_MOD1_MASK)
+ flags |= ui::EF_ALT_DOWN;
+ if (state & IBUS_BUTTON1_MASK)
+ flags |= ui::EF_LEFT_BUTTON_DOWN;
+ if (state & IBUS_BUTTON2_MASK)
+ flags |= ui::EF_MIDDLE_BUTTON_DOWN;
+ if (state & IBUS_BUTTON3_MASK)
+ flags |= ui::EF_RIGHT_BUTTON_DOWN;
+
+ ForwardKeyEvent(views::KeyEvent(
+ state & IBUS_RELEASE_MASK ?
+ ui::ET_KEY_RELEASED : ui::ET_KEY_PRESSED,
+ ui::WindowsKeyCodeForGdkKeyCode(keyval),
+ flags));
+}
+
+void IBusIMEContext::OnUpdatePreeditText(IBusInputContext *context,
+ IBusText* text,
+ guint cursor_pos,
+ gboolean visible) {
+ DCHECK(context_ == context);
+ DCHECK(IBUS_IS_TEXT(text));
+
+ if (visible) {
+ views::CompositionAttributeList attributes;
+ IBusAttrList *attrs = text->attrs;
+ if (attrs) {
+ int i = 0;
+ while (1) {
+ IBusAttribute *attr = ibus_attr_list_get(attrs, i++);
+ if (!attr)
+ break;
+ if (attr->type == IBUS_ATTR_TYPE_UNDERLINE ||
+ attr->type == IBUS_ATTR_TYPE_BACKGROUND) {
+ views::CompositionAttribute attribute(attr->start_index,
+ attr->end_index,
+ SK_ColorBLACK,
+ false);
+ if (attr->type == IBUS_ATTR_TYPE_BACKGROUND) {
+ attribute.thick = true;
+ } else if (attr->type == IBUS_ATTR_TYPE_UNDERLINE) {
+ if (attr->value == IBUS_ATTR_UNDERLINE_DOUBLE) {
+ attribute.thick = true;
+ } else if (attr->value == IBUS_ATTR_UNDERLINE_ERROR) {
+ attribute.color = SK_ColorRED;
+ }
+ }
+ attributes.push_back(attribute);
+ }
+ }
+ }
+
+ SetComposition(UTF8ToUTF16(text->text),
+ attributes,
+ cursor_pos);
+ } else {
+ EndComposition();
+ }
+}
+
+void IBusIMEContext::OnShowPreeditText(IBusInputContext *context) {
+ DCHECK(context_ == context);
+}
+
+void IBusIMEContext::OnHidePreeditText(IBusInputContext *context) {
+ DCHECK(context_ == context);
+
+ EndComposition();
+}
+
+void IBusIMEContext::OnEnable(IBusInputContext *context) {
+ DCHECK(context_ == context);
+}
+
+void IBusIMEContext::OnDisable(IBusInputContext *context) {
+ DCHECK(context_ == context);
+}
+
+void IBusIMEContext::OnDestroy(IBusInputContext *context) {
+ DCHECK(context_ == context);
+
+ g_object_unref(context_);
+ context_ = NULL;
+
+ EndComposition();
+}
+
+void IBusIMEContext::ProcessKeyEventDone(IBusInputContext *context,
+ GAsyncResult* res,
+ ProcessKeyEventData *data) {
+ DCHECK(data->context->context_ == context);
+
+ gboolean processed = FALSE;
+
+ if (!ibus_input_context_process_key_event_finish(context,
+ res,
+ &processed,
+ NULL))
+ processed = FALSE;
+
+ if (processed == FALSE)
+ data->context->ForwardKeyEvent(data->event);
+
+ delete data;
+}
+
+} // namespace
+
+namespace views {
+
+IMEContext* IMEContext::Create(View* view) {
+ return new IBusIMEContext(view);
+}
+
+} // namespace views
diff --git a/views/ime/ime_context.cc b/views/ime/ime_context.cc
new file mode 100644
index 0000000..033e3be
--- /dev/null
+++ b/views/ime/ime_context.cc
@@ -0,0 +1,88 @@
+// 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 "views/ime/ime_context.h"
+
+namespace {
+
+#ifdef USE_DUMMY_IME_CONTEXT
+class DummyIMEContext : public views::IMEContext {
+ public:
+ explicit DummyIMEContext(views::View* view)
+ : views::IMEContext(view) {}
+ virtual ~DummyIMEContext() {}
+
+ // views::IMEContext implementations:
+ virtual void Focus() {}
+ virtual void Blur() {}
+ virtual void Reset() {}
+ virtual bool FilterKeyEvent(const views::KeyEvent& event) {
+ return false;
+ }
+ virtual void SetCursorLocation(const gfx::Rect& caret_rect) {}
+ virtual void SetSurrounding(const string16& text, int cursor_pos) {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DummyIMEContext);
+};
+#endif // USE_DUMMY_IME_CONTEXT
+
+} // namespace
+
+namespace views {
+
+IMEContext::IMEContext(View* view)
+ : view_(view) ,
+ commit_text_listener_(NULL),
+ composition_listener_(NULL),
+ forward_key_event_listener_(NULL),
+ surrounding_listener_(NULL) {
+}
+
+void IMEContext::CommitText(const string16& text) {
+ if (commit_text_listener_)
+ commit_text_listener_->OnCommitText(this, text);
+}
+
+void IMEContext::StartComposition() {
+ if (composition_listener_)
+ composition_listener_->OnStartComposition(this);
+}
+
+void IMEContext::EndComposition() {
+ if (composition_listener_)
+ composition_listener_->OnEndComposition(this);
+}
+
+void IMEContext::SetComposition(const string16& text,
+ const CompositionAttributeList& attributes,
+ uint32 cursor_pos) {
+ if (composition_listener_)
+ composition_listener_->OnSetComposition(this, text, attributes, cursor_pos);
+}
+
+void IMEContext::ForwardKeyEvent(const KeyEvent& event) {
+ if (forward_key_event_listener_)
+ forward_key_event_listener_->OnForwardKeyEvent(this, event);
+}
+
+bool IMEContext::SetSurroundingActive(bool active) {
+ if (surrounding_listener_)
+ return surrounding_listener_->OnSetSurroundingActive(this, active);
+ return false;
+}
+
+bool IMEContext::DeleteSurrounding(int offset, int nchars) {
+ if (surrounding_listener_)
+ return surrounding_listener_->OnDeleteSurrounding(this, offset, nchars);
+ return false;
+}
+
+#ifdef USE_DUMMY_IME_CONTEXT
+IMEContext* IMEContext::Create(View* view) {
+ return new DummyIMEContext(view);
+}
+#endif // USE_DUMMY_IME_CONTEXT
+
+} // namespace views
diff --git a/views/ime/ime_context.h b/views/ime/ime_context.h
new file mode 100644
index 0000000..7261b4e
--- /dev/null
+++ b/views/ime/ime_context.h
@@ -0,0 +1,240 @@
+// 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.
+
+#ifndef VIEWS_IME_IME_CONTEXT_H_
+#define VIEWS_IME_IME_CONTEXT_H_
+#pragma once
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/string16.h"
+#include "third_party/skia/include/core/SkColor.h"
+
+namespace gfx {
+class Rect;
+}
+
+namespace views {
+
+class IMEContext;
+class KeyEvent;
+class View;
+
+// Duplicate WebKit::WebCompositionUnderline
+struct CompositionUnderline {
+ CompositionUnderline()
+ : start_offset(0),
+ end_offset(0),
+ color(0),
+ thick(false) {}
+
+ CompositionUnderline(uint32 s, uint32 e, SkColor c, bool t)
+ : start_offset(s),
+ end_offset(e),
+ color(c),
+ thick(t) {}
+
+ uint32 start_offset;
+ uint32 end_offset;
+ SkColor color;
+ bool thick;
+};
+
+// WebKit only supports underline attribue for composition, so we use
+// CompositionUnderline as CompositionAttribute right now.
+typedef struct CompositionUnderline CompositionAttribute;
+typedef std::vector<CompositionAttribute> CompositionAttributeList;
+
+// TODO(penghuang) more attributes (background, foreground color and etc)
+// class CompositionAttribute {
+// public:
+// enum CompositionAttributeType{
+// CAT_UNDERLINE = 1,
+// CAT_FORGROUND = 2,
+// CAT_BACKGRUND = 3,
+// };
+//
+// CompositionAttributeType GetType() const { return type_; }
+// unsigned GetStartOffset() const { return start_offset_; }
+// unsigned GetEndOffset() const { return end_offset_; }
+// unsigned GetValue() const { return value_; }
+//
+// private:
+// CompositionAttributeType type_;
+// unsigned start_offset_;
+// unsigned end_offset_;
+// unsigned value_;
+// };
+
+// CommitTextListener is notified when a text is commited from the context.
+class CommitTextListener {
+ public:
+ virtual void OnCommitText(IMEContext* sender,
+ const string16& text) = 0;
+
+ protected:
+ virtual ~CommitTextListener() {}
+};
+
+// CompositionListener is notified when composition of the context is changed.
+class CompositionListener {
+ public:
+ virtual void OnStartComposition(IMEContext* sender) = 0;
+ virtual void OnEndComposition(IMEContext* sender) = 0;
+ virtual void OnSetComposition(IMEContext* sender,
+ const string16& text,
+ const CompositionAttributeList& attributes,
+ uint32 cursor_pos) = 0;
+
+ protected:
+ virtual ~CompositionListener() {}
+};
+
+// CompositionListener is notified when a key event is forwarded from
+// the context.
+class ForwardKeyEventListener {
+ public:
+ virtual void OnForwardKeyEvent(IMEContext* sender,
+ const KeyEvent& event) = 0;
+
+ protected:
+ virtual ~ForwardKeyEventListener() {}
+};
+
+// SurroundingListener is notified when an input method context needs to
+// manipulate the text surround the input cursor. If associated view supports
+// surrounding, it should set the listener to input method context. Some input
+// methods generate different result depends on the chars before or after the
+// input cursor.
+//
+// For example:
+// Some Korean input method:
+// Key events Unicode char
+// 1 'C' +U314a
+// 2 'K' +U314f
+// 3 'C' 'K' +Ucc28
+//
+// In case 2 and 3, when users press 'K', the input method will check the char
+// before input cursor. If the char is +U314a, it will remove the char and
+// insert a new char +Ucc28. If no char before input cursor, it will insert char
+// +U314f.
+//
+// See also OnSetSurroundingActive() and OnDeleteSurrounding().
+class SurroundingListener {
+ public:
+ // Activate or inactivate surrounding support. When surrounding is activated,
+ // The assoicated view should call SetSurrounding() to notify any changes of
+ // text surround the input cursor.
+ // Return true if associated view can support surrounding.
+ virtual bool OnSetSurroundingActive(IMEContext* sender,
+ bool activate) = 0;
+
+ // Delete a picse of text surround the input cursor.
+ // Return true if associated view delete the surrounding text successfully.
+ virtual bool OnDeleteSurrounding(IMEContext* sender,
+ int offset,
+ int chars) = 0;
+ protected:
+ virtual ~SurroundingListener() {}
+};
+
+class IMEContext {
+ public:
+ virtual ~IMEContext() {}
+
+ // Set associated view.
+ void set_view(View* view) { view_ = view; }
+
+ // Get associated view.
+ const View* view() const { return view_; }
+
+ // Set a listener to receive a callback when im context commits a text.
+ void set_commit_text_listener(CommitTextListener* listener) {
+ commit_text_listener_ = listener;
+ }
+
+ // Set a listener to receive a callback when im context changes composition.
+ void set_composition_listener(CompositionListener* listener) {
+ composition_listener_ = listener;
+ }
+
+ // Set a listener to receive a callback when im context forwards a key event.
+ void set_forward_key_event_listener(ForwardKeyEventListener* listener) {
+ forward_key_event_listener_ = listener;
+ }
+
+ // Set a listener to receive a callback when im context need operater
+ // surrounding.
+ void set_surrounding_listener(SurroundingListener* listener) {
+ surrounding_listener_ = listener;
+ }
+
+ // Tell the context it got/lost focus.
+ virtual void Focus() = 0;
+ virtual void Blur() = 0;
+
+ // Reset context, context will be reset to initial state.
+ virtual void Reset() = 0;
+
+ // Filter key event, returns true, if the key event is handled,
+ // associated widget should ignore it.
+ virtual bool FilterKeyEvent(const views::KeyEvent& event) = 0;
+
+ // Set text input cursor location on screen.
+ virtual void SetCursorLocation(const gfx::Rect& caret_rect) = 0;
+
+ // Set surrounding context.
+ virtual void SetSurrounding(const string16& text,
+ int cursor_pos) = 0;
+
+ // Create an im context.
+ static IMEContext* Create(View* view);
+
+ protected:
+ explicit IMEContext(View* view);
+
+ // Commit text.
+ void CommitText(const string16& text);
+
+ // Start compostion.
+ void StartComposition();
+
+ // End composition.
+ void EndComposition();
+
+ // Set composition.
+ void SetComposition(const string16& text,
+ const CompositionAttributeList& attributes,
+ uint32 cursor_pos);
+
+ // Forward key event.
+ void ForwardKeyEvent(const KeyEvent& event);
+
+ // Notify the associated view whether or not the input context needs
+ // surrounding. When surrounding is activated, associated view should
+ // call SetSurrounding() to update any changes of text arround the input
+ // cursor.
+ // Return true if associated view can support surrounding.
+ bool SetSurroundingActive(bool activate);
+
+ // Delete surrouding arround cursor. Return true, if it is handled.
+ bool DeleteSurrounding(int offset, int nchars);
+
+ private:
+ // Client view.
+ View* view_;
+
+ // Listeners:
+ CommitTextListener* commit_text_listener_;
+ CompositionListener* composition_listener_;
+ ForwardKeyEventListener* forward_key_event_listener_;
+ SurroundingListener* surrounding_listener_;
+
+ DISALLOW_COPY_AND_ASSIGN(IMEContext);
+};
+
+} // namespace views
+
+#endif // VIEWS_IME_IM_CONTEXT_H_