diff options
Diffstat (limited to 'chromium/ui/base/ime')
46 files changed, 593 insertions, 563 deletions
diff --git a/chromium/ui/base/ime/BUILD.gn b/chromium/ui/base/ime/BUILD.gn index 2a0670796c0..5ab39cdea54 100644 --- a/chromium/ui/base/ime/BUILD.gn +++ b/chromium/ui/base/ime/BUILD.gn @@ -58,8 +58,6 @@ jumbo_component("ime") { "constants.cc", "constants.h", "ime_assistive_window_handler_interface.h", - "ime_bridge.cc", - "ime_bridge.h", "ime_candidate_window_handler_interface.h", "ime_engine_handler_interface.h", "ime_input_context_handler_interface.h", @@ -81,7 +79,6 @@ jumbo_component("ime") { "text_edit_commands.h", "text_input_client.cc", "text_input_client.h", - "virtual_keyboard_visibility_request.h", ] defines = [ "IS_UI_BASE_IME_IMPL" ] diff --git a/chromium/ui/base/ime/chromeos/BUILD.gn b/chromium/ui/base/ime/chromeos/BUILD.gn index 4baf9294a95..03f91b5ea59 100644 --- a/chromium/ui/base/ime/chromeos/BUILD.gn +++ b/chromium/ui/base/ime/chromeos/BUILD.gn @@ -22,6 +22,8 @@ jumbo_component("chromeos") { "fake_ime_keyboard.h", "fake_input_method_delegate.cc", "fake_input_method_delegate.h", + "ime_bridge.cc", + "ime_bridge.h", "ime_keyboard.cc", "ime_keyboard_impl.cc", "ime_keyboard_impl.h", diff --git a/chromium/ui/base/ime/dummy_input_method.cc b/chromium/ui/base/ime/dummy_input_method.cc index 4e3dff450b2..da32e766c9c 100644 --- a/chromium/ui/base/ime/dummy_input_method.cc +++ b/chromium/ui/base/ime/dummy_input_method.cc @@ -98,9 +98,4 @@ DummyInputMethod::GetInputMethodKeyboardController() { return nullptr; } -const std::vector<std::unique_ptr<KeyEvent>>& -DummyInputMethod::GetKeyEventsForTesting() { - return key_events_for_testing_; -} - } // namespace ui diff --git a/chromium/ui/base/ime/dummy_input_method.h b/chromium/ui/base/ime/dummy_input_method.h index 9865876b0ad..fba6e76cdb2 100644 --- a/chromium/ui/base/ime/dummy_input_method.h +++ b/chromium/ui/base/ime/dummy_input_method.h @@ -49,11 +49,7 @@ class DummyInputMethod : public InputMethod { void RemoveObserver(InputMethodObserver* observer) override; InputMethodKeyboardController* GetInputMethodKeyboardController() override; - const std::vector<std::unique_ptr<KeyEvent>>& GetKeyEventsForTesting() - override; - private: - std::vector<std::unique_ptr<KeyEvent>> key_events_for_testing_; DISALLOW_COPY_AND_ASSIGN(DummyInputMethod); }; diff --git a/chromium/ui/base/ime/dummy_text_input_client.cc b/chromium/ui/base/ime/dummy_text_input_client.cc index 2ed42e851b2..a286b663259 100644 --- a/chromium/ui/base/ime/dummy_text_input_client.cc +++ b/chromium/ui/base/ime/dummy_text_input_client.cc @@ -152,6 +152,14 @@ bool DummyTextInputClient::SetCompositionFromExistingText( } #endif +#if defined(OS_CHROMEOS) +bool DummyTextInputClient::SetAutocorrectRange( + const base::string16& autocorrect_text, + const gfx::Range& range) { + return false; +} +#endif + #if defined(OS_WIN) void DummyTextInputClient::GetActiveTextInputControlLayoutBounds( base::Optional<gfx::Rect>* control_bounds, diff --git a/chromium/ui/base/ime/dummy_text_input_client.h b/chromium/ui/base/ime/dummy_text_input_client.h index e145feda8f6..af8f0ad48fc 100644 --- a/chromium/ui/base/ime/dummy_text_input_client.h +++ b/chromium/ui/base/ime/dummy_text_input_client.h @@ -62,6 +62,12 @@ class DummyTextInputClient : public TextInputClient { const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) override; #endif +#if defined(OS_CHROMEOS) + // Set the autocorrect range + bool SetAutocorrectRange(const base::string16& autocorrect_text, + const gfx::Range& range) override; +#endif + #if defined(OS_WIN) void GetActiveTextInputControlLayoutBounds( base::Optional<gfx::Rect>* control_bounds, diff --git a/chromium/ui/base/ime/fuchsia/input_method_fuchsia.cc b/chromium/ui/base/ime/fuchsia/input_method_fuchsia.cc index 2d205c8d182..9959fa3d031 100644 --- a/chromium/ui/base/ime/fuchsia/input_method_fuchsia.cc +++ b/chromium/ui/base/ime/fuchsia/input_method_fuchsia.cc @@ -9,7 +9,7 @@ #include <memory> #include <utility> -#include "base/fuchsia/default_context.h" +#include "base/fuchsia/process_context.h" #include "ui/base/ime/text_input_client.h" #include "ui/events/base_event_utils.h" #include "ui/events/keycodes/dom/dom_code.h" @@ -22,7 +22,7 @@ InputMethodFuchsia::InputMethodFuchsia(internal::InputMethodDelegate* delegate, : InputMethodBase(delegate), event_converter_(this), ime_client_binding_(this), - ime_service_(base::fuchsia::ComponentContextForCurrentProcess() + ime_service_(base::ComponentContextForProcess() ->svc() ->Connect<fuchsia::ui::input::ImeService>()), virtual_keyboard_controller_(ime_service_.get()) {} diff --git a/chromium/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.cc b/chromium/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.cc index c284253ad9b..6a6271b471e 100644 --- a/chromium/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.cc +++ b/chromium/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.cc @@ -7,9 +7,11 @@ #include <lib/sys/cpp/component_context.h> #include <utility> +#include "base/check.h" #include "base/fuchsia/default_context.h" #include "base/fuchsia/fuchsia_logging.h" -#include "base/logging.h" +#include "base/fuchsia/process_context.h" +#include "base/notreached.h" namespace ui { @@ -17,7 +19,7 @@ InputMethodKeyboardControllerFuchsia::InputMethodKeyboardControllerFuchsia( fuchsia::ui::input::ImeService* ime_service) : ime_service_(ime_service), ime_visibility_( - base::fuchsia::ComponentContextForCurrentProcess() + base::ComponentContextForProcess() ->svc() ->Connect<fuchsia::ui::input::ImeVisibilityService>()) { DCHECK(ime_service_); diff --git a/chromium/ui/base/ime/ime_assistive_window_handler_interface.h b/chromium/ui/base/ime/ime_assistive_window_handler_interface.h index 8807731e9a0..d400f291dff 100644 --- a/chromium/ui/base/ime/ime_assistive_window_handler_interface.h +++ b/chromium/ui/base/ime/ime_assistive_window_handler_interface.h @@ -14,6 +14,13 @@ namespace gfx { class Rect; } // namespace gfx +namespace ui { +namespace ime { +struct AssistiveWindowButton; +struct SuggestionDetails; +} // namespace ime +} // namespace ui + namespace chromeos { struct AssistiveWindowProperties; @@ -27,9 +34,19 @@ class COMPONENT_EXPORT(UI_BASE_IME) IMEAssistiveWindowHandlerInterface { virtual void SetAssistiveWindowProperties( const AssistiveWindowProperties& window) {} - virtual void ShowSuggestion(const base::string16& text, - const size_t confirmed_length, - const bool show_tab) {} + virtual void ShowSuggestion(const ui::ime::SuggestionDetails& details) {} + + virtual void ShowMultipleSuggestions( + const std::vector<base::string16>& suggestions) {} + + // Highlights or unhighlights a given assistive button based on the given + // parameters. + virtual void SetButtonHighlighted( + const ui::ime::AssistiveWindowButton& button, + bool highlighted) {} + + virtual void AcceptSuggestion(const base::string16& suggestion) {} + virtual void HideSuggestion() {} // Called to get the current suggestion text. diff --git a/chromium/ui/base/ime/ime_bridge.cc b/chromium/ui/base/ime/ime_bridge.cc deleted file mode 100644 index 5e44712f9a0..00000000000 --- a/chromium/ui/base/ime/ime_bridge.cc +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2014 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 "ui/base/ime/ime_bridge.h" - -#include <map> - -#include "base/macros.h" -#include "base/memory/singleton.h" -#include "base/observer_list.h" -#include "build/build_config.h" - -namespace ui { - -static IMEBridge* g_ime_bridge = nullptr; - -// An implementation of IMEBridge. -class IMEBridgeImpl : public IMEBridge { - public: - IMEBridgeImpl() - : current_input_context_(ui::TEXT_INPUT_TYPE_NONE, - ui::TEXT_INPUT_MODE_DEFAULT, - 0, - ui::TextInputClient::FOCUS_REASON_NONE, - false /* should_do_learning */) {} - - ~IMEBridgeImpl() override {} - - // IMEBridge override. - IMEInputContextHandlerInterface* GetInputContextHandler() const override { - return input_context_handler_; - } - - // IMEBridge override. - void SetInputContextHandler( - IMEInputContextHandlerInterface* handler) override { - input_context_handler_ = handler; - for (auto& observer : observers_) - observer.OnInputContextHandlerChanged(); - } - - // IMEBridge override. - void SetCurrentEngineHandler(IMEEngineHandlerInterface* handler) override { - engine_handler_ = handler; - } - - // IMEBridge override. - IMEEngineHandlerInterface* GetCurrentEngineHandler() const override { - return engine_handler_; - } - - // IMEBridge override. - void SetCurrentInputContext( - const IMEEngineHandlerInterface::InputContext& input_context) override { - current_input_context_ = input_context; - } - - // IMEBridge override. - const IMEEngineHandlerInterface::InputContext& GetCurrentInputContext() - const override { - return current_input_context_; - } - - // IMEBridge override. - void AddObserver(ui::IMEBridgeObserver* observer) override { - observers_.AddObserver(observer); - } - - // IMEBridge override. - void RemoveObserver(ui::IMEBridgeObserver* observer) override { - observers_.RemoveObserver(observer); - } - - // IMEBridge override. - void MaybeSwitchEngine() override { - for (auto& observer : observers_) - observer.OnRequestSwitchEngine(); - } - -#if defined(OS_CHROMEOS) - // IMEBridge override. - void SetCandidateWindowHandler( - chromeos::IMECandidateWindowHandlerInterface* handler) override { - candidate_window_handler_ = handler; - } - - // IMEBridge override. - chromeos::IMECandidateWindowHandlerInterface* GetCandidateWindowHandler() - const override { - return candidate_window_handler_; - } - - // IMEBridge override. - void SetAssistiveWindowHandler( - chromeos::IMEAssistiveWindowHandlerInterface* handler) override { - assistive_window_handler_ = handler; - } - - // IMEBridge override. - chromeos::IMEAssistiveWindowHandlerInterface* GetAssistiveWindowHandler() - const override { - return assistive_window_handler_; - } -#endif - - private: - IMEInputContextHandlerInterface* input_context_handler_ = nullptr; - IMEEngineHandlerInterface* engine_handler_ = nullptr; - base::ObserverList<IMEBridgeObserver> observers_; - IMEEngineHandlerInterface::InputContext current_input_context_; - -#if defined(OS_CHROMEOS) - chromeos::IMECandidateWindowHandlerInterface* candidate_window_handler_ = - nullptr; - chromeos::IMEAssistiveWindowHandlerInterface* assistive_window_handler_ = - nullptr; -#endif - - DISALLOW_COPY_AND_ASSIGN(IMEBridgeImpl); -}; - -/////////////////////////////////////////////////////////////////////////////// -// IMEBridge -IMEBridge::IMEBridge() {} - -IMEBridge::~IMEBridge() {} - -// static. -void IMEBridge::Initialize() { - if (!g_ime_bridge) - g_ime_bridge = new IMEBridgeImpl(); -} - -// static. -void IMEBridge::Shutdown() { - delete g_ime_bridge; - g_ime_bridge = nullptr; -} - -// static. -IMEBridge* IMEBridge::Get() { - return g_ime_bridge; -} - -} // namespace ui diff --git a/chromium/ui/base/ime/ime_bridge.h b/chromium/ui/base/ime/ime_bridge.h deleted file mode 100644 index 9fade0b1944..00000000000 --- a/chromium/ui/base/ime/ime_bridge.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2014 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 UI_BASE_IME_IME_BRIDGE_H_ -#define UI_BASE_IME_IME_BRIDGE_H_ - -#include "base/component_export.h" -#include "base/macros.h" -#include "build/build_config.h" -#include "ui/base/ime/ime_bridge_observer.h" -#include "ui/base/ime/ime_engine_handler_interface.h" -#include "ui/base/ime/ime_input_context_handler_interface.h" - -#if defined(OS_CHROMEOS) -#include "ui/base/ime/ime_assistive_window_handler_interface.h" -#include "ui/base/ime/ime_candidate_window_handler_interface.h" - -namespace chromeos { -class IMECandidateWindowHandlerInterface; -class IMEAssistiveWindowHandlerInterface; -} -#endif - -namespace ui { - -// IMEBridge provides access of each IME related handler. This class -// is used for IME implementation. -class COMPONENT_EXPORT(UI_BASE_IME) IMEBridge { - public: - virtual ~IMEBridge(); - - // Allocates the global instance. Must be called before any calls to Get(). - static void Initialize(); - - // Releases the global instance. - static void Shutdown(); - - // Returns IMEBridge global instance. Initialize() must be called first. - static IMEBridge* Get(); - - // Returns current InputContextHandler. This function returns NULL if input - // context is not ready to use. - virtual IMEInputContextHandlerInterface* GetInputContextHandler() const = 0; - - // Updates current InputContextHandler. If there is no active input context, - // pass NULL for |handler|. Caller must release |handler|. - virtual void SetInputContextHandler( - IMEInputContextHandlerInterface* handler) = 0; - - // Updates current EngineHandler. If there is no active engine service, pass - // NULL for |handler|. Caller must release |handler|. - virtual void SetCurrentEngineHandler(IMEEngineHandlerInterface* handler) = 0; - - // Returns current EngineHandler. This function returns NULL if current engine - // is not ready to use. - virtual IMEEngineHandlerInterface* GetCurrentEngineHandler() const = 0; - - // Updates the current input context. - // This is called from InputMethodChromeOS. - virtual void SetCurrentInputContext( - const IMEEngineHandlerInterface::InputContext& input_context) = 0; - - // Returns the current input context. - // This is called from InputMethodEngine. - virtual const IMEEngineHandlerInterface::InputContext& - GetCurrentInputContext() const = 0; - - // Add or remove observers of events such as switching engines, etc. - virtual void AddObserver(ui::IMEBridgeObserver* observer) = 0; - virtual void RemoveObserver(ui::IMEBridgeObserver* observer) = 0; - - // Switches the engine handler upon top level window focus change. - virtual void MaybeSwitchEngine() = 0; - -#if defined(OS_CHROMEOS) - // Returns current CandidateWindowHandler. This function returns NULL if - // current candidate window is not ready to use. - virtual chromeos::IMECandidateWindowHandlerInterface* - GetCandidateWindowHandler() const = 0; - - // Updates current CandidatWindowHandler. If there is no active candidate - // window service, pass NULL for |handler|. Caller must release |handler|. - virtual void SetCandidateWindowHandler( - chromeos::IMECandidateWindowHandlerInterface* handler) = 0; - - virtual chromeos::IMEAssistiveWindowHandlerInterface* - GetAssistiveWindowHandler() const = 0; - virtual void SetAssistiveWindowHandler( - chromeos::IMEAssistiveWindowHandlerInterface* handler) = 0; -#endif - - protected: - IMEBridge(); - - private: - DISALLOW_COPY_AND_ASSIGN(IMEBridge); -}; - -} // namespace ui - -#endif // UI_BASE_IME_IME_BRIDGE_H_ diff --git a/chromium/ui/base/ime/ime_engine_handler_interface.h b/chromium/ui/base/ime/ime_engine_handler_interface.h index 4eb49c6ecf0..4895587e81c 100644 --- a/chromium/ui/base/ime/ime_engine_handler_interface.h +++ b/chromium/ui/base/ime/ime_engine_handler_interface.h @@ -24,8 +24,15 @@ class Rect; namespace ui { +class InputMethodKeyboardController; class KeyEvent; +#if defined(OS_CHROMEOS) +namespace ime { +struct AssistiveWindowButton; +} // namespace ime +#endif // defined(OS_CHROMEOS) + // A interface to handle the engine handler method call. class COMPONENT_EXPORT(UI_BASE_IME) IMEEngineHandlerInterface { public: @@ -114,6 +121,10 @@ class COMPONENT_EXPORT(UI_BASE_IME) IMEEngineHandlerInterface { // Called when the composition bounds changed. virtual void SetCompositionBounds(const std::vector<gfx::Rect>& bounds) = 0; + // Gets the implementation of the keyboard controller. + virtual ui::InputMethodKeyboardController* GetInputMethodKeyboardController() + const = 0; + #if defined(OS_CHROMEOS) // Called when a property is activated or changed. @@ -123,6 +134,10 @@ class COMPONENT_EXPORT(UI_BASE_IME) IMEEngineHandlerInterface { // based candidate index in lookup table. virtual void CandidateClicked(uint32_t index) = 0; + // Called when assistive window is clicked. + virtual void AssistiveWindowButtonClicked( + const ui::ime::AssistiveWindowButton& button) {} + // Sets the mirroring/casting enable states. virtual void SetMirroringEnabled(bool mirroring_enabled) = 0; virtual void SetCastingEnabled(bool casting_enabled) = 0; diff --git a/chromium/ui/base/ime/ime_input_context_handler_interface.h b/chromium/ui/base/ime/ime_input_context_handler_interface.h index 5387c7b7b0e..46fd1fef8ea 100644 --- a/chromium/ui/base/ime/ime_input_context_handler_interface.h +++ b/chromium/ui/base/ime/ime_input_context_handler_interface.h @@ -33,6 +33,11 @@ class COMPONENT_EXPORT(UI_BASE_IME) IMEInputContextHandlerInterface { uint32_t after, const std::vector<ui::ImeTextSpan>& text_spans) = 0; + // Set the autocorrect range with text. + virtual bool SetAutocorrectRange(const base::string16& autocorrect_text, + uint32_t start, + uint32_t end) = 0; + // Called when the engine changes the selection range. // Returns true if the operation was successful. virtual bool SetSelectionRange(uint32_t start, uint32_t end) = 0; diff --git a/chromium/ui/base/ime/ime_text_span.h b/chromium/ui/base/ime/ime_text_span.h index c76734e2e4f..62bdfb8cbac 100644 --- a/chromium/ui/base/ime/ime_text_span.h +++ b/chromium/ui/base/ime/ime_text_span.h @@ -15,9 +15,6 @@ namespace ui { -// Intentionally keep sync with blink::WebImeTextSpan defined in: -// third_party/WebKit/public/web/WebImeTextSpan.h - struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) ImeTextSpan { enum class Type { // Creates a composition marker. @@ -29,6 +26,8 @@ struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) ImeTextSpan { // replacement, and will be ignored if added to an element with spell // checking disabled. kMisspellingSuggestion, + // Creates an autocorrect marker that isn't cleared by itself. + kAutocorrect, }; enum class Thickness { @@ -72,6 +71,7 @@ struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) ImeTextSpan { rhs.suggestion_highlight_color) && (this->remove_on_finish_composing == rhs.remove_on_finish_composing) && + (this->interim_char_selection == rhs.interim_char_selection) && (this->suggestions == rhs.suggestions); } @@ -87,6 +87,7 @@ struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) ImeTextSpan { SkColor background_color; SkColor suggestion_highlight_color; bool remove_on_finish_composing = false; + bool interim_char_selection = false; std::vector<std::string> suggestions; }; diff --git a/chromium/ui/base/ime/init/BUILD.gn b/chromium/ui/base/ime/init/BUILD.gn index 0aad80f4551..26e7a60f901 100644 --- a/chromium/ui/base/ime/init/BUILD.gn +++ b/chromium/ui/base/ime/init/BUILD.gn @@ -31,6 +31,9 @@ jumbo_component("init") { if (is_mac) { deps += [ "//ui/base/ime/mac" ] } + if (is_chromeos) { + deps += [ "//ui/base/ime/chromeos" ] + } if (is_linux && !is_chromeos) { deps += [ "//ui/base/ime/linux" ] } diff --git a/chromium/ui/base/ime/init/input_method_factory.cc b/chromium/ui/base/ime/init/input_method_factory.cc index 5e98636a36c..d923c6b2331 100644 --- a/chromium/ui/base/ime/init/input_method_factory.cc +++ b/chromium/ui/base/ime/init/input_method_factory.cc @@ -5,6 +5,7 @@ #include "ui/base/ime/init/input_method_factory.h" #include "base/command_line.h" +#include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/win/windows_version.h" #include "build/build_config.h" @@ -17,10 +18,15 @@ #include "ui/base/ime/win/input_method_win_tsf.h" #elif defined(OS_MACOSX) #include "ui/base/ime/mac/input_method_mac.h" -#elif defined(USE_X11) -#include "ui/base/ime/linux/input_method_auralinux.h" -#elif defined(USE_OZONE) +#elif defined(USE_X11) || defined(USE_OZONE) +#if defined(USE_X11) +// TODO(crbug.com/1085700): Remove nogncheck when we can build both Ozone +// Wayland and X11 on Linux codesearch-gen bots. +#include "ui/base/ime/linux/input_method_auralinux.h" // nogncheck +#endif // defined(USE_X11) +#if defined(USE_OZONE) #include "ui/ozone/public/ozone_platform.h" +#endif // defined(USE_OZONE) #else #include "ui/base/ime/input_method_minimal.h" #endif @@ -63,10 +69,18 @@ std::unique_ptr<InputMethod> CreateInputMethod( return std::make_unique<InputMethodWinImm32>(delegate, widget); #elif defined(OS_MACOSX) return std::make_unique<InputMethodMac>(delegate); -#elif defined(USE_X11) - return std::make_unique<InputMethodAuraLinux>(delegate); -#elif defined(USE_OZONE) - return ui::OzonePlatform::GetInstance()->CreateInputMethod(delegate, widget); +#elif defined(USE_X11) || defined(USE_OZONE) +#if defined(USE_OZONE) + if (features::IsUsingOzonePlatform()) { + return ui::OzonePlatform::GetInstance()->CreateInputMethod(delegate, + widget); + } +#endif // defined(USE_OZONE) +#if defined(USE_X11) + return std::make_unique<ui::InputMethodAuraLinux>(delegate); +#endif // defined(USE_X11) + NOTREACHED(); + return nullptr; #else return std::make_unique<InputMethodMinimal>(delegate); #endif diff --git a/chromium/ui/base/ime/init/input_method_initializer.cc b/chromium/ui/base/ime/init/input_method_initializer.cc index 1a453109dbc..1bfc48a8005 100644 --- a/chromium/ui/base/ime/init/input_method_initializer.cc +++ b/chromium/ui/base/ime/init/input_method_initializer.cc @@ -9,10 +9,12 @@ #include "build/build_config.h" #if defined(OS_CHROMEOS) -#include "ui/base/ime/ime_bridge.h" +#include "ui/base/ime/chromeos/ime_bridge.h" #elif defined(USE_AURA) && defined(OS_LINUX) #include "base/check.h" -#include "ui/base/ime/linux/fake_input_method_context_factory.h" +// TODO(crbug.com/1085700): Remove nogncheck when we can build both Ozone +// Wayland and X11 on Linux codesearch-gen bots. +#include "ui/base/ime/linux/fake_input_method_context_factory.h" // nogncheck #elif defined(OS_WIN) #include "ui/base/ime/init/input_method_factory.h" #include "ui/base/ime/win/tsf_bridge.h" diff --git a/chromium/ui/base/ime/input_method.h b/chromium/ui/base/ime/input_method.h index b400ece46ac..9ead7fa666e 100644 --- a/chromium/ui/base/ime/input_method.h +++ b/chromium/ui/base/ime/input_method.h @@ -18,10 +18,6 @@ #include "ui/events/platform_event.h" #include "ui/gfx/geometry/rect.h" -namespace extensions { -class InputImeApiTest; -} // namespace extensions - namespace ui { namespace internal { @@ -57,8 +53,6 @@ class TextInputClient; // ui::InputMethod and owns it. class InputMethod { public: - InputMethod() : track_key_events_for_testing_(false) {} - #if defined(OS_WIN) typedef LRESULT NativeEventResult; #else @@ -174,16 +168,6 @@ class InputMethod { // Return the keyboard controller; used only on Windows. virtual InputMethodKeyboardController* GetInputMethodKeyboardController() = 0; - - protected: - friend class extensions::InputImeApiTest; - - // Gets the tracked key events of using input.ime.sendKeyEvents API. - virtual const std::vector<std::unique_ptr<ui::KeyEvent>>& - GetKeyEventsForTesting() = 0; - - // Whether the key events will be tracked. Only used for testing. - bool track_key_events_for_testing_; }; } // namespace ui diff --git a/chromium/ui/base/ime/input_method_base.cc b/chromium/ui/base/ime/input_method_base.cc index 6051072ddb7..b5f26b6bf9d 100644 --- a/chromium/ui/base/ime/input_method_base.cc +++ b/chromium/ui/base/ime/input_method_base.cc @@ -9,7 +9,6 @@ #include "base/check.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" -#include "ui/base/ime/ime_bridge.h" #include "ui/base/ime/input_method_delegate.h" #include "ui/base/ime/input_method_keyboard_controller_stub.h" #include "ui/base/ime/input_method_observer.h" @@ -18,11 +17,6 @@ namespace ui { -ui::IMEEngineHandlerInterface* InputMethodBase::GetEngine() { - auto* bridge = ui::IMEBridge::Get(); - return bridge ? bridge->GetCurrentEngineHandler() : nullptr; -} - InputMethodBase::InputMethodBase(internal::InputMethodDelegate* delegate) : InputMethodBase(delegate, nullptr) {} @@ -35,9 +29,6 @@ InputMethodBase::InputMethodBase( InputMethodBase::~InputMethodBase() { for (InputMethodObserver& observer : observer_list_) observer.OnInputMethodDestroyed(this); - if (ui::IMEBridge::Get() && - ui::IMEBridge::Get()->GetInputContextHandler() == this) - ui::IMEBridge::Get()->SetInputContextHandler(nullptr); } void InputMethodBase::SetDelegate(internal::InputMethodDelegate* delegate) { @@ -45,17 +36,9 @@ void InputMethodBase::SetDelegate(internal::InputMethodDelegate* delegate) { } void InputMethodBase::OnFocus() { - ui::IMEBridge* bridge = ui::IMEBridge::Get(); - if (bridge) { - bridge->SetInputContextHandler(this); - bridge->MaybeSwitchEngine(); - } } void InputMethodBase::OnBlur() { - if (ui::IMEBridge::Get() && - ui::IMEBridge::Get()->GetInputContextHandler() == this) - ui::IMEBridge::Get()->SetInputContextHandler(nullptr); } #if defined(OS_WIN) @@ -251,6 +234,13 @@ bool InputMethodBase::SetCompositionRange( return false; } +bool InputMethodBase::SetAutocorrectRange( + const base::string16& autocorrect_text, + uint32_t start, + uint32_t end) { + return false; +} + bool InputMethodBase::SetSelectionRange(uint32_t start, uint32_t end) { return false; } @@ -275,9 +265,6 @@ SurroundingTextInfo InputMethodBase::GetSurroundingTextInfo() { } void InputMethodBase::SendKeyEvent(KeyEvent* event) { - if (track_key_events_for_testing_) { - key_events_for_testing_.push_back(std::make_unique<KeyEvent>(*event)); - } ui::EventDispatchDetails details = DispatchKeyEvent(event); DCHECK(!details.dispatcher_destroyed); } @@ -298,9 +285,4 @@ bool InputMethodBase::HasCompositionText() { return client && client->HasCompositionText(); } -const std::vector<std::unique_ptr<ui::KeyEvent>>& -InputMethodBase::GetKeyEventsForTesting() { - return key_events_for_testing_; -} - } // namespace ui diff --git a/chromium/ui/base/ime/input_method_base.h b/chromium/ui/base/ime/input_method_base.h index 7d182e01975..e87cdcab71e 100644 --- a/chromium/ui/base/ime/input_method_base.h +++ b/chromium/ui/base/ime/input_method_base.h @@ -92,6 +92,9 @@ class COMPONENT_EXPORT(UI_BASE_IME) InputMethodBase uint32_t before, uint32_t after, const std::vector<ui::ImeTextSpan>& text_spans) override; + bool SetAutocorrectRange(const base::string16& autocorrect_text, + uint32_t start, + uint32_t end) override; bool SetSelectionRange(uint32_t start, uint32_t end) override; #endif @@ -134,23 +137,15 @@ class COMPONENT_EXPORT(UI_BASE_IME) InputMethodBase internal::InputMethodDelegate* delegate() const { return delegate_; } - static IMEEngineHandlerInterface* GetEngine(); - private: internal::InputMethodDelegate* delegate_; - // InputMethod: - const std::vector<std::unique_ptr<ui::KeyEvent>>& GetKeyEventsForTesting() - override; - void SetFocusedTextInputClientInternal(TextInputClient* client); TextInputClient* text_input_client_ = nullptr; base::ObserverList<InputMethodObserver>::Unchecked observer_list_; - std::vector<std::unique_ptr<ui::KeyEvent>> key_events_for_testing_; - // Screen bounds of a on-screen keyboard. gfx::Rect keyboard_bounds_; diff --git a/chromium/ui/base/ime/linux/BUILD.gn b/chromium/ui/base/ime/linux/BUILD.gn index 01c9b24e6a7..dbef616118c 100644 --- a/chromium/ui/base/ime/linux/BUILD.gn +++ b/chromium/ui/base/ime/linux/BUILD.gn @@ -5,7 +5,14 @@ import("//build/config/jumbo.gni") import("//build/config/linux/pangocairo/pangocairo.gni") -assert(is_linux && !is_chromeos) +# Allows base/ime/linux to be built if it's just for making kythe annotations. +# This is used to generate cross references in codesearch. References are +# generated by building the ozone wayland backend on ChromiumOS, which +# normally we would not want to compile base/ime/linux for. We can't build +# both ozone and x11 on Linux yet, but when we can we should remove this. +# TODO(crbug.com/1085700): Remove || enable_kythe_annotations here. +import("//build/toolchain/kythe.gni") +assert((is_linux && !is_chromeos) || enable_kythe_annotations) jumbo_component("linux") { output_name = "ui_base_ime_linux" diff --git a/chromium/ui/base/ime/linux/input_method_auralinux.cc b/chromium/ui/base/ime/linux/input_method_auralinux.cc index 3f3663c3a51..de49a5b15f1 100644 --- a/chromium/ui/base/ime/linux/input_method_auralinux.cc +++ b/chromium/ui/base/ime/linux/input_method_auralinux.cc @@ -8,8 +8,6 @@ #include "base/bind.h" #include "base/environment.h" #include "ui/base/ime/constants.h" -#include "ui/base/ime/ime_bridge.h" -#include "ui/base/ime/ime_engine_handler_interface.h" #include "ui/base/ime/linux/linux_input_method_context_factory.h" #include "ui/base/ime/text_input_client.h" #include "ui/events/event.h" @@ -88,42 +86,9 @@ ui::EventDispatchDetails InputMethodAuraLinux::DispatchKeyEvent( } } - // If there's an active IME extension is listening to the key event, and the - // current text input client is not password input client, the key event - // should be dispatched to the extension engine in the two conditions: - // 1) |filtered| == false: the ET_KEY_PRESSED event of non-character key, - // or the ET_KEY_RELEASED event of all key. - // 2) |filtered| == true && NeedInsertChar(): the ET_KEY_PRESSED event of - // character key. - if (text_input_type_ != TEXT_INPUT_TYPE_PASSWORD && GetEngine() && - (!filtered || NeedInsertChar())) { - ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback = - base::BindOnce(&InputMethodAuraLinux::ProcessKeyEventByEngineDone, - weak_ptr_factory_.GetWeakPtr(), - base::Owned(new ui::KeyEvent(*event)), filtered, - composition_changed_, - base::Owned(new ui::CompositionText(composition_)), - base::Owned(new base::string16(result_text_))); - GetEngine()->ProcessKeyEvent(*event, std::move(callback)); - return ui::EventDispatchDetails(); - } - return ProcessKeyEventDone(event, filtered, false); } -void InputMethodAuraLinux::ProcessKeyEventByEngineDone( - ui::KeyEvent* event, - bool filtered, - bool composition_changed, - ui::CompositionText* composition, - base::string16* result_text, - bool is_handled) { - composition_changed_ = composition_changed; - composition_ = *composition; - result_text_ = *result_text; - ignore_result(ProcessKeyEventDone(event, filtered, is_handled)); -} - ui::EventDispatchDetails InputMethodAuraLinux::ProcessKeyEventDone( ui::KeyEvent* event, bool filtered, @@ -248,22 +213,6 @@ void InputMethodAuraLinux::UpdateContextFocusState() { context_simple_->Focus(); else context_simple_->Blur(); - - if (!ui::IMEBridge::Get()) // IMEBridge could be null for tests. - return; - - ui::IMEEngineHandlerInterface::InputContext context( - GetTextInputType(), GetTextInputMode(), GetTextInputFlags(), - ui::TextInputClient::FOCUS_REASON_OTHER, GetClientShouldDoLearning()); - ui::IMEBridge::Get()->SetCurrentInputContext(context); - - ui::IMEEngineHandlerInterface* engine = GetEngine(); - if (engine) { - if (old_text_input_type != TEXT_INPUT_TYPE_NONE) - engine->FocusOut(); - if (text_input_type_ != TEXT_INPUT_TYPE_NONE) - engine->FocusIn(context); - } } void InputMethodAuraLinux::OnTextInputTypeChanged( @@ -286,19 +235,12 @@ void InputMethodAuraLinux::OnCaretBoundsChanged(const TextInputClient* client) { client->GetEditableSelectionRange(&selection_range)) { context_->SetSurroundingText(text, selection_range); } - - if (!IsTextInputTypeNone() && text_input_type_ != TEXT_INPUT_TYPE_PASSWORD && - GetEngine()) - GetEngine()->SetCompositionBounds(GetCompositionBounds(client)); } void InputMethodAuraLinux::CancelComposition(const TextInputClient* client) { if (!IsTextInputClientFocused(client)) return; - if (GetEngine()) - GetEngine()->Reset(); - ResetContext(); } @@ -457,8 +399,6 @@ void InputMethodAuraLinux::ConfirmCompositionText(bool reset_engine, NOTIMPLEMENTED_LOG_ONCE(); } InputMethodBase::ConfirmCompositionText(reset_engine, keep_selection); - if (reset_engine && GetEngine()) - GetEngine()->Reset(); ResetContext(); } diff --git a/chromium/ui/base/ime/linux/input_method_auralinux.h b/chromium/ui/base/ime/linux/input_method_auralinux.h index 294979dec2d..e560171df5b 100644 --- a/chromium/ui/base/ime/linux/input_method_auralinux.h +++ b/chromium/ui/base/ime/linux/input_method_auralinux.h @@ -65,18 +65,6 @@ class COMPONENT_EXPORT(UI_BASE_IME_LINUX) InputMethodAuraLinux bool is_handled) WARN_UNUSED_RESULT; - // Callback function for IMEEngineHandlerInterface::ProcessKeyEvent(). - // It recovers the context when the event is being passed to the extension and - // call ProcessKeyEventDone() for the following processing. This is necessary - // as this method is async. The environment may be changed by other generated - // key events by the time the callback is run. - void ProcessKeyEventByEngineDone(ui::KeyEvent* event, - bool filtered, - bool composition_changed, - ui::CompositionText* composition, - base::string16* result_text, - bool is_handled); - std::unique_ptr<LinuxInputMethodContext> context_; std::unique_ptr<LinuxInputMethodContext> context_simple_; diff --git a/chromium/ui/base/ime/linux/input_method_auralinux_unittest.cc b/chromium/ui/base/ime/linux/input_method_auralinux_unittest.cc index 02819b93d51..c7d29003977 100644 --- a/chromium/ui/base/ime/linux/input_method_auralinux_unittest.cc +++ b/chromium/ui/base/ime/linux/input_method_auralinux_unittest.cc @@ -271,19 +271,19 @@ class TextInputClientForTesting : public DummyTextInputClient { class InputMethodAuraLinuxTest : public testing::Test { protected: InputMethodAuraLinuxTest() - : factory_(NULL), - input_method_auralinux_(NULL), - delegate_(NULL), - context_(NULL), - context_simple_(NULL) { + : factory_(nullptr), + input_method_auralinux_(nullptr), + delegate_(nullptr), + context_(nullptr), + context_simple_(nullptr) { factory_ = new LinuxInputMethodContextFactoryForTesting(); LinuxInputMethodContextFactory::SetInstance(factory_); test_result_ = TestResult::GetInstance(); } ~InputMethodAuraLinuxTest() override { delete factory_; - factory_ = NULL; - test_result_ = NULL; + factory_ = nullptr; + test_result_ = nullptr; } void SetUp() override { @@ -303,13 +303,13 @@ class InputMethodAuraLinuxTest : public testing::Test { context_simple_->SetSyncMode(false); context_simple_->SetEatKey(false); - context_ = NULL; - context_simple_ = NULL; + context_ = nullptr; + context_simple_ = nullptr; delete input_method_auralinux_; - input_method_auralinux_ = NULL; + input_method_auralinux_ = nullptr; delete delegate_; - delegate_ = NULL; + delegate_ = nullptr; } LinuxInputMethodContextFactoryForTesting* factory_; diff --git a/chromium/ui/base/ime/mock_ime_input_context_handler.cc b/chromium/ui/base/ime/mock_ime_input_context_handler.cc index f6d7cf6decb..f2ba25fbeb6 100644 --- a/chromium/ui/base/ime/mock_ime_input_context_handler.cc +++ b/chromium/ui/base/ime/mock_ime_input_context_handler.cc @@ -5,6 +5,7 @@ #include "ui/base/ime/mock_ime_input_context_handler.h" #include "base/logging.h" +#include "base/notreached.h" #include "base/strings/utf_string_conversions.h" #include "ui/base/ime/composition_text.h" #include "ui/base/ime/input_method.h" @@ -16,8 +17,7 @@ MockIMEInputContextHandler::MockIMEInputContextHandler() : commit_text_call_count_(0), set_selection_range_call_count_(0), update_preedit_text_call_count_(0), - delete_surrounding_text_call_count_(0), - last_sent_key_event_(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, 0) {} + delete_surrounding_text_call_count_(0) {} MockIMEInputContextHandler::~MockIMEInputContextHandler() {} @@ -47,6 +47,14 @@ bool MockIMEInputContextHandler::SetCompositionRange( return true; } +bool MockIMEInputContextHandler::SetAutocorrectRange( + const base::string16& autocorrect_text, + uint32_t start, + uint32_t end) { + // TODO(crbug.com/1091088): Implement function. + return false; +} + bool MockIMEInputContextHandler::SetSelectionRange(uint32_t start, uint32_t end) { ++set_selection_range_call_count_; @@ -72,11 +80,11 @@ void MockIMEInputContextHandler::Reset() { update_preedit_text_call_count_ = 0; delete_surrounding_text_call_count_ = 0; last_commit_text_.clear(); - last_sent_key_event_ = ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, 0); + sent_key_events_.clear(); } void MockIMEInputContextHandler::SendKeyEvent(KeyEvent* event) { - last_sent_key_event_ = *event; + sent_key_events_.emplace_back(*event); } InputMethod* MockIMEInputContextHandler::GetInputMethod() { diff --git a/chromium/ui/base/ime/mock_ime_input_context_handler.h b/chromium/ui/base/ime/mock_ime_input_context_handler.h index e13c67f0b9d..6890e6b538a 100644 --- a/chromium/ui/base/ime/mock_ime_input_context_handler.h +++ b/chromium/ui/base/ime/mock_ime_input_context_handler.h @@ -44,6 +44,10 @@ class COMPONENT_EXPORT(UI_BASE_IME) MockIMEInputContextHandler uint32_t after, const std::vector<ui::ImeTextSpan>& text_spans) override; + bool SetAutocorrectRange(const base::string16& autocorrect_text, + uint32_t start, + uint32_t end) override; + bool SetSelectionRange(uint32_t start, uint32_t end) override; #endif @@ -66,6 +70,8 @@ class COMPONENT_EXPORT(UI_BASE_IME) MockIMEInputContextHandler return delete_surrounding_text_call_count_; } + int send_key_event_call_count() const { return sent_key_events_.size(); } + const std::string& last_commit_text() const { return last_commit_text_; } const UpdateCompositionTextArg& last_update_composition_arg() const { @@ -76,8 +82,8 @@ class COMPONENT_EXPORT(UI_BASE_IME) MockIMEInputContextHandler return last_delete_surrounding_text_arg_; } - const ui::KeyEvent& last_sent_key_event() const { - return last_sent_key_event_; + const std::vector<ui::KeyEvent>& sent_key_events() const { + return sent_key_events_; } // Resets all call count. @@ -89,7 +95,7 @@ class COMPONENT_EXPORT(UI_BASE_IME) MockIMEInputContextHandler int update_preedit_text_call_count_; int delete_surrounding_text_call_count_; std::string last_commit_text_; - ui::KeyEvent last_sent_key_event_; + std::vector<ui::KeyEvent> sent_key_events_; UpdateCompositionTextArg last_update_composition_arg_; DeleteSurroundingTextArg last_delete_surrounding_text_arg_; }; diff --git a/chromium/ui/base/ime/mock_input_method.cc b/chromium/ui/base/ime/mock_input_method.cc index 17555ca526f..5cd43dd5165 100644 --- a/chromium/ui/base/ime/mock_input_method.cc +++ b/chromium/ui/base/ime/mock_input_method.cc @@ -13,8 +13,7 @@ namespace ui { MockInputMethod::MockInputMethod(internal::InputMethodDelegate* delegate) - : text_input_client_(NULL), delegate_(delegate) { -} + : text_input_client_(nullptr), delegate_(delegate) {} MockInputMethod::~MockInputMethod() { for (InputMethodObserver& observer : observer_list_) @@ -35,7 +34,7 @@ void MockInputMethod::SetFocusedTextInputClient(TextInputClient* client) { void MockInputMethod::DetachTextInputClient(TextInputClient* client) { if (text_input_client_ == client) { - text_input_client_ = NULL; + text_input_client_ = nullptr; } } @@ -129,9 +128,4 @@ MockInputMethod::GetInputMethodKeyboardController() { return &keyboard_controller_; } -const std::vector<std::unique_ptr<ui::KeyEvent>>& -MockInputMethod::GetKeyEventsForTesting() { - return key_events_for_testing_; -} - } // namespace ui diff --git a/chromium/ui/base/ime/mock_input_method.h b/chromium/ui/base/ime/mock_input_method.h index 2d72e99a4bc..3cbfa920c9a 100644 --- a/chromium/ui/base/ime/mock_input_method.h +++ b/chromium/ui/base/ime/mock_input_method.h @@ -61,15 +61,11 @@ class COMPONENT_EXPORT(UI_BASE_IME) MockInputMethod : public InputMethod { InputMethodKeyboardController* GetInputMethodKeyboardController() override; private: - // InputMethod: - const std::vector<std::unique_ptr<ui::KeyEvent>>& GetKeyEventsForTesting() - override; TextInputClient* text_input_client_; base::ObserverList<InputMethodObserver>::Unchecked observer_list_; internal::InputMethodDelegate* delegate_; - std::vector<std::unique_ptr<ui::KeyEvent>> key_events_for_testing_; InputMethodKeyboardControllerStub keyboard_controller_; DISALLOW_COPY_AND_ASSIGN(MockInputMethod); diff --git a/chromium/ui/base/ime/mojom/BUILD.gn b/chromium/ui/base/ime/mojom/BUILD.gn index dd96cc53288..c69ea02d7a9 100644 --- a/chromium/ui/base/ime/mojom/BUILD.gn +++ b/chromium/ui/base/ime/mojom/BUILD.gn @@ -4,11 +4,33 @@ import("//mojo/public/tools/bindings/mojom.gni") +component("shared_mojom_traits") { + output_name = "ime_shared_mojom_traits" + defines = [ "IS_IME_SHARED_MOJOM_TRAITS_IMPL" ] + sources = [ + "ime_types_mojom_traits.cc", + "ime_types_mojom_traits.h", + ] + public_deps = [ + ":mojom_shared", + "//ipc:param_traits", + "//ui/base/ime:ime_types", + ] +} + mojom("mojom") { generate_java = true - sources = [ "ime_types.mojom" ] + sources = [ + "ime_types.mojom", + "text_input_state.mojom", + "virtual_keyboard_types.mojom", + ] - public_deps = [ "//mojo/public/mojom/base" ] + public_deps = [ + "//mojo/public/mojom/base", + "//ui/gfx/geometry/mojom", + "//ui/gfx/range/mojom", + ] cpp_typemaps = [ { @@ -26,19 +48,30 @@ mojom("mojom") { cpp = "::ui::ImeTextSpan::UnderlineStyle" }, { + mojom = "ui.mojom.TextInputAction" + cpp = "::ui::TextInputAction" + }, + { + mojom = "ui.mojom.TextInputMode" + cpp = "::ui::TextInputMode" + }, + { mojom = "ui.mojom.TextInputType" cpp = "::ui::TextInputType" }, ] - traits_sources = [ "ime_types_mojom_traits.cc" ] traits_headers = [ "ime_types_mojom_traits.h" ] traits_public_deps = [ - "//ui/base/ime:ime_types", + ":shared_mojom_traits", "//ui/gfx/range", ] }, ] + blink_cpp_typemaps = cpp_typemaps + export_class_attribute_blink = "BLINK_PLATFORM_EXPORT" + export_define_blink = "BLINK_PLATFORM_IMPLEMENTATION=1" + export_header_blink = "third_party/blink/public/platform/web_common.h" } mojom("test_interfaces") { diff --git a/chromium/ui/base/ime/mojom/ime_types.mojom b/chromium/ui/base/ime/mojom/ime_types.mojom index 57b07029fa3..0c04bbfa900 100644 --- a/chromium/ui/base/ime/mojom/ime_types.mojom +++ b/chromium/ui/base/ime/mojom/ime_types.mojom @@ -6,6 +6,29 @@ module ui.mojom; import "mojo/public/mojom/base/string16.mojom"; +enum TextInputMode { + kDefault, + kNone, + kText, + kTel, + kUrl, + kEmail, + kNumeric, + kDecimal, + kSearch, +}; + +enum TextInputAction { + kDefault, + kEnter, + kDone, + kGo, + kNext, + kPrevious, + kSearch, + kSend, +}; + // Text input type which is based on blink::WebTextInputType. enum TextInputType { NONE, @@ -34,6 +57,7 @@ enum ImeTextSpanType { kComposition, kSuggestion, kMisspellingSuggestion, + kAutocorrect, }; // This enum represents the thickness of an underline segment of text, @@ -76,5 +100,6 @@ struct ImeTextSpan { uint32 background_color; uint32 suggestion_highlight_color; bool remove_on_finish_composing; + bool interim_char_selection; array<string> suggestions; }; diff --git a/chromium/ui/base/ime/mojom/ime_types_mojom_traits.cc b/chromium/ui/base/ime/mojom/ime_types_mojom_traits.cc index 694959deddd..e09781c80e8 100644 --- a/chromium/ui/base/ime/mojom/ime_types_mojom_traits.cc +++ b/chromium/ui/base/ime/mojom/ime_types_mojom_traits.cc @@ -6,6 +6,99 @@ namespace mojo { +#define UI_TO_MOJO_ACTION_CASE(name) \ + case ui::TextInputAction::name: \ + return ui::mojom::TextInputAction::name + +// static +ui::mojom::TextInputAction +EnumTraits<ui::mojom::TextInputAction, ui::TextInputAction>::ToMojom( + ui::TextInputAction text_input_action) { + switch (text_input_action) { + UI_TO_MOJO_ACTION_CASE(kDefault); + UI_TO_MOJO_ACTION_CASE(kEnter); + UI_TO_MOJO_ACTION_CASE(kDone); + UI_TO_MOJO_ACTION_CASE(kGo); + UI_TO_MOJO_ACTION_CASE(kNext); + UI_TO_MOJO_ACTION_CASE(kPrevious); + UI_TO_MOJO_ACTION_CASE(kSearch); + UI_TO_MOJO_ACTION_CASE(kSend); + } +} + +#undef UI_TO_MOJO_ACTION_CASE + +#define MOJO_TO_UI_ACTION_CASE(name) \ + case ui::mojom::TextInputAction::name: \ + *out = ui::TextInputAction::name; \ + return true; + +// static +bool EnumTraits<ui::mojom::TextInputAction, ui::TextInputAction>::FromMojom( + ui::mojom::TextInputAction input, + ui::TextInputAction* out) { + switch (input) { + MOJO_TO_UI_ACTION_CASE(kDefault); + MOJO_TO_UI_ACTION_CASE(kEnter); + MOJO_TO_UI_ACTION_CASE(kDone); + MOJO_TO_UI_ACTION_CASE(kGo); + MOJO_TO_UI_ACTION_CASE(kNext); + MOJO_TO_UI_ACTION_CASE(kPrevious); + MOJO_TO_UI_ACTION_CASE(kSearch); + MOJO_TO_UI_ACTION_CASE(kSend); + } + return false; +} + +#undef MOJO_TO_UI_ACTION_CASE + +#define UI_TO_MOJO_MODE_CASE(name, mojo_name) \ + case ui::TextInputMode::TEXT_INPUT_MODE_##name: \ + return ui::mojom::TextInputMode::mojo_name + +// static +ui::mojom::TextInputMode +EnumTraits<ui::mojom::TextInputMode, ui::TextInputMode>::ToMojom( + ui::TextInputMode text_input_mode) { + switch (text_input_mode) { + UI_TO_MOJO_MODE_CASE(DEFAULT, kDefault); + UI_TO_MOJO_MODE_CASE(NONE, kNone); + UI_TO_MOJO_MODE_CASE(TEXT, kText); + UI_TO_MOJO_MODE_CASE(TEL, kTel); + UI_TO_MOJO_MODE_CASE(URL, kUrl); + UI_TO_MOJO_MODE_CASE(EMAIL, kEmail); + UI_TO_MOJO_MODE_CASE(NUMERIC, kNumeric); + UI_TO_MOJO_MODE_CASE(DECIMAL, kDecimal); + UI_TO_MOJO_MODE_CASE(SEARCH, kSearch); + } +} + +#undef UI_TO_MOJO_MODE_CASE + +#define MOJO_TO_UI_MODE_CASE(name, mojo_name) \ + case ui::mojom::TextInputMode::mojo_name: \ + *out = ui::TextInputMode::TEXT_INPUT_MODE_##name; \ + return true; + +// static +bool EnumTraits<ui::mojom::TextInputMode, ui::TextInputMode>::FromMojom( + ui::mojom::TextInputMode input, + ui::TextInputMode* out) { + switch (input) { + MOJO_TO_UI_MODE_CASE(DEFAULT, kDefault); + MOJO_TO_UI_MODE_CASE(NONE, kNone); + MOJO_TO_UI_MODE_CASE(TEXT, kText); + MOJO_TO_UI_MODE_CASE(TEL, kTel); + MOJO_TO_UI_MODE_CASE(URL, kUrl); + MOJO_TO_UI_MODE_CASE(EMAIL, kEmail); + MOJO_TO_UI_MODE_CASE(NUMERIC, kNumeric); + MOJO_TO_UI_MODE_CASE(DECIMAL, kDecimal); + MOJO_TO_UI_MODE_CASE(SEARCH, kSearch); + } +} + +#undef MOJO_TO_UI_MODE_CASE + #define UI_TO_MOJO_TYPE_CASE(name) \ case ui::TEXT_INPUT_TYPE_##name: \ return ui::mojom::TextInputType::name @@ -97,6 +190,7 @@ bool StructTraits<ui::mojom::ImeTextSpanDataView, ui::ImeTextSpan>::Read( out->background_color = data.background_color(); out->suggestion_highlight_color = data.suggestion_highlight_color(); out->remove_on_finish_composing = data.remove_on_finish_composing(); + out->interim_char_selection = data.interim_char_selection(); if (!data.ReadSuggestions(&out->suggestions)) return false; return true; @@ -113,6 +207,8 @@ EnumTraits<ui::mojom::ImeTextSpanType, ui::ImeTextSpan::Type>::ToMojom( return ui::mojom::ImeTextSpanType::kSuggestion; case ui::ImeTextSpan::Type::kMisspellingSuggestion: return ui::mojom::ImeTextSpanType::kMisspellingSuggestion; + case ui::ImeTextSpan::Type::kAutocorrect: + return ui::mojom::ImeTextSpanType::kAutocorrect; } NOTREACHED(); @@ -133,6 +229,9 @@ bool EnumTraits<ui::mojom::ImeTextSpanType, ui::ImeTextSpan::Type>::FromMojom( case ui::mojom::ImeTextSpanType::kMisspellingSuggestion: *out = ui::ImeTextSpan::Type::kMisspellingSuggestion; return true; + case ui::mojom::ImeTextSpanType::kAutocorrect: + *out = ui::ImeTextSpan::Type::kAutocorrect; + return true; } NOTREACHED(); diff --git a/chromium/ui/base/ime/mojom/ime_types_mojom_traits.h b/chromium/ui/base/ime/mojom/ime_types_mojom_traits.h index 58d192e2910..50489fadc75 100644 --- a/chromium/ui/base/ime/mojom/ime_types_mojom_traits.h +++ b/chromium/ui/base/ime/mojom/ime_types_mojom_traits.h @@ -7,20 +7,41 @@ #include <vector> +#include "base/component_export.h" #include "ui/base/ime/ime_text_span.h" -#include "ui/base/ime/mojom/ime_types.mojom.h" +#include "ui/base/ime/mojom/ime_types.mojom-shared.h" +#include "ui/base/ime/text_input_action.h" +#include "ui/base/ime/text_input_mode.h" #include "ui/base/ime/text_input_type.h" namespace mojo { template <> -struct EnumTraits<ui::mojom::TextInputType, ui::TextInputType> { +struct COMPONENT_EXPORT(IME_SHARED_MOJOM_TRAITS) + EnumTraits<ui::mojom::TextInputMode, ui::TextInputMode> { + static ui::mojom::TextInputMode ToMojom(ui::TextInputMode text_input_mode); + static bool FromMojom(ui::mojom::TextInputMode input, ui::TextInputMode* out); +}; + +template <> +struct COMPONENT_EXPORT(IME_SHARED_MOJOM_TRAITS) + EnumTraits<ui::mojom::TextInputAction, ui::TextInputAction> { + static ui::mojom::TextInputAction ToMojom( + ui::TextInputAction text_input_action); + static bool FromMojom(ui::mojom::TextInputAction input, + ui::TextInputAction* out); +}; + +template <> +struct COMPONENT_EXPORT(IME_SHARED_MOJOM_TRAITS) + EnumTraits<ui::mojom::TextInputType, ui::TextInputType> { static ui::mojom::TextInputType ToMojom(ui::TextInputType text_input_type); static bool FromMojom(ui::mojom::TextInputType input, ui::TextInputType* out); }; template <> -struct StructTraits<ui::mojom::ImeTextSpanDataView, ui::ImeTextSpan> { +struct COMPONENT_EXPORT(IME_SHARED_MOJOM_TRAITS) + StructTraits<ui::mojom::ImeTextSpanDataView, ui::ImeTextSpan> { static ui::ImeTextSpan::Type type(const ui::ImeTextSpan& c) { return c.type; } static uint32_t start_offset(const ui::ImeTextSpan& c) { return c.start_offset; @@ -46,6 +67,9 @@ struct StructTraits<ui::mojom::ImeTextSpanDataView, ui::ImeTextSpan> { static bool remove_on_finish_composing(const ui::ImeTextSpan& c) { return c.remove_on_finish_composing; } + static bool interim_char_selection(const ui::ImeTextSpan& c) { + return c.interim_char_selection; + } static std::vector<std::string> suggestions(const ui::ImeTextSpan& c) { return c.suggestions; } @@ -53,7 +77,8 @@ struct StructTraits<ui::mojom::ImeTextSpanDataView, ui::ImeTextSpan> { }; template <> -struct EnumTraits<ui::mojom::ImeTextSpanType, ui::ImeTextSpan::Type> { +struct COMPONENT_EXPORT(IME_SHARED_MOJOM_TRAITS) + EnumTraits<ui::mojom::ImeTextSpanType, ui::ImeTextSpan::Type> { static ui::mojom::ImeTextSpanType ToMojom( ui::ImeTextSpan::Type ime_text_span_type); static bool FromMojom(ui::mojom::ImeTextSpanType input, @@ -61,7 +86,8 @@ struct EnumTraits<ui::mojom::ImeTextSpanType, ui::ImeTextSpan::Type> { }; template <> -struct EnumTraits<ui::mojom::ImeTextSpanThickness, ui::ImeTextSpan::Thickness> { +struct COMPONENT_EXPORT(IME_SHARED_MOJOM_TRAITS) + EnumTraits<ui::mojom::ImeTextSpanThickness, ui::ImeTextSpan::Thickness> { static ui::mojom::ImeTextSpanThickness ToMojom( ui::ImeTextSpan::Thickness thickness); static bool FromMojom(ui::mojom::ImeTextSpanThickness input, @@ -69,8 +95,9 @@ struct EnumTraits<ui::mojom::ImeTextSpanThickness, ui::ImeTextSpan::Thickness> { }; template <> -struct EnumTraits<ui::mojom::ImeTextSpanUnderlineStyle, - ui::ImeTextSpan::UnderlineStyle> { +struct COMPONENT_EXPORT(IME_SHARED_MOJOM_TRAITS) + EnumTraits<ui::mojom::ImeTextSpanUnderlineStyle, + ui::ImeTextSpan::UnderlineStyle> { static ui::mojom::ImeTextSpanUnderlineStyle ToMojom( ui::ImeTextSpan::UnderlineStyle underline_style); static bool FromMojom(ui::mojom::ImeTextSpanUnderlineStyle input, diff --git a/chromium/ui/base/ime/mojom/text_input_state.mojom b/chromium/ui/base/ime/mojom/text_input_state.mojom new file mode 100644 index 00000000000..63746cb4d67 --- /dev/null +++ b/chromium/ui/base/ime/mojom/text_input_state.mojom @@ -0,0 +1,68 @@ +// Copyright 2020 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. + +module ui.mojom; + +import "mojo/public/mojom/base/string16.mojom"; +import "mojo/public/mojom/base/text_direction.mojom"; +import "ui/base/ime/mojom/ime_types.mojom"; +import "ui/base/ime/mojom/virtual_keyboard_types.mojom"; +import "ui/gfx/geometry/mojom/geometry.mojom"; +import "ui/gfx/range/mojom/range.mojom"; + +// This structure represents the current editing state. +struct TextInputState { + // Type of the input field. + ui.mojom.TextInputType type = ui.mojom.TextInputType.NONE; + + // The mode of input field. + ui.mojom.TextInputMode mode = ui.mojom.TextInputMode.kDefault; + + // The action of the input field. + ui.mojom.TextInputAction action = ui.mojom.TextInputAction.kDefault; + + // The flags of input field (autocorrect, autocomplete, etc.) + // See ui/base/ime/text_input_flags.h for definitions. + uint32 flags; + + // The value of input field. + mojo_base.mojom.String16? value; + + // The current selection range, or the caret position if nothing is selected. + gfx.mojom.Range selection; + + // The current composition range if there is one. + gfx.mojom.Range? composition; + + // Whether or not inline composition can be performed for the current input. + bool can_compose_inline = true; + + // Whether or not the IME should be shown as a result of this update. Even if + // true, the IME will only be shown if the input is appropriate (e.g. not + // TEXT_INPUT_TYPE_NONE). + bool show_ime_if_needed; + + // Whether or not the IME should always be hidden as a result of this update. + bool always_hide_ime; + + // Whether or not this is a reply to a request from IME. + bool reply_to_request; + + // Store control and selection bounds of EditContext. + // These optionals will be nullopts if there isn't any active EditContext. + // For non EditContext scenarios, the bounds are returned via + // |GetCompositionCharacterBounds| + gfx.mojom.Rect? edit_context_control_bounds; + gfx.mojom.Rect? edit_context_selection_bounds; + + // The virtualkeyboardpolicy of the input field. + ui.mojom.VirtualKeyboardPolicy vk_policy = + ui.mojom.VirtualKeyboardPolicy.AUTO; + + // Whether or not show()/hide() API is called from VirtualKeyboard by web + // authors when the virtualkeyboardpolicy is manual. + ui.mojom.VirtualKeyboardVisibilityRequest last_vk_visibility_request = + ui.mojom.VirtualKeyboardVisibilityRequest.NONE; +}; + diff --git a/chromium/ui/base/ime/virtual_keyboard_visibility_request.h b/chromium/ui/base/ime/mojom/virtual_keyboard_types.mojom index 65cee20f299..d1cd8d038f7 100644 --- a/chromium/ui/base/ime/virtual_keyboard_visibility_request.h +++ b/chromium/ui/base/ime/mojom/virtual_keyboard_types.mojom @@ -2,20 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef UI_BASE_IME_VIRTUAL_KEYBOARD_VISIBILITY_REQUEST_H_ -#define UI_BASE_IME_VIRTUAL_KEYBOARD_VISIBILITY_REQUEST_H_ +module ui.mojom; -namespace ui { +// This mode corresponds to virtualkeyboardpolicy +// https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/master/VirtualKeyboardPolicy/explainer.md +enum VirtualKeyboardPolicy { + AUTO, + MANUAL, +}; // This mode corresponds to VirtualKeyboard API show/hide. // https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/master/VirtualKeyboardPolicy/explainer.md -enum class VirtualKeyboardVisibilityRequest { +enum VirtualKeyboardVisibilityRequest { SHOW, HIDE, NONE, - MAX = NONE, }; - -} // namespace ui - -#endif // UI_BASE_IME_VIRTUAL_KEYBOARD_VISIBILITY_REQUEST_H_ diff --git a/chromium/ui/base/ime/text_input_client.h b/chromium/ui/base/ime/text_input_client.h index 7fc2d584a94..b6302623328 100644 --- a/chromium/ui/base/ime/text_input_client.h +++ b/chromium/ui/base/ime/text_input_client.h @@ -217,6 +217,13 @@ class COMPONENT_EXPORT(UI_BASE_IME) TextInputClient { const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) = 0; #endif +#if defined(OS_CHROMEOS) + // Set the autocorrect range and return if it has been set correctly as a + // boolean value. + virtual bool SetAutocorrectRange(const base::string16& autocorrect_text, + const gfx::Range& range) = 0; +#endif + #if defined(OS_WIN) // Returns false if either the focused editable element or the EditContext // bounds is not available, else it returns true with the control and diff --git a/chromium/ui/base/ime/win/input_method_win_base.cc b/chromium/ui/base/ime/win/input_method_win_base.cc index 83850840d83..fc9c8d3a0f2 100644 --- a/chromium/ui/base/ime/win/input_method_win_base.cc +++ b/chromium/ui/base/ime/win/input_method_win_base.cc @@ -13,8 +13,6 @@ #include "base/command_line.h" #include "base/memory/ptr_util.h" #include "base/win/windows_version.h" -#include "ui/base/ime/ime_bridge.h" -#include "ui/base/ime/ime_engine_handler_interface.h" #include "ui/base/ime/text_input_client.h" #include "ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.h" #include "ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h" @@ -237,21 +235,6 @@ ui::EventDispatchDetails InputMethodWinBase::DispatchKeyEvent( !std::iswcntrl(static_cast<wint_t>(char_msgs[0].wParam))) event->set_character(static_cast<base::char16>(char_msgs[0].wParam)); - // Dispatches the key events to the Chrome IME extension which is listening to - // key events on the following two situations: - // 1) |char_msgs| is empty when the event is non-character key. - // 2) |char_msgs|.size() == 1 when the event is character key and the WM_CHAR - // messages have been combined in the event processing flow. - if (char_msgs.size() <= 1 && GetEngine()) { - ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback = - base::BindOnce(&InputMethodWinBase::ProcessKeyEventDone, - weak_ptr_factory_.GetWeakPtr(), - base::Owned(new ui::KeyEvent(*event)), - base::Owned(new std::vector<MSG>(char_msgs))); - GetEngine()->ProcessKeyEvent(*event, std::move(callback)); - return ui::EventDispatchDetails(); - } - return ProcessUnhandledKeyEvent(event, &char_msgs); } @@ -506,48 +489,4 @@ ui::EventDispatchDetails InputMethodWinBase::ProcessUnhandledKeyEvent( return details; } -void InputMethodWinBase::UpdateCompositionBoundsForEngine( - const TextInputClient* client) { - TextInputType text_input_type = GetTextInputType(); - if (client == GetTextInputClient() && - text_input_type != TEXT_INPUT_TYPE_NONE && - text_input_type != TEXT_INPUT_TYPE_PASSWORD && GetEngine()) { - GetEngine()->SetCompositionBounds(GetCompositionBounds(client)); - } -} - -void InputMethodWinBase::ResetEngine() { - if (GetEngine()) - GetEngine()->Reset(); -} - -void InputMethodWinBase::CancelCompositionForEngine() { - TextInputType text_input_type = GetTextInputType(); - if (text_input_type != TEXT_INPUT_TYPE_NONE && - text_input_type != TEXT_INPUT_TYPE_PASSWORD) { - InputMethodWinBase::ResetEngine(); - } -} - -void InputMethodWinBase::UpdateEngineFocusAndInputContext() { - if (!ui::IMEBridge::Get()) // IMEBridge could be null for tests. - return; - - const TextInputType old_text_input_type = - ui::IMEBridge::Get()->GetCurrentInputContext().type; - ui::IMEEngineHandlerInterface::InputContext context( - GetTextInputType(), GetTextInputMode(), GetTextInputFlags(), - ui::TextInputClient::FOCUS_REASON_OTHER, GetClientShouldDoLearning()); - ui::IMEBridge::Get()->SetCurrentInputContext(context); - - // Update IME Engine state. - ui::IMEEngineHandlerInterface* engine = GetEngine(); - if (engine) { - if (old_text_input_type != ui::TEXT_INPUT_TYPE_NONE) - engine->FocusOut(); - if (GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE) - engine->FocusIn(context); - } -} - } // namespace ui diff --git a/chromium/ui/base/ime/win/input_method_win_base.h b/chromium/ui/base/ime/win/input_method_win_base.h index 139d966dc0e..c788c6b5f35 100644 --- a/chromium/ui/base/ime/win/input_method_win_base.h +++ b/chromium/ui/base/ime/win/input_method_win_base.h @@ -62,19 +62,6 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) InputMethodWinBase ui::KeyEvent* event, const std::vector<MSG>* char_msgs); - // Update composition bounds for Chromium IME extension. - void UpdateCompositionBoundsForEngine(const TextInputClient* client); - - // Reset composition status for Chromium IME extension. - void ResetEngine(); - - // Cancel composition for Chromium IME extension. - void CancelCompositionForEngine(); - - // Update focus state for Chromium IME extension and update input context in - // ui::IMEBridge. - void UpdateEngineFocusAndInputContext(); - // The toplevel window handle. const HWND toplevel_window_handle_; diff --git a/chromium/ui/base/ime/win/input_method_win_imm32.cc b/chromium/ui/base/ime/win/input_method_win_imm32.cc index 7c0ee3ee966..324a6bc91fb 100644 --- a/chromium/ui/base/ime/win/input_method_win_imm32.cc +++ b/chromium/ui/base/ime/win/input_method_win_imm32.cc @@ -12,8 +12,6 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/metrics/histogram_macros.h" -#include "ui/base/ime/ime_bridge.h" -#include "ui/base/ime/ime_engine_handler_interface.h" #include "ui/base/ime/text_input_client.h" #include "ui/base/ime/win/tsf_input_scope.h" #include "ui/display/win/screen_win.h" @@ -101,7 +99,6 @@ void InputMethodWinImm32::OnCaretBoundsChanged(const TextInputClient* client) { if (!IsTextInputClientFocused(client) || !IsWindowFocused(client)) return; NotifyTextInputCaretBoundsChanged(client); - InputMethodWinBase::UpdateCompositionBoundsForEngine(client); if (!enabled_) return; @@ -126,13 +123,8 @@ void InputMethodWinImm32::OnCaretBoundsChanged(const TextInputClient* client) { } void InputMethodWinImm32::CancelComposition(const TextInputClient* client) { - if (IsTextInputClientFocused(client)) { - // |enabled_| == false could be faked, and the engine should rely on the - // real type get from GetTextInputType(). - InputMethodWinBase::CancelCompositionForEngine(); - - if (enabled_) - imm32_manager_.CancelIME(toplevel_window_handle_); + if (IsTextInputClientFocused(client) && enabled_) { + imm32_manager_.CancelIME(toplevel_window_handle_); } } @@ -326,8 +318,6 @@ void InputMethodWinImm32::RefreshInputLanguage() { void InputMethodWinImm32::ConfirmCompositionText(bool reset_engine, bool keep_selection) { InputMethodBase::ConfirmCompositionText(reset_engine, keep_selection); - if (reset_engine) - InputMethodWinBase::ResetEngine(); // Makes sure the native IME app can be informed about the composition is // cleared, so that it can clean up its internal states. @@ -339,8 +329,7 @@ void InputMethodWinImm32::UpdateIMEState() { // Use switch here in case we are going to add more text input types. // We disable input method in password field. const HWND window_handle = toplevel_window_handle_; - const TextInputType text_input_type = - GetEngine() ? TEXT_INPUT_TYPE_NONE : GetTextInputType(); + const TextInputType text_input_type = GetTextInputType(); const TextInputMode text_input_mode = GetTextInputMode(); switch (text_input_type) { case ui::TEXT_INPUT_TYPE_NONE: @@ -357,8 +346,6 @@ void InputMethodWinImm32::UpdateIMEState() { imm32_manager_.SetTextInputMode(window_handle, text_input_mode); tsf_inputscope::SetInputScopeForTsfUnawareWindow( window_handle, text_input_type, text_input_mode); - - InputMethodWinBase::UpdateEngineFocusAndInputContext(); } } // namespace ui diff --git a/chromium/ui/base/ime/win/input_method_win_tsf.cc b/chromium/ui/base/ime/win/input_method_win_tsf.cc index 58926e51a7f..b4e4fcc2e67 100644 --- a/chromium/ui/base/ime/win/input_method_win_tsf.cc +++ b/chromium/ui/base/ime/win/input_method_win_tsf.cc @@ -100,7 +100,6 @@ void InputMethodWinTSF::OnTextInputTypeChanged(const TextInputClient* client) { } ui::TSFBridge::GetInstance()->CancelComposition(); ui::TSFBridge::GetInstance()->OnTextInputTypeChanged(client); - InputMethodWinBase::UpdateEngineFocusAndInputContext(); } void InputMethodWinTSF::OnCaretBoundsChanged(const TextInputClient* client) { @@ -110,14 +109,12 @@ void InputMethodWinTSF::OnCaretBoundsChanged(const TextInputClient* client) { } NotifyTextInputCaretBoundsChanged(client); ui::TSFBridge::GetInstance()->OnTextLayoutChanged(); - InputMethodWinBase::UpdateCompositionBoundsForEngine(client); } void InputMethodWinTSF::CancelComposition(const TextInputClient* client) { if (ui::TSFBridge::GetInstance() && IsTextInputClientFocused(client) && IsWindowFocused(client)) { ui::TSFBridge::GetInstance()->CancelComposition(); - InputMethodWinBase::CancelCompositionForEngine(); } } @@ -181,8 +178,6 @@ void InputMethodWinTSF::ConfirmCompositionText(bool reset_engine, if (IsTextInputTypeNone()) return; - if (reset_engine && GetTextInputClient()->HasCompositionText()) - InputMethodWinBase::ResetEngine(); if (ui::TSFBridge::GetInstance()) ui::TSFBridge::GetInstance()->ConfirmComposition(); } diff --git a/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.cc b/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.cc index cf2caabef7d..5c19abd64d6 100644 --- a/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.cc +++ b/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.cc @@ -222,7 +222,7 @@ void OnScreenKeyboardDisplayManagerInputPane::Run() { // Execute show() or hide() on the background thread after the debounce // expires. switch (last_vk_visibility_request_) { - case VirtualKeyboardVisibilityRequest::SHOW: { + case mojom::VirtualKeyboardVisibilityRequest::SHOW: { background_task_runner_->PostTask( FROM_HERE, base::BindOnce( @@ -231,7 +231,7 @@ void OnScreenKeyboardDisplayManagerInputPane::Run() { base::RetainedRef(virtual_keyboard_input_pane_), hwnd_)); break; } - case VirtualKeyboardVisibilityRequest::HIDE: { + case mojom::VirtualKeyboardVisibilityRequest::HIDE: { background_task_runner_->PostTask( FROM_HERE, base::BindOnce( @@ -240,18 +240,18 @@ void OnScreenKeyboardDisplayManagerInputPane::Run() { base::RetainedRef(virtual_keyboard_input_pane_), hwnd_)); break; } - case VirtualKeyboardVisibilityRequest::NONE: { + case mojom::VirtualKeyboardVisibilityRequest::NONE: { break; } } // Reset the VK visibility state to none so we can keep track of subsequent // API calls. - last_vk_visibility_request_ = VirtualKeyboardVisibilityRequest::NONE; + last_vk_visibility_request_ = mojom::VirtualKeyboardVisibilityRequest::NONE; } bool OnScreenKeyboardDisplayManagerInputPane::DisplayVirtualKeyboard() { DCHECK(main_task_runner_->BelongsToCurrentThread()); - last_vk_visibility_request_ = VirtualKeyboardVisibilityRequest::SHOW; + last_vk_visibility_request_ = mojom::VirtualKeyboardVisibilityRequest::SHOW; debouncer_->RequestRun(base::BindOnce( &OnScreenKeyboardDisplayManagerInputPane::Run, base::Unretained(this))); return true; @@ -259,7 +259,7 @@ bool OnScreenKeyboardDisplayManagerInputPane::DisplayVirtualKeyboard() { void OnScreenKeyboardDisplayManagerInputPane::DismissVirtualKeyboard() { DCHECK(main_task_runner_->BelongsToCurrentThread()); - last_vk_visibility_request_ = VirtualKeyboardVisibilityRequest::HIDE; + last_vk_visibility_request_ = mojom::VirtualKeyboardVisibilityRequest::HIDE; debouncer_->RequestRun(base::BindOnce( &OnScreenKeyboardDisplayManagerInputPane::Run, base::Unretained(this))); } diff --git a/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.h b/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.h index 40c8578cb79..68b15c27f21 100644 --- a/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.h +++ b/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_input_pane.h @@ -18,7 +18,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/win/windows_types.h" #include "ui/base/ime/input_method_keyboard_controller.h" -#include "ui/base/ime/virtual_keyboard_visibility_request.h" +#include "ui/base/ime/mojom/virtual_keyboard_types.mojom-shared.h" #include "ui/base/ime/win/virtual_keyboard_debounce_timer.h" #include "ui/gfx/geometry/rect.h" @@ -47,8 +47,8 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) pane); // Returns whether show/hide VK API is called from // InputMethodKeyboardController or not. - VirtualKeyboardVisibilityRequest GetLastVirtualKeyboardVisibilityRequest() - const { + mojom::VirtualKeyboardVisibilityRequest + GetLastVirtualKeyboardVisibilityRequest() const { return last_vk_visibility_request_; } @@ -69,8 +69,8 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) const scoped_refptr<base::SingleThreadTaskRunner> background_task_runner_; scoped_refptr<VirtualKeyboardInputPane> virtual_keyboard_input_pane_; bool is_keyboard_visible_; - VirtualKeyboardVisibilityRequest last_vk_visibility_request_ = - VirtualKeyboardVisibilityRequest::NONE; + mojom::VirtualKeyboardVisibilityRequest last_vk_visibility_request_ = + mojom::VirtualKeyboardVisibilityRequest::NONE; std::unique_ptr<VirtualKeyboardDebounceTimer> debouncer_; base::WeakPtrFactory<OnScreenKeyboardDisplayManagerInputPane> weak_factory_{ this}; diff --git a/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h b/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h index c32989e65b7..f718926d662 100644 --- a/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h +++ b/chromium/ui/base/ime/win/on_screen_keyboard_display_manager_tab_tip.h @@ -11,7 +11,6 @@ #include "base/observer_list.h" #include "base/strings/string16.h" #include "ui/base/ime/input_method_keyboard_controller.h" -#include "ui/base/ui_base_export.h" #include "ui/gfx/geometry/rect.h" namespace ui { diff --git a/chromium/ui/base/ime/win/tsf_bridge.cc b/chromium/ui/base/ime/win/tsf_bridge.cc index 778f19bb853..f5c8c7155d4 100644 --- a/chromium/ui/base/ime/win/tsf_bridge.cc +++ b/chromium/ui/base/ime/win/tsf_bridge.cc @@ -111,6 +111,10 @@ class TSFBridgeImpl : public TSFBridge { // An ITfThreadMgr object to be used in focus and document management. Microsoft::WRL::ComPtr<ITfThreadMgr> thread_manager_; + // An ITfInputProcessorProfiles object to be used to get current language + // locale profile. + Microsoft::WRL::ComPtr<ITfInputProcessorProfiles> input_processor_profiles_; + // A map from TextInputType to an editable document for TSF. We use multiple // TSF documents that have different InputScopes and TSF attributes based on // the TextInputType associated with the target document. For a TextInputType @@ -134,6 +138,9 @@ class TSFBridgeImpl : public TSFBridge { // Handle to ITfKeyTraceEventSink. DWORD key_trace_sink_cookie_ = 0; + // Handle to ITfLanguageProfileNotifySink + DWORD language_profile_cookie_ = 0; + DISALLOW_COPY_AND_ASSIGN(TSFBridgeImpl); }; @@ -149,6 +156,11 @@ TSFBridgeImpl::~TSFBridgeImpl() { if (SUCCEEDED(thread_manager_->QueryInterface(IID_PPV_ARGS(&source)))) { source->UnadviseSink(key_trace_sink_cookie_); } + Microsoft::WRL::ComPtr<ITfSource> language_source; + if (SUCCEEDED(input_processor_profiles_->QueryInterface( + IID_PPV_ARGS(&language_source)))) { + language_source->UnadviseSink(language_profile_cookie_); + } } for (TSFDocumentMap::iterator it = tsf_document_map_.begin(); @@ -174,6 +186,13 @@ bool TSFBridgeImpl::Initialize() { return false; } + if (FAILED(::CoCreateInstance(CLSID_TF_InputProcessorProfiles, nullptr, + CLSCTX_ALL, + IID_PPV_ARGS(&input_processor_profiles_)))) { + DVLOG(1) << "Failed to create InputProcessorProfiles instance."; + return false; + } + if (FAILED(::CoCreateInstance(CLSID_TF_ThreadMgr, nullptr, CLSCTX_ALL, IID_PPV_ARGS(&thread_manager_)))) { DVLOG(1) << "Failed to create ThreadManager instance."; @@ -309,7 +328,8 @@ void TSFBridgeImpl::SetFocusedClient(HWND focused_window, void TSFBridgeImpl::RemoveFocusedClient(TextInputClient* client) { DCHECK(base::MessageLoopCurrentForUI::IsSet()); - DCHECK(IsInitialized()); + if (!IsInitialized()) + return; if (client_ != client) return; ClearAssociateFocus(); @@ -422,6 +442,21 @@ bool TSFBridgeImpl::CreateDocumentManager(TSFTextStore* text_store, return false; } + Microsoft::WRL::ComPtr<ITfSource> language_source; + if (FAILED(input_processor_profiles_->QueryInterface( + IID_PPV_ARGS(&language_source)))) { + DVLOG(1) << "Failed to get source_ITfInputProcessorProfiles."; + return false; + } + + if (FAILED( + language_source->AdviseSink(IID_ITfLanguageProfileNotifySink, + static_cast<ITfTextEditSink*>(text_store), + &language_profile_cookie_))) { + DVLOG(1) << "AdviseSink for language profile notify sink failed."; + return false; + } + if (*source_cookie == TF_INVALID_COOKIE) { DVLOG(1) << "The result of cookie is invalid."; return false; diff --git a/chromium/ui/base/ime/win/tsf_text_store.cc b/chromium/ui/base/ime/win/tsf_text_store.cc index 22f43ff72b0..98ca302320d 100644 --- a/chromium/ui/base/ime/win/tsf_text_store.cc +++ b/chromium/ui/base/ime/win/tsf_text_store.cc @@ -11,6 +11,7 @@ #include <algorithm> +#include "base/logging.h" #include "base/numerics/ranges.h" #include "base/win/scoped_variant.h" #include "ui/base/ime/text_input_client.h" @@ -80,6 +81,8 @@ HRESULT TSFTextStore::QueryInterface(REFIID iid, void** result) { *result = static_cast<ITextStoreACP*>(this); } else if (iid == IID_ITfContextOwnerCompositionSink) { *result = static_cast<ITfContextOwnerCompositionSink*>(this); + } else if (iid == IID_ITfLanguageProfileNotifySink) { + *result = static_cast<ITfLanguageProfileNotifySink*>(this); } else if (iid == IID_ITfTextEditSink) { *result = static_cast<ITfTextEditSink*>(this); } else if (iid == IID_ITfKeyTraceEventSink) { @@ -647,9 +650,7 @@ HRESULT TSFTextStore::RequestLock(DWORD lock_flags, HRESULT* result) { // 3. User commits current composition text. if (((new_composition_start > last_composition_start && text_input_client_->HasCompositionText()) || - (wparam_keydown_fired_ == 0 && !has_composition_range_ && - !text_input_client_->HasCompositionText()) || - (wparam_keydown_fired_ != 0 && !has_composition_range_)) && + !has_composition_range_) && text_input_client_) { CommitTextAndEndCompositionIfAny(last_composition_start, new_composition_start); @@ -694,6 +695,7 @@ HRESULT TSFTextStore::RequestLock(DWORD lock_flags, HRESULT* result) { // reset the flag since we've already inserted/replaced the text. new_text_inserted_ = false; + is_selection_interim_char_ = false; // reset string_buffer_ if composition is no longer active. if (!text_input_client_->HasCompositionText()) { @@ -760,6 +762,7 @@ HRESULT TSFTextStore::SetSelection(ULONG selection_buffer_size, } selection_.set_start(start_pos); selection_.set_end(end_pos); + is_selection_interim_char_ = selection_buffer[0].style.fInterimChar; } return S_OK; } @@ -829,6 +832,15 @@ HRESULT TSFTextStore::OnEndComposition(ITfCompositionView* composition_view) { return S_OK; } +HRESULT TSFTextStore::OnLanguageChange(LANGID langid, BOOL* pfAccept) { + return S_OK; +} +HRESULT TSFTextStore::OnLanguageChanged() { + if (text_input_client_) + text_input_client_->OnInputMethodChanged(); + return S_OK; +} + HRESULT TSFTextStore::OnKeyTraceDown(WPARAM wParam, LPARAM lParam) { // fire the event right away if we're in composition if (has_composition_range_) { @@ -1052,6 +1064,10 @@ bool TSFTextStore::GetCompositionStatus( span.end_offset = start_pos + length; span.underline_color = SK_ColorBLACK; span.background_color = SK_ColorTRANSPARENT; + if (selection_.EqualsIgnoringDirection( + gfx::Range(span.start_offset, span.end_offset))) { + span.interim_char_selection = is_selection_interim_char_; + } if (has_display_attribute) GetStyle(display_attribute, &span); spans->push_back(span); @@ -1355,8 +1371,11 @@ void TSFTextStore::CommitTextAndEndCompositionIfAny(size_t old_size, : new_committed_string_size); // TODO(crbug.com/978678): Unify the behavior of // |TextInputClient::InsertText(text)| for the empty text. - if (!new_committed_string.empty()) + if (!new_committed_string.empty()) { text_input_client_->InsertText(new_committed_string); + } else { + text_input_client_->ClearCompositionText(); + } // Notify accessibility about this committed composition text_input_client_->SetActiveCompositionForAccessibility( replace_text_range_, new_committed_string, diff --git a/chromium/ui/base/ime/win/tsf_text_store.h b/chromium/ui/base/ime/win/tsf_text_store.h index 10bbae5a50e..bf02704ffff 100644 --- a/chromium/ui/base/ime/win/tsf_text_store.h +++ b/chromium/ui/base/ime/win/tsf_text_store.h @@ -102,6 +102,7 @@ class TextInputClient; class COMPONENT_EXPORT(UI_BASE_IME_WIN) TSFTextStore : public ITextStoreACP, public ITfContextOwnerCompositionSink, + public ITfLanguageProfileNotifySink, public ITfKeyTraceEventSink, public ITfTextEditSink { public: @@ -216,6 +217,10 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) TSFTextStore IFACEMETHODIMP OnEndComposition( ITfCompositionView* composition_view) override; + // ITfLanguageProfileNotifySink: + IFACEMETHODIMP OnLanguageChange(LANGID langid, BOOL* pfAccept) override; + IFACEMETHODIMP OnLanguageChanged() override; + // ITfTextEditSink: IFACEMETHODIMP OnEndEdit(ITfContext* context, TfEditCookie read_only_edit_cookie, @@ -391,6 +396,10 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) TSFTextStore // |selection_.end()|: 4 gfx::Range selection_; + // Indicates if the selection is an interim character. Please refer to + // https://docs.microsoft.com/en-us/windows/win32/api/textstor/ns-textstor-ts_selectionstyle + bool is_selection_interim_char_ = false; + // |start_offset| and |end_offset| of |text_spans_| indicates // the offsets in |string_buffer_document_|. // Example: "aoi" is committed. There are two underlines in "umi" and "no". diff --git a/chromium/ui/base/ime/win/tsf_text_store_unittest.cc b/chromium/ui/base/ime/win/tsf_text_store_unittest.cc index 081809d75a1..4e81d7c1012 100644 --- a/chromium/ui/base/ime/win/tsf_text_store_unittest.cc +++ b/chromium/ui/base/ime/win/tsf_text_store_unittest.cc @@ -3394,5 +3394,92 @@ TEST_F(TSFTextStoreTest, RegressionTest7) { EXPECT_EQ(S_OK, result); } +// regression tests for crbug.com/1091069. +// We should allow inserting empty compositon string to cancel composition. +class RegressionTest8Callback : public TSFTextStoreTestCallback { + public: + explicit RegressionTest8Callback(TSFTextStore* text_store) + : TSFTextStoreTestCallback(text_store) {} + + HRESULT LockGranted1(DWORD flags) { + SetTextTest(0, 0, L"bbbb", S_OK); + SetSelectionTest(0, 4, S_OK); + + text_spans()->clear(); + ImeTextSpan text_span_1; + text_span_1.start_offset = 0; + text_span_1.end_offset = 4; + text_span_1.underline_color = SK_ColorBLACK; + text_span_1.thickness = ImeTextSpan::Thickness::kThin; + text_span_1.background_color = SK_ColorTRANSPARENT; + text_spans()->push_back(text_span_1); + + *edit_flag() = true; + *composition_start() = 0; + composition_range()->set_start(0); + composition_range()->set_end(4); + *has_composition_range() = true; + + text_store_->OnKeyTraceDown(65u, 1966081u); + return S_OK; + } + + void SetCompositionText1(const ui::CompositionText& composition) { + EXPECT_EQ(L"bbbb", composition.text); + EXPECT_EQ(0u, composition.selection.start()); + EXPECT_EQ(4u, composition.selection.end()); + ASSERT_EQ(1u, composition.ime_text_spans.size()); + EXPECT_EQ(0u, composition.ime_text_spans[0].start_offset); + EXPECT_EQ(4u, composition.ime_text_spans[0].end_offset); + SetHasCompositionText(true); + } + + HRESULT LockGranted2(DWORD flags) { + GetTextTest(0, -1, L"bbbb", 4); + SetTextTest(0, 4, L"", S_OK); + + text_spans()->clear(); + *edit_flag() = true; + *composition_start() = 0; + composition_range()->set_start(0); + composition_range()->set_end(0); + + *has_composition_range() = false; + text_store_->OnKeyTraceUp(65u, 1966081u); + return S_OK; + } + + void ClearCompositionText2() { EXPECT_EQ(false, *has_composition_range()); } + + private: + DISALLOW_COPY_AND_ASSIGN(RegressionTest8Callback); +}; + +TEST_F(TSFTextStoreTest, RegressionTest8) { + RegressionTest8Callback callback(text_store_.get()); + EXPECT_CALL(text_input_client_, SetCompositionText(_)) + .WillOnce( + Invoke(&callback, &RegressionTest8Callback::SetCompositionText1)); + + EXPECT_CALL(text_input_client_, ClearCompositionText()) + .WillOnce( + Invoke(&callback, &RegressionTest8Callback::ClearCompositionText2)); + + EXPECT_CALL(*sink_, OnLockGranted(_)) + .WillOnce(Invoke(&callback, &RegressionTest8Callback::LockGranted1)) + .WillOnce(Invoke(&callback, &RegressionTest8Callback::LockGranted2)); + + ON_CALL(text_input_client_, HasCompositionText()) + .WillByDefault( + Invoke(&callback, &TSFTextStoreTestCallback::HasCompositionText)); + + HRESULT result = kInvalidResult; + EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); + EXPECT_EQ(S_OK, result); + result = kInvalidResult; + EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result)); + EXPECT_EQ(S_OK, result); +} + } // namespace } // namespace ui |