| Index: chrome/browser/chromeos/input_method/ibus_ui_controller.cc
|
| diff --git a/chrome/browser/chromeos/input_method/ibus_ui_controller.cc b/chrome/browser/chromeos/input_method/ibus_ui_controller.cc
|
| index 1b70a0aa31f151cedfc79213481cbf3752e2b99d..dce2aa316794d03b2c4c13c562e24cbe378ea687 100644
|
| --- a/chrome/browser/chromeos/input_method/ibus_ui_controller.cc
|
| +++ b/chrome/browser/chromeos/input_method/ibus_ui_controller.cc
|
| @@ -1,13 +1,10 @@
|
| // Copyright (c) 2012 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.
|
| +// TODO(nona): Remvoe IBusUiController
|
|
|
| #include "chrome/browser/chromeos/input_method/ibus_ui_controller.h"
|
|
|
| -#if defined(HAVE_IBUS)
|
| -#include <ibus.h>
|
| -#endif
|
| -
|
| #include <sstream>
|
|
|
| #include "ash/shell.h"
|
| @@ -17,6 +14,8 @@
|
| #include "chrome/browser/chromeos/input_method/input_method_descriptor.h"
|
| #include "chrome/browser/chromeos/input_method/input_method_manager.h"
|
| #include "chrome/browser/chromeos/input_method/input_method_util.h"
|
| +#include "chromeos/dbus/dbus_thread_manager.h"
|
| +#include "chromeos/dbus/ibus/ibus_lookup_table.h"
|
| #include "ui/aura/client/aura_constants.h"
|
| #include "ui/aura/root_window.h"
|
| #include "ui/base/ime/input_method_ibus.h"
|
| @@ -25,18 +24,59 @@ namespace chromeos {
|
| namespace input_method {
|
| namespace {
|
|
|
| -bool IsActive(const std::string& input_method_id,
|
| - const InputMethodDescriptors* descriptors) {
|
| - for (size_t i = 0; i < descriptors->size(); ++i) {
|
| - if (descriptors->at(i).id() == input_method_id) {
|
| - return true;
|
| - }
|
| - }
|
| - return false;
|
| +// Returns pointer of IBusPanelService. This function returns NULL if it is not
|
| +// ready.
|
| +ibus::IBusPanelService* GetIBusPanelService() {
|
| + return DBusThreadManager::Get()->GetIBusPanelService();
|
| +}
|
| +
|
| +// Returns a ui::InputMethodIBus object which is associated with the root
|
| +// window. Returns NULL if the Ash shell has already been destructed.
|
| +static ui::InputMethodIBus* GetChromeInputMethod() {
|
| + if (!ash::Shell::HasInstance())
|
| + return NULL;
|
| + aura::Window* root_window = ash::Shell::GetPrimaryRootWindow();
|
| + if (!root_window)
|
| + return NULL;
|
| + return static_cast<ui::InputMethodIBus*>(root_window->GetProperty(
|
| + aura::client::kRootWindowInputMethodKey));
|
| }
|
|
|
| } // namespace
|
|
|
| +// A class for customizing the behavior of ui::InputMethodIBus for Chrome OS.
|
| +class IBusChromeOSClientImpl : public ui::internal::IBusClient {
|
| + public:
|
| + explicit IBusChromeOSClientImpl(IBusUiController* ui) : ui_(ui) {}
|
| +
|
| + // ui::IBusClient override.
|
| + virtual InputMethodType GetInputMethodType() OVERRIDE {
|
| + InputMethodManager* manager = InputMethodManager::GetInstance();
|
| + DCHECK(manager);
|
| + return InputMethodUtil::IsKeyboardLayout(
|
| + manager->GetCurrentInputMethod().id()) ?
|
| + INPUT_METHOD_XKB_LAYOUT : INPUT_METHOD_NORMAL;
|
| + }
|
| +
|
| + virtual void SetCursorLocation(const gfx::Rect& cursor_location,
|
| + const gfx::Rect& composition_head) OVERRIDE {
|
| + if (!ui_)
|
| + return;
|
| + // We don't have to call ibus_input_context_set_cursor_location() on
|
| + // Chrome OS because the candidate window for IBus is integrated with
|
| + // Chrome.
|
| + ui_->SetCursorLocation(cursor_location, composition_head);
|
| + }
|
| +
|
| + void set_ui(IBusUiController* ui) {
|
| + ui_ = ui;
|
| + }
|
| +
|
| + private:
|
| + IBusUiController* ui_;
|
| + DISALLOW_COPY_AND_ASSIGN(IBusChromeOSClientImpl);
|
| +};
|
| +
|
| InputMethodLookupTable::InputMethodLookupTable()
|
| : visible(false),
|
| cursor_absolute_index(0),
|
| @@ -64,682 +104,137 @@ std::string InputMethodLookupTable::ToString() const {
|
| return stream.str();
|
| }
|
|
|
| -#if defined(HAVE_IBUS)
|
| -
|
| -// Returns an string representation of |table| for debugging.
|
| -std::string IBusLookupTableToString(IBusLookupTable* table) {
|
| - std::stringstream stream;
|
| - stream << "page_size: " << table->page_size << "\n";
|
| - stream << "cursor_pos: " << table->cursor_pos << "\n";
|
| - stream << "cursor_visible: " << table->cursor_visible << "\n";
|
| - stream << "round: " << table->round << "\n";
|
| - stream << "orientation: " << table->orientation << "\n";
|
| - stream << "candidates:";
|
| - for (int i = 0; ; i++) {
|
| - IBusText *text = ibus_lookup_table_get_candidate(table, i);
|
| - if (!text) {
|
| - break;
|
| - }
|
| - stream << " " << text->text;
|
| - }
|
| - return stream.str();
|
| -}
|
| -
|
| // The real implementation of the IBusUiController.
|
| -class IBusUiControllerImpl : public IBusUiController {
|
| - public:
|
| - IBusUiControllerImpl()
|
| - : ibus_(NULL),
|
| - ibus_panel_service_(NULL) {
|
| - ui::InputMethodIBus* input_method = GetChromeInputMethod();
|
| - DCHECK(input_method);
|
| - input_method->set_ibus_client(scoped_ptr<ui::internal::IBusClient>(
|
| - new IBusChromeOSClientImpl(this)).Pass());
|
| - }
|
| -
|
| - ~IBusUiControllerImpl() {
|
| - ui::InputMethodIBus* input_method = GetChromeInputMethod();
|
| - if (input_method) {
|
| - ui::internal::IBusClient* client = input_method->ibus_client();
|
| - // We assume that no objects other than |this| set an IBus client.
|
| - DCHECK(client);
|
| - static_cast<IBusChromeOSClientImpl*>(client)->set_ui(NULL);
|
| - }
|
| - // ibus_panel_service_ depends on ibus_, thus unref it first.
|
| - if (ibus_panel_service_) {
|
| - DisconnectPanelServiceSignals();
|
| - g_object_unref(ibus_panel_service_);
|
| - }
|
| - if (ibus_) {
|
| - DisconnectIBusSignals();
|
| - g_object_unref(ibus_);
|
| - }
|
| - }
|
| -
|
| - // Creates IBusBus object if it's not created yet, and tries to connect to
|
| - // ibus-daemon. Returns true if IBusBus is successfully connected to the
|
| - // daemon.
|
| - bool ConnectToIBus() {
|
| - if (ibus_) {
|
| - return true;
|
| - }
|
| - ibus_init();
|
| - ibus_ = ibus_bus_new();
|
| - CHECK(ibus_) << "ibus_bus_new() failed. Out of memory?";
|
| -
|
| - bool result = false;
|
| - // Check the IBus connection status.
|
| - if (ibus_bus_is_connected(ibus_)) {
|
| - DVLOG(1) << "ibus_bus_is_connected(). IBus connection is ready.";
|
| - FOR_EACH_OBSERVER(Observer, observers_, OnConnectionChange(true));
|
| - result = true;
|
| - }
|
| -
|
| - // Start listening the gobject signals regardless of the bus connection
|
| - // status.
|
| - ConnectIBusSignals();
|
| - return result;
|
| - }
|
| -
|
| - // Creates IBusPanelService object if |ibus_| is already connected.
|
| - bool MaybeRestorePanelService() {
|
| - if (!ibus_ || !ibus_bus_is_connected(ibus_)) {
|
| - return false;
|
| - }
|
| -
|
| - if (ibus_panel_service_) {
|
| - DVLOG(1) << "IBusPanelService is already available. Remove it first.";
|
| - g_object_set_data(G_OBJECT(ibus_), kPanelObjectKey, NULL);
|
| - g_object_unref(ibus_panel_service_);
|
| - ibus_panel_service_ = NULL;
|
| - }
|
| -
|
| - // Create an IBusPanelService object.
|
| - GDBusConnection* ibus_connection = ibus_bus_get_connection(ibus_);
|
| - if (!ibus_connection) {
|
| - DVLOG(1) << "ibus_bus_get_connection() failed";
|
| - return false;
|
| - }
|
| - ibus_panel_service_ = ibus_panel_service_new(ibus_connection);
|
| - if (!ibus_panel_service_) {
|
| - DVLOG(1) << "ibus_chromeos_panel_service_new() failed";
|
| - return false;
|
| - }
|
| - ConnectPanelServiceSignals();
|
| - g_object_set_data(G_OBJECT(ibus_), kPanelObjectKey, ibus_panel_service_);
|
| - DVLOG(1) << "IBusPanelService object is successfully (re-)created.";
|
| -
|
| - // Request the well-known name *asynchronously*.
|
| - ibus_bus_request_name_async(ibus_,
|
| - IBUS_SERVICE_PANEL,
|
| - 0 /* flags */,
|
| - -1 /* timeout */,
|
| - NULL /* cancellable */,
|
| - RequestNameCallback,
|
| - g_object_ref(ibus_));
|
| - return true;
|
| - }
|
| -
|
| - // IBusUiController override.
|
| - virtual void NotifyCandidateClicked(int index,
|
| - int button,
|
| - int flags) OVERRIDE {
|
| - if (!ibus_ || !ibus_bus_is_connected(ibus_)) {
|
| - DVLOG(1) << "NotifyCandidateClicked: bus is not connected.";
|
| - return;
|
| - }
|
| - if (!ibus_panel_service_) {
|
| - DVLOG(1) << "NotifyCandidateClicked: panel service is not available.";
|
| - return;
|
| - }
|
| -
|
| - /* Send a D-Bus signal to ibus-daemon *asynchronously*. */
|
| - ibus_panel_service_candidate_clicked(ibus_panel_service_,
|
| - index,
|
| - button,
|
| - flags);
|
| - }
|
| -
|
| - // IBusUiController override.
|
| - virtual void NotifyCursorUp() OVERRIDE {
|
| - if (!ibus_ || !ibus_bus_is_connected(ibus_)) {
|
| - DVLOG(1) << "NotifyCursorUp: bus is not connected.";
|
| - return;
|
| - }
|
| - if (!ibus_panel_service_) {
|
| - DVLOG(1) << "NotifyCursorUp: panel service is not available.";
|
| - return;
|
| - }
|
| -
|
| - /* Send a D-Bus signal to ibus-daemon *asynchronously*. */
|
| - ibus_panel_service_cursor_up(ibus_panel_service_);
|
| - }
|
| -
|
| - // IBusUiController override.
|
| - virtual void NotifyCursorDown() OVERRIDE {
|
| - if (!ibus_ || !ibus_bus_is_connected(ibus_)) {
|
| - DVLOG(1) << "NotifyCursorDown: bus is not connected.";
|
| - return;
|
| - }
|
| - if (!ibus_panel_service_) {
|
| - DVLOG(1) << "NotifyCursorDown: panel service is not available.";
|
| - return;
|
| - }
|
| - /* Send a D-Bus signal to ibus-daemon *asynchronously*. */
|
| - ibus_panel_service_cursor_down(ibus_panel_service_);
|
| - }
|
| -
|
| - // IBusUiController override.
|
| - virtual void NotifyPageUp() OVERRIDE {
|
| - if (!ibus_ || !ibus_bus_is_connected(ibus_)) {
|
| - DVLOG(1) << "NotifyPageUp: bus is not connected.";
|
| - return;
|
| - }
|
| - if (!ibus_panel_service_) {
|
| - DVLOG(1) << "NotifyPageUp: panel service is not available.";
|
| - return;
|
| - }
|
| -
|
| - /* Send a D-Bus signal to ibus-daemon *asynchronously*. */
|
| - ibus_panel_service_page_up(ibus_panel_service_);
|
| - }
|
| -
|
| - // IBusUiController override.
|
| - virtual void NotifyPageDown() OVERRIDE {
|
| - if (!ibus_ || !ibus_bus_is_connected(ibus_)) {
|
| - DVLOG(1) << "NotifyPageDown: bus is not connected.";
|
| - return;
|
| - }
|
| - if (!ibus_panel_service_) {
|
| - DVLOG(1) << "NotifyPageDown: panel service is not available.";
|
| - return;
|
| - }
|
| -
|
| - /* Send a D-Bus signal to ibus-daemon *asynchronously*. */
|
| - ibus_panel_service_page_down(ibus_panel_service_);
|
| - }
|
| -
|
| - // IBusUiController override.
|
| - virtual void Connect() OVERRIDE {
|
| - // It's totally fine if ConnectToIBus() fails here, as we'll get
|
| - // "connected" gobject signal once the connection becomes ready.
|
| - if (ConnectToIBus())
|
| - MaybeRestorePanelService();
|
| - }
|
| -
|
| - // IBusUiController override.
|
| - virtual void AddObserver(Observer* observer) OVERRIDE {
|
| - observers_.AddObserver(observer);
|
| - }
|
| -
|
| - // IBusUiController override.
|
| - virtual void RemoveObserver(Observer* observer) OVERRIDE {
|
| - observers_.RemoveObserver(observer);
|
| - }
|
| -
|
| - private:
|
| - // A class for customizing the behavior of ui::InputMethodIBus for Chrome OS.
|
| - class IBusChromeOSClientImpl : public ui::internal::IBusClient {
|
| - public:
|
| - explicit IBusChromeOSClientImpl(IBusUiControllerImpl* ui)
|
| - : ui_(ui) {
|
| - }
|
| -
|
| - // ui::IBusClient override.
|
| - virtual InputMethodType GetInputMethodType() OVERRIDE {
|
| - const std::string current_input_method_id = GetCurrentInputMethodId();
|
| - return InputMethodUtil::IsKeyboardLayout(current_input_method_id) ?
|
| - INPUT_METHOD_XKB_LAYOUT : INPUT_METHOD_NORMAL;
|
| - }
|
| -
|
| - virtual void SetCursorLocation(const gfx::Rect& cursor_location,
|
| - const gfx::Rect& composition_head) OVERRIDE {
|
| - if (!ui_)
|
| - return;
|
| - // We don't have to call ibus_input_context_set_cursor_location() on
|
| - // Chrome OS because the candidate window for IBus is integrated with
|
| - // Chrome.
|
| - ui_->SetCursorLocation(NULL, cursor_location, composition_head);
|
| - }
|
| -
|
| - void set_ui(IBusUiControllerImpl* ui) {
|
| - ui_ = ui;
|
| - }
|
| -
|
| - private:
|
| - std::string GetCurrentInputMethodId() {
|
| - InputMethodManager* manager = InputMethodManager::GetInstance();
|
| - return manager->GetCurrentInputMethod().id();
|
| - }
|
| -
|
| - IBusUiControllerImpl* ui_;
|
| - };
|
| -
|
| - // Returns a ui::InputMethodIBus object which is associated with the root
|
| - // window. Returns NULL if the Ash shell has already been destructed.
|
| - static ui::InputMethodIBus* GetChromeInputMethod() {
|
| - if (!ash::Shell::HasInstance())
|
| - return NULL;
|
| - aura::Window* root_window = ash::Shell::GetPrimaryRootWindow();
|
| - if (!root_window)
|
| - return NULL;
|
| - return static_cast<ui::InputMethodIBus*>(root_window->GetProperty(
|
| - aura::client::kRootWindowInputMethodKey));
|
| - }
|
| -
|
| - // Functions that end with Thunk are used to deal with glib callbacks.
|
| - //
|
| - // Note that we cannot use CHROMEG_CALLBACK_0() here as we'll define
|
| - // IBusBusConnected() inline. If we are to define the function outside
|
| - // of the class definition, we should use CHROMEG_CALLBACK_0() here.
|
| - //
|
| - // CHROMEG_CALLBACK_0(Impl,
|
| - // void, IBusBusConnected, IBusBus*);
|
| - static void IBusBusConnectedThunk(IBusBus* sender, gpointer userdata) {
|
| - return reinterpret_cast<IBusUiControllerImpl*>(userdata)
|
| - ->IBusBusConnected(sender);
|
| - }
|
| - static void IBusBusDisconnectedThunk(IBusBus* sender, gpointer userdata) {
|
| - return reinterpret_cast<IBusUiControllerImpl*>(userdata)
|
| - ->IBusBusDisconnected(sender);
|
| - }
|
| - static void HideAuxiliaryTextThunk(IBusPanelService* sender,
|
| - gpointer userdata) {
|
| - return reinterpret_cast<IBusUiControllerImpl*>(userdata)
|
| - ->HideAuxiliaryText(sender);
|
| - }
|
| - static void HideLookupTableThunk(IBusPanelService* sender,
|
| - gpointer userdata) {
|
| - return reinterpret_cast<IBusUiControllerImpl*>(userdata)
|
| - ->HideLookupTable(sender);
|
| - }
|
| - static void UpdateAuxiliaryTextThunk(IBusPanelService* sender,
|
| - IBusText* text, gboolean visible,
|
| - gpointer userdata) {
|
| - return reinterpret_cast<IBusUiControllerImpl*>(userdata)
|
| - ->UpdateAuxiliaryText(sender, text, visible);
|
| - }
|
| - static void SetCursorLocationThunk(IBusPanelService* sender,
|
| - gint x, gint y, gint width, gint height,
|
| - gpointer userdata) {
|
| - return reinterpret_cast<IBusUiControllerImpl*>(userdata)
|
| - ->SetCursorLocation(sender, gfx::Rect(x, y, width, height),
|
| - gfx::Rect());
|
| - }
|
| - static void UpdateLookupTableThunk(IBusPanelService* sender,
|
| - IBusLookupTable* table, gboolean visible,
|
| - gpointer userdata) {
|
| - return reinterpret_cast<IBusUiControllerImpl*>(userdata)
|
| - ->UpdateLookupTable(sender, table, visible);
|
| - }
|
| - static void UpdatePreeditTextThunk(IBusPanelService* sender,
|
| - IBusText* text,
|
| - guint cursor_pos,
|
| - gboolean visible,
|
| - gpointer userdata) {
|
| - return reinterpret_cast<IBusUiControllerImpl*>(userdata)
|
| - ->UpdatePreeditText(sender, text, cursor_pos, visible);
|
| - }
|
| - static void HidePreeditTextThunk(IBusPanelService* sender,
|
| - gpointer userdata) {
|
| - return reinterpret_cast<IBusUiControllerImpl*>(userdata)
|
| - ->HidePreeditText(sender);
|
| - }
|
| -
|
| -
|
| - // Installs gobject signal handlers to |ibus_|.
|
| - void ConnectIBusSignals() {
|
| - if (!ibus_) {
|
| - return;
|
| - }
|
| - g_signal_connect(ibus_,
|
| - "connected",
|
| - G_CALLBACK(IBusBusConnectedThunk),
|
| - this);
|
| - g_signal_connect(ibus_,
|
| - "disconnected",
|
| - G_CALLBACK(IBusBusDisconnectedThunk),
|
| - this);
|
| - }
|
| -
|
| - // Removes gobject signal handlers from |ibus_|.
|
| - void DisconnectIBusSignals() {
|
| - if (!ibus_) {
|
| - return;
|
| - }
|
| - g_signal_handlers_disconnect_by_func(
|
| - ibus_,
|
| - reinterpret_cast<gpointer>(G_CALLBACK(IBusBusConnectedThunk)),
|
| - this);
|
| - g_signal_handlers_disconnect_by_func(
|
| - ibus_,
|
| - reinterpret_cast<gpointer>(G_CALLBACK(IBusBusDisconnectedThunk)),
|
| - this);
|
| - }
|
| -
|
| - // Installs gobject signal handlers to |ibus_panel_service_|.
|
| - void ConnectPanelServiceSignals() {
|
| - if (!ibus_panel_service_) {
|
| - return;
|
| - }
|
| - g_signal_connect(ibus_panel_service_,
|
| - "hide-auxiliary-text",
|
| - G_CALLBACK(HideAuxiliaryTextThunk),
|
| - this);
|
| - g_signal_connect(ibus_panel_service_,
|
| - "hide-lookup-table",
|
| - G_CALLBACK(HideLookupTableThunk),
|
| - this);
|
| - g_signal_connect(ibus_panel_service_,
|
| - "update-auxiliary-text",
|
| - G_CALLBACK(UpdateAuxiliaryTextThunk),
|
| - this);
|
| - g_signal_connect(ibus_panel_service_,
|
| - "set-cursor-location",
|
| - G_CALLBACK(SetCursorLocationThunk),
|
| - this);
|
| - g_signal_connect(ibus_panel_service_,
|
| - "update-lookup-table",
|
| - G_CALLBACK(UpdateLookupTableThunk),
|
| - this);
|
| - g_signal_connect(ibus_panel_service_,
|
| - "update-preedit-text",
|
| - G_CALLBACK(UpdatePreeditTextThunk),
|
| - this);
|
| - g_signal_connect(ibus_panel_service_,
|
| - "hide-preedit-text",
|
| - G_CALLBACK(HidePreeditTextThunk),
|
| - this);
|
| - }
|
| -
|
| - // Removes gobject signal handlers from |ibus_panel_service_|.
|
| - void DisconnectPanelServiceSignals() {
|
| - if (!ibus_panel_service_) {
|
| - return;
|
| - }
|
| - g_signal_handlers_disconnect_by_func(
|
| - ibus_panel_service_,
|
| - reinterpret_cast<gpointer>(HideAuxiliaryTextThunk),
|
| - this);
|
| - g_signal_handlers_disconnect_by_func(
|
| - ibus_panel_service_,
|
| - reinterpret_cast<gpointer>(HideLookupTableThunk),
|
| - this);
|
| - g_signal_handlers_disconnect_by_func(
|
| - ibus_panel_service_,
|
| - reinterpret_cast<gpointer>(UpdateAuxiliaryTextThunk),
|
| - this);
|
| - g_signal_handlers_disconnect_by_func(
|
| - ibus_panel_service_,
|
| - reinterpret_cast<gpointer>(SetCursorLocationThunk),
|
| - this);
|
| - g_signal_handlers_disconnect_by_func(
|
| - ibus_panel_service_,
|
| - reinterpret_cast<gpointer>(UpdateLookupTableThunk),
|
| - this);
|
| - g_signal_handlers_disconnect_by_func(
|
| - ibus_panel_service_,
|
| - reinterpret_cast<gpointer>(UpdatePreeditTextThunk),
|
| - this);
|
| - g_signal_handlers_disconnect_by_func(
|
| - ibus_panel_service_,
|
| - reinterpret_cast<gpointer>(HidePreeditTextThunk),
|
| - this);
|
| - }
|
| -
|
| - // Handles "connected" signal from ibus-daemon.
|
| - void IBusBusConnected(IBusBus* bus) {
|
| - DVLOG(1) << "IBus connection is recovered.";
|
| - if (!MaybeRestorePanelService()) {
|
| - DVLOG(1) << "MaybeRestorePanelService() failed";
|
| - return;
|
| - }
|
| +IBusUiController::IBusUiController() {
|
| + ui::InputMethodIBus* input_method = GetChromeInputMethod();
|
| + DCHECK(input_method);
|
| + input_method->set_ibus_client(scoped_ptr<ui::internal::IBusClient>(
|
| + new IBusChromeOSClientImpl(this)).Pass());
|
| +}
|
|
|
| - FOR_EACH_OBSERVER(Observer, observers_, OnConnectionChange(true));
|
| +IBusUiController::~IBusUiController() {
|
| + ui::InputMethodIBus* input_method = GetChromeInputMethod();
|
| + if (input_method) {
|
| + ui::internal::IBusClient* client = input_method->ibus_client();
|
| + // We assume that no objects other than |this| set an IBus client.
|
| + DCHECK(client);
|
| + static_cast<IBusChromeOSClientImpl*>(client)->set_ui(NULL);
|
| }
|
| +}
|
|
|
| - // Handles "disconnected" signal from ibus-daemon. Releases the
|
| - // |ibus_panel_service_| object since the connection the service has will be
|
| - // destroyed soon.
|
| - void IBusBusDisconnected(IBusBus* bus) {
|
| - DVLOG(1) << "IBus connection is terminated.";
|
| - if (ibus_panel_service_) {
|
| - DisconnectPanelServiceSignals();
|
| - // Since the connection being disconnected is currently mutex-locked,
|
| - // we can't unref the panel service object directly here. Because when the
|
| - // service object is deleted, the connection, which the service also has,
|
| - // will be locked again. To avoid deadlock, we use g_idle_add instead.
|
| - g_object_set_data(G_OBJECT(ibus_), kPanelObjectKey, NULL);
|
| - g_idle_add(ReleasePanelService, ibus_panel_service_);
|
| - ibus_panel_service_ = NULL;
|
| - }
|
| -
|
| - FOR_EACH_OBSERVER(Observer, observers_, OnConnectionChange(false));
|
| +void IBusUiController::NotifyCandidateClicked(int index, int button,
|
| + int flags) {
|
| + ibus::IBusPanelService* service = GetIBusPanelService();
|
| + if (service) {
|
| + service->CandidateClicked(
|
| + index,
|
| + static_cast<ibus::IBusMouseButton>(button),
|
| + flags);
|
| }
|
| +}
|
|
|
| - // Releases |ibus_panel_service_|. See the comment above.
|
| - static gboolean ReleasePanelService(gpointer user_data) {
|
| - g_return_val_if_fail(IBUS_IS_PANEL_SERVICE(user_data), FALSE);
|
| - g_object_unref(user_data);
|
| - return FALSE; // stop the idle timer.
|
| - }
|
| +void IBusUiController::NotifyCursorUp() {
|
| + ibus::IBusPanelService* service = GetIBusPanelService();
|
| + if (service)
|
| + service->CursorUp();
|
| +}
|
|
|
| - // Handles IBusPanelService's |HideAuxiliaryText| method call.
|
| - void HideAuxiliaryText(IBusPanelService* panel) {
|
| - FOR_EACH_OBSERVER(Observer, observers_, OnHideAuxiliaryText());
|
| - }
|
| +void IBusUiController::NotifyCursorDown() {
|
| + ibus::IBusPanelService* service = GetIBusPanelService();
|
| + if (service)
|
| + service->CursorDown();
|
| +}
|
|
|
| - // Handles IBusPanelService's |HideLookupTable| method call.
|
| - void HideLookupTable(IBusPanelService *panel) {
|
| - FOR_EACH_OBSERVER(Observer, observers_, OnHideLookupTable());
|
| - }
|
| +void IBusUiController::NotifyPageUp() {
|
| + ibus::IBusPanelService* service = GetIBusPanelService();
|
| + if (service)
|
| + service->PageUp();
|
| +}
|
|
|
| - // Handles IBusPanelService's |UpdateAuxiliaryText| method call.
|
| - void UpdateAuxiliaryText(IBusPanelService* panel,
|
| - IBusText* text,
|
| - gboolean visible) {
|
| - g_return_if_fail(text);
|
| - g_return_if_fail(text->text);
|
| - // Convert IBusText to a std::string. IBusText is an attributed text,
|
| - const std::string simple_text = text->text;
|
| - FOR_EACH_OBSERVER(Observer, observers_,
|
| - OnUpdateAuxiliaryText(simple_text, visible == TRUE));
|
| - }
|
| +void IBusUiController::NotifyPageDown() {
|
| + ibus::IBusPanelService* service = GetIBusPanelService();
|
| + if (service)
|
| + service->PageDown();
|
| +}
|
|
|
| - // Handles IBusPanelService's |SetCursorLocation| method call.
|
| - void SetCursorLocation(IBusPanelService *panel,
|
| - const gfx::Rect& cursor_location,
|
| - const gfx::Rect& composition_head) {
|
| - // Note: |panel| might be NULL. See IBusChromeOSClientImpl above.
|
| - FOR_EACH_OBSERVER(Observer, observers_,
|
| - OnSetCursorLocation(cursor_location, composition_head));
|
| - }
|
| +void IBusUiController::AddObserver(Observer* observer) {
|
| + observers_.AddObserver(observer);
|
| +}
|
|
|
| - // Handles IBusPanelService's |UpdatePreeditText| method call.
|
| - void UpdatePreeditText(IBusPanelService *panel,
|
| - IBusText *text,
|
| - guint cursor_pos,
|
| - gboolean visible) {
|
| - FOR_EACH_OBSERVER(Observer, observers_,
|
| - OnUpdatePreeditText(text->text, cursor_pos, visible));
|
| - }
|
| +void IBusUiController::RemoveObserver(Observer* observer) {
|
| + observers_.RemoveObserver(observer);
|
| +}
|
|
|
| - // Handles IBusPanelService's |UpdatePreeditText| method call.
|
| - void HidePreeditText(IBusPanelService *panel) {
|
| - FOR_EACH_OBSERVER(Observer, observers_, OnHidePreeditText());
|
| - }
|
| +void IBusUiController::HideAuxiliaryText() {
|
| + FOR_EACH_OBSERVER(Observer, observers_, OnHideAuxiliaryText());
|
| +}
|
|
|
| - // Handles IBusPanelService's |UpdateLookupTable| method call.
|
| - void UpdateLookupTable(IBusPanelService *panel,
|
| - IBusLookupTable *table,
|
| - gboolean visible) {
|
| - g_return_if_fail(table);
|
| -
|
| - InputMethodLookupTable lookup_table;
|
| - lookup_table.visible = (visible == TRUE);
|
| -
|
| - // Copy the orientation information.
|
| - const gint orientation = ibus_lookup_table_get_orientation(table);
|
| - if (orientation == IBUS_ORIENTATION_VERTICAL) {
|
| - lookup_table.orientation = InputMethodLookupTable::kVertical;
|
| - } else if (orientation == IBUS_ORIENTATION_HORIZONTAL) {
|
| - lookup_table.orientation = InputMethodLookupTable::kHorizontal;
|
| - }
|
| -
|
| - // The function ibus_serializable_get_attachment had been changed
|
| - // to use GVariant by the commit
|
| - // https://github.com/ibus/ibus/commit/ac9dfac13cef34288440a2ecdf067cd827fb2f8f
|
| - GVariant* variant = ibus_serializable_get_attachment(
|
| - IBUS_SERIALIZABLE(table), "show_window_at_composition");
|
| - if (variant)
|
| - lookup_table.show_at_composition_head = !!g_variant_get_boolean(variant);
|
| - else
|
| - lookup_table.show_at_composition_head = false;
|
| -
|
| - // Copy candidates and annotations to |lookup_table|.
|
| - for (int i = 0; ; i++) {
|
| - IBusText *text = ibus_lookup_table_get_candidate(table, i);
|
| - if (!text)
|
| - break;
|
| - lookup_table.candidates.push_back(text->text);
|
| -
|
| - IBusText *label = ibus_lookup_table_get_label(table, i);
|
| - if (label)
|
| - lookup_table.labels.push_back(label->text);
|
| -
|
| - GVariant* annotation_variant =
|
| - ibus_serializable_get_attachment(IBUS_SERIALIZABLE(text),
|
| - "annotation");
|
| - lookup_table.annotations.push_back("");
|
| - if (annotation_variant) {
|
| - const gchar* annotation =
|
| - g_variant_get_string(annotation_variant, NULL);
|
| - if (annotation)
|
| - lookup_table.annotations[i] = annotation;
|
| - }
|
| -
|
| - GVariant* description_title_variant =
|
| - ibus_serializable_get_attachment(IBUS_SERIALIZABLE(text),
|
| - "description_title");
|
| - InputMethodLookupTable::Description description;
|
| - if (description_title_variant) {
|
| - const gchar* description_title =
|
| - g_variant_get_string(description_title_variant, NULL);
|
| - if (description_title)
|
| - description.title = description_title;
|
| -
|
| - }
|
| -
|
| - GVariant* description_body_variant =
|
| - ibus_serializable_get_attachment(IBUS_SERIALIZABLE(text),
|
| - "description_body");
|
| - if (description_body_variant) {
|
| - const gchar* description_body =
|
| - g_variant_get_string(description_body_variant, NULL);
|
| - if (description_body)
|
| - description.body = description_body;
|
| - }
|
| - lookup_table.descriptions.push_back(description);
|
| - }
|
| - DCHECK_EQ(lookup_table.candidates.size(),
|
| - lookup_table.annotations.size());
|
| -
|
| - lookup_table.cursor_absolute_index =
|
| - ibus_lookup_table_get_cursor_pos(table);
|
| - lookup_table.page_size = ibus_lookup_table_get_page_size(table);
|
| - // Ensure that the page_size is non-zero to avoid div-by-zero error.
|
| - if (lookup_table.page_size <= 0) {
|
| - DVLOG(1) << "Invalid page size: " << lookup_table.page_size;
|
| - lookup_table.page_size = 1;
|
| - }
|
| -
|
| - FOR_EACH_OBSERVER(Observer, observers_,
|
| - OnUpdateLookupTable(lookup_table));
|
| - }
|
| +void IBusUiController::HideLookupTable() {
|
| + FOR_EACH_OBSERVER(Observer, observers_, OnHideLookupTable());
|
| +}
|
|
|
| - // A callback function that will be called when ibus_bus_request_name_async()
|
| - // request is finished.
|
| - static void RequestNameCallback(GObject* source_object,
|
| - GAsyncResult* res,
|
| - gpointer user_data) {
|
| - IBusBus* bus = IBUS_BUS(user_data);
|
| - g_return_if_fail(bus);
|
| -
|
| - GError* error = NULL;
|
| - const guint service_id =
|
| - ibus_bus_request_name_async_finish(bus, res, &error);
|
| -
|
| - if (!service_id) {
|
| - std::string message = "(unknown error)";
|
| - if (error && error->message) {
|
| - message = error->message;
|
| - }
|
| - DVLOG(1) << "Failed to register the panel service: " << message;
|
| - } else {
|
| - DVLOG(1) << "The panel service is registered: ID=" << service_id;
|
| - }
|
| -
|
| - if (error) {
|
| - g_error_free(error);
|
| - }
|
| - g_object_unref(bus);
|
| - }
|
| +void IBusUiController::UpdateAuxiliaryText(const std::string& text,
|
| + bool visible) {
|
| + FOR_EACH_OBSERVER(Observer, observers_,
|
| + OnUpdateAuxiliaryText(text, visible));
|
| +}
|
|
|
| - IBusBus* ibus_;
|
| - IBusPanelService* ibus_panel_service_;
|
| - ObserverList<Observer> observers_;
|
| -};
|
| -#endif // defined(HAVE_IBUS)
|
| -
|
| -// The stub implementation is used if IBus is not present.
|
| -//
|
| -// Note that this class is intentionally built even if HAVE_IBUS is
|
| -// defined so that we can easily tell build breakage when we change the
|
| -// IBusUiControllerImpl but forget to update the stub implementation.
|
| -class IBusUiControllerStubImpl : public IBusUiController {
|
| - public:
|
| - IBusUiControllerStubImpl() {
|
| - }
|
| +void IBusUiController::SetCursorLocation(const gfx::Rect& cursor_location,
|
| + const gfx::Rect& composition_head) {
|
| + FOR_EACH_OBSERVER(Observer, observers_,
|
| + OnSetCursorLocation(cursor_location, composition_head));
|
| +}
|
|
|
| - virtual void Connect() {
|
| - }
|
| +void IBusUiController::UpdatePreeditText(const std::string& text,
|
| + uint32 cursor_pos,
|
| + bool visible) {
|
| + FOR_EACH_OBSERVER(Observer, observers_,
|
| + OnUpdatePreeditText(text, cursor_pos, visible));
|
| +}
|
|
|
| - virtual void AddObserver(Observer* observer) {
|
| - }
|
| +void IBusUiController::HidePreeditText() {
|
| + FOR_EACH_OBSERVER(Observer, observers_, OnHidePreeditText());
|
| +}
|
|
|
| - virtual void RemoveObserver(Observer* observer) {
|
| - }
|
| +void IBusUiController::UpdateLookupTable(const ibus::IBusLookupTable& table,
|
| + bool visible) {
|
| + // TODO(nona): Use ibus::IBusLookupTable instead.
|
| + InputMethodLookupTable lookup_table;
|
| + lookup_table.visible = visible;
|
|
|
| - virtual void NotifyCandidateClicked(int index, int button, int flags) {
|
| + // Copy the orientation information.
|
| + if (table.orientation() ==
|
| + ibus::IBusLookupTable::IBUS_LOOKUP_TABLE_ORIENTATION_VERTICAL) {
|
| + lookup_table.orientation = InputMethodLookupTable::kVertical;
|
| + } else {
|
| + lookup_table.orientation = InputMethodLookupTable::kHorizontal;
|
| }
|
|
|
| - virtual void NotifyCursorUp() {
|
| - }
|
| + lookup_table.show_at_composition_head = table.show_window_at_composition();
|
|
|
| - virtual void NotifyCursorDown() {
|
| - }
|
| + // Copy candidates and annotations to |lookup_table|.
|
| + for (size_t i = 0; i < table.candidates().size(); ++i) {
|
| + const ibus::IBusLookupTable::Entry& entry = table.candidates()[i];
|
| + lookup_table.candidates.push_back(entry.value);
|
| + lookup_table.labels.push_back(entry.label);
|
| + lookup_table.annotations.push_back(entry.annotation);
|
|
|
| - virtual void NotifyPageUp() {
|
| + InputMethodLookupTable::Description description;
|
| + description.title = entry.description_title;
|
| + description.body = entry.description_body;
|
| + lookup_table.descriptions.push_back(description);
|
| }
|
|
|
| - virtual void NotifyPageDown() {
|
| + lookup_table.cursor_absolute_index = table.cursor_position();
|
| + lookup_table.page_size = table.page_size();
|
| + // Ensure that the page_size is non-zero to avoid div-by-zero error.
|
| + if (lookup_table.page_size <= 0) {
|
| + DVLOG(1) << "Invalid page size: " << lookup_table.page_size;
|
| + lookup_table.page_size = 1;
|
| }
|
| -};
|
| -
|
| -IBusUiController* IBusUiController::Create() {
|
| -#if defined(HAVE_IBUS)
|
| - return new IBusUiControllerImpl;
|
| -#else
|
| - return new IBusUiControllerStubImpl;
|
| -#endif
|
| -}
|
| -
|
| -IBusUiController::~IBusUiController() {
|
| -}
|
|
|
| -bool IsActiveForTesting(const std::string& input_method_id,
|
| - const InputMethodDescriptors* descriptors) {
|
| - return IsActive(input_method_id, descriptors);
|
| + FOR_EACH_OBSERVER(Observer, observers_,
|
| + OnUpdateLookupTable(lookup_table));
|
| }
|
|
|
| } // namespace input_method
|
|
|