Chromium Code Reviews| 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..25da540f9b545c783558376647db4af7a496eac6 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,136 @@ 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) |
|
satorux1
2012/12/02 23:14:24
add {}. the body is not one line.
Seigo Nonaka
2012/12/03 09:53:49
Done.
|
| + 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 |