Commit fb2a2b5f authored by Darren Shen's avatar Darren Shen Committed by Commit Bot

ime: Delete chrome.input.ime for Windows and Linux.

This CL deletes "win" and "linux" specific functions in chrome.input.ime,
which resulted in a chain reaction of deletions, including InputImeApi,
InputMethodEngine and UI code.

This CL is intentionally kept as small as possible. There will be
additional cleanups in the future.

Proposal doc: http://doc/1eIsYPs2JhzQ8qmM-96amsashfFmAAC9xoYRmY2CIjtM

Change-Id: I689badba5157f76b5a92d6a9b705a198760e7f00
Bug: 1083803
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2198861
Commit-Queue: Darren Shen <shend@chromium.org>
Reviewed-by: default avatarIstiaque Ahmed <lazyboy@chromium.org>
Reviewed-by: default avatarTrent Apted <tapted@chromium.org>
Reviewed-by: default avatarShu Chen <shuchen@chromium.org>
Reviewed-by: default avatarKeith Lee <keithlee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#771457}
parent d8696470
...@@ -1160,17 +1160,6 @@ static_library("extensions") { ...@@ -1160,17 +1160,6 @@ static_library("extensions") {
] ]
} }
if (is_win || (is_linux && !is_chromeos)) {
sources += [
"api/input_ime/input_ime_api.cc",
"api/input_ime/input_ime_api.h",
"api/input_ime/input_ime_api_nonchromeos.cc",
"api/input_ime/input_ime_api_nonchromeos.h",
"api/input_ime/input_ime_event_router_base.cc",
"api/input_ime/input_ime_event_router_base.h",
]
}
if (enable_plugins) { if (enable_plugins) {
sources += [ sources += [
"plugin_manager.cc", "plugin_manager.cc",
......
...@@ -31,8 +31,6 @@ ...@@ -31,8 +31,6 @@
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
#include "chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h" #include "chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h"
#elif defined(OS_LINUX) || defined(OS_WIN)
#include "chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h"
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
class Profile; class Profile;
......
// Copyright 2016 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 CHROME_BROWSER_EXTENSIONS_API_INPUT_IME_INPUT_IME_API_NONCHROMEOS_H_
#define CHROME_BROWSER_EXTENSIONS_API_INPUT_IME_INPUT_IME_API_NONCHROMEOS_H_
#include "chrome/browser/extensions/api/input_ime/input_ime_event_router_base.h"
#include "chrome/browser/profiles/profile.h"
#include "extensions/browser/extension_function.h"
class Profile;
namespace input_method {
class InputMethodEngine;
} // namespace input_method
// The status indicates whether the permission has been granted or denied when
// the IME warning bubble has been closed.
enum class ImeWarningBubblePermissionStatus {
GRANTED,
GRANTED_AND_NEVER_SHOW,
DENIED,
ABORTED
};
namespace extensions {
class InputImeEventRouterBase;
class InputImeEventRouter : public InputImeEventRouterBase {
public:
explicit InputImeEventRouter(Profile* profile);
~InputImeEventRouter() override;
// Gets the input method engine if the extension is active.
input_method::InputMethodEngineBase* GetEngineIfActive(
const std::string& extension_id,
std::string* error) override;
// Actives the extension with new input method engine, and deletes the
// previous engine if another extension was active.
void SetActiveEngine(const std::string& extension_id);
input_method::InputMethodEngine* active_engine() {
return active_engine_;
}
// Deletes the current input method engine of the specific extension.
void DeleteInputMethodEngine(const std::string& extension_id);
private:
// The active input method engine.
input_method::InputMethodEngine* active_engine_;
DISALLOW_COPY_AND_ASSIGN(InputImeEventRouter);
};
class InputImeCreateWindowFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("input.ime.createWindow", INPUT_IME_CREATEWINDOW)
protected:
~InputImeCreateWindowFunction() override = default;
// ExtensionFunction:
ExtensionFunction::ResponseAction Run() override;
};
class InputImeShowWindowFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("input.ime.showWindow", INPUT_IME_SHOWWINDOW)
protected:
~InputImeShowWindowFunction() override = default;
// ExtensionFunction:
ExtensionFunction::ResponseAction Run() override;
};
class InputImeHideWindowFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("input.ime.hideWindow", INPUT_IME_HIDEWINDOW)
protected:
~InputImeHideWindowFunction() override = default;
// ExtensionFunction:
ExtensionFunction::ResponseAction Run() override;
};
class InputImeActivateFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("input.ime.activate", INPUT_IME_ACTIVATE)
// During testing we can disable showing a warning bubble by setting this flag
// to true, so that the extension can be activated directly.
static bool disable_bubble_for_testing_;
protected:
~InputImeActivateFunction() override = default;
// ExtensionFunction:
ResponseAction Run() override;
private:
// Called when the user finishes interacting with the warning bubble.
// |status| indicates whether the user allows or denies to activate the
// extension.
void OnPermissionBubbleFinished(ImeWarningBubblePermissionStatus status);
};
class InputImeDeactivateFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("input.ime.deactivate", INPUT_IME_DEACTIVATE)
protected:
~InputImeDeactivateFunction() override = default;
// ExtensionFunction:
ResponseAction Run() override;
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_INPUT_IME_INPUT_IME_API_NONCHROMEOS_H_
...@@ -103,7 +103,7 @@ void EnsureBrowserContextKeyedServiceFactoriesBuilt() { ...@@ -103,7 +103,7 @@ void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
extensions::IdentityAPI::GetFactoryInstance(); extensions::IdentityAPI::GetFactoryInstance();
extensions::InstallTrackerFactory::GetInstance(); extensions::InstallTrackerFactory::GetInstance();
extensions::InstallVerifierFactory::GetInstance(); extensions::InstallVerifierFactory::GetInstance();
#if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_WIN) #if defined(OS_CHROMEOS)
extensions::InputImeAPI::GetFactoryInstance(); extensions::InputImeAPI::GetFactoryInstance();
#endif #endif
extensions::LanguageSettingsPrivateDelegateFactory::GetInstance(); extensions::LanguageSettingsPrivateDelegateFactory::GetInstance();
......
...@@ -2396,18 +2396,11 @@ static_library("ui") { ...@@ -2396,18 +2396,11 @@ static_library("ui") {
] ]
} }
if (is_win || is_linux) { if (is_chromeos) {
sources += [ sources += [
"input_method/input_method_engine_base.cc", "input_method/input_method_engine_base.cc",
"input_method/input_method_engine_base.h", "input_method/input_method_engine_base.h",
] ]
if (!is_chromeos) {
sources += [
"input_method/input_method_engine.cc",
"input_method/input_method_engine.h",
]
}
} }
if (is_mac) { if (is_mac) {
...@@ -3101,8 +3094,6 @@ static_library("ui") { ...@@ -3101,8 +3094,6 @@ static_library("ui") {
"views/hover_button_controller.h", "views/hover_button_controller.h",
"views/hung_renderer_view.cc", "views/hung_renderer_view.cc",
"views/hung_renderer_view.h", "views/hung_renderer_view.h",
"views/ime/ime_warning_bubble_view.cc",
"views/ime/ime_warning_bubble_view.h",
"views/importer/import_lock_dialog_view.cc", "views/importer/import_lock_dialog_view.cc",
"views/importer/import_lock_dialog_view.h", "views/importer/import_lock_dialog_view.h",
"views/infobars/alternate_nav_infobar_view.cc", "views/infobars/alternate_nav_infobar_view.cc",
...@@ -3711,10 +3702,6 @@ static_library("ui") { ...@@ -3711,10 +3702,6 @@ static_library("ui") {
"aura/native_window_tracker_aura.h", "aura/native_window_tracker_aura.h",
"aura/tab_contents/web_drag_bookmark_handler_aura.cc", "aura/tab_contents/web_drag_bookmark_handler_aura.cc",
"aura/tab_contents/web_drag_bookmark_handler_aura.h", "aura/tab_contents/web_drag_bookmark_handler_aura.h",
"input_method/ime_native_window.h",
"input_method/ime_window.cc",
"input_method/ime_window.h",
"input_method/ime_window_observer.h",
"views/accelerator_utils_aura.cc", "views/accelerator_utils_aura.cc",
"views/apps/app_window_desktop_native_widget_aura_win.cc", "views/apps/app_window_desktop_native_widget_aura_win.cc",
"views/apps/app_window_desktop_native_widget_aura_win.h", "views/apps/app_window_desktop_native_widget_aura_win.h",
...@@ -3734,10 +3721,6 @@ static_library("ui") { ...@@ -3734,10 +3721,6 @@ static_library("ui") {
"views/apps/shaped_app_window_targeter.h", "views/apps/shaped_app_window_targeter.h",
"views/dropdown_bar_host_aura.cc", "views/dropdown_bar_host_aura.cc",
"views/frame/browser_non_client_frame_view_factory_chromeos.cc", "views/frame/browser_non_client_frame_view_factory_chromeos.cc",
"views/ime/ime_window_frame_view.cc",
"views/ime/ime_window_frame_view.h",
"views/ime/ime_window_view.cc",
"views/ime/ime_window_view.h",
"views/renderer_context_menu/render_view_context_menu_views.cc", "views/renderer_context_menu/render_view_context_menu_views.cc",
"views/renderer_context_menu/render_view_context_menu_views.h", "views/renderer_context_menu/render_view_context_menu_views.h",
"views/tab_contents/chrome_web_contents_view_delegate_views.cc", "views/tab_contents/chrome_web_contents_view_delegate_views.cc",
......
...@@ -82,8 +82,6 @@ namespace web_modal { ...@@ -82,8 +82,6 @@ namespace web_modal {
class WebContentsModalDialogHost; class WebContentsModalDialogHost;
} }
enum class ImeWarningBubblePermissionStatus;
enum class ShowTranslateBubbleResult { enum class ShowTranslateBubbleResult {
// The translate bubble was successfully shown. // The translate bubble was successfully shown.
SUCCESS, SUCCESS,
...@@ -471,12 +469,6 @@ class BrowserWindow : public ui::BaseWindow { ...@@ -471,12 +469,6 @@ class BrowserWindow : public ui::BaseWindow {
// Returns object implementing ExclusiveAccessContext interface. // Returns object implementing ExclusiveAccessContext interface.
virtual ExclusiveAccessContext* GetExclusiveAccessContext() = 0; virtual ExclusiveAccessContext* GetExclusiveAccessContext() = 0;
// Shows the IME warning bubble.
virtual void ShowImeWarningBubble(
const extensions::Extension* extension,
const base::Callback<void(ImeWarningBubblePermissionStatus status)>&
callback) = 0;
// Shows in-product help for the given feature. // Shows in-product help for the given feature.
virtual void ShowInProductHelpPromo(InProductHelpFeature iph_feature) = 0; virtual void ShowInProductHelpPromo(InProductHelpFeature iph_feature) = 0;
......
// Copyright 2016 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 CHROME_BROWSER_UI_INPUT_METHOD_IME_NATIVE_WINDOW_H_
#define CHROME_BROWSER_UI_INPUT_METHOD_IME_NATIVE_WINDOW_H_
namespace gfx {
class Rect;
}
namespace ui {
// The interface to bridge the interactions between ImeWindow and ImeWindowView.
// Note that c/b/ui cannot depend upon the platform specific implementations.
// This is held weakly by ImeWindow. The subclass should do self-destruction
// while the IME window (widget) is destroyed, and its destructor is expected
// to call to ImeWindow::OnWindowDestroyed().
class ImeNativeWindow {
public:
// Shows the native IME window.
virtual void Show() = 0;
// Hides the native IME window.
virtual void Hide() = 0;
// Hides the native IME window.
virtual void Close() = 0;
// Sets the bounds of the native window.
virtual void SetBounds(const gfx::Rect& bounds) = 0;
// Gets the bounds of the native window.
virtual gfx::Rect GetBounds() const = 0;
// Updates the window's title icon.
virtual void UpdateWindowIcon() = 0;
// For testing.
virtual bool IsVisible() const = 0;
protected:
virtual ~ImeNativeWindow() {}
};
} // namespace ui
#endif // CHROME_BROWSER_UI_INPUT_METHOD_IME_NATIVE_WINDOW_H_
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/input_method/ime_window.h"
#include <utility>
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/input_method/ime_native_window.h"
#include "chrome/browser/ui/input_method/ime_window_observer.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_handlers/icons_handler.h"
#include "ui/display/display.h"
#include "ui/display/display_finder.h"
#include "ui/display/screen.h"
#include "ui/gfx/image/image.h"
namespace {
// The vertical margin between the cursor and the follow-cursor window.
const int kFollowCursorMargin = 3;
// The offset from the left of follow cursor window to the left of cursor.
const int kFollowCursorOffset = 32;
} // namespace
namespace ui {
ImeWindow::ImeWindow(Profile* profile,
const extensions::Extension* extension,
content::RenderFrameHost* opener_render_frame_host,
const std::string& url,
Mode mode,
const gfx::Rect& bounds)
: mode_(mode),
title_(extension ? extension->name() : std::string()),
icon_(extension ? std::make_unique<extensions::IconImage>(
profile,
extension,
extensions::IconsInfo::GetIcons(extension),
extension_misc::EXTENSION_ICON_BITTY,
gfx::ImageSkia(),
this)
: nullptr),
native_window_(nullptr) {
registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
content::NotificationService::AllSources());
GURL gurl(url);
if (!gurl.is_valid())
gurl = extension->GetResourceURL(url);
scoped_refptr<content::SiteInstance> site_instance =
opener_render_frame_host ? opener_render_frame_host->GetSiteInstance()
: nullptr;
if (!site_instance ||
site_instance->GetSiteURL().GetOrigin() != gurl.GetOrigin()) {
site_instance = content::SiteInstance::CreateForURL(profile, gurl);
}
content::WebContents::CreateParams create_params(profile,
std::move(site_instance));
if (opener_render_frame_host) {
create_params.opener_render_process_id =
opener_render_frame_host->GetProcess()->GetID();
create_params.opener_render_frame_id =
opener_render_frame_host->GetRoutingID();
}
web_contents_ = content::WebContents::Create(create_params);
web_contents_->SetDelegate(this);
content::OpenURLParams params(gurl, content::Referrer(),
WindowOpenDisposition::SINGLETON_TAB,
ui::PAGE_TRANSITION_LINK, false);
web_contents_->OpenURL(params);
native_window_ = CreateNativeWindow(this, bounds, web_contents_.get());
}
void ImeWindow::Show() {
native_window_->Show();
}
void ImeWindow::Hide() {
native_window_->Hide();
}
void ImeWindow::Close() {
web_contents_.reset();
native_window_->Close();
}
void ImeWindow::SetBounds(const gfx::Rect& bounds) {
native_window_->SetBounds(bounds);
}
void ImeWindow::FollowCursor(const gfx::Rect& cursor_bounds) {
if (mode_ != FOLLOW_CURSOR)
return;
gfx::Rect screen_bounds =
display::FindDisplayNearestPoint(
display::Screen::GetScreen()->GetAllDisplays(),
gfx::Point(cursor_bounds.x(), cursor_bounds.y()))
->bounds();
gfx::Rect window_bounds = native_window_->GetBounds();
int screen_width = screen_bounds.x() + screen_bounds.width();
int screen_height = screen_bounds.y() + screen_bounds.height();
int width = window_bounds.width();
int height = window_bounds.height();
// By default, aligns the left of the window client area to the left of the
// cursor, and aligns the top of the window to the bottom of the cursor.
// If the right of the window would go beyond the screen bounds, aligns the
// right of the window to the screen bounds.
// If the bottom of the window would go beyond the screen bounds, aligns the
// bottom of the window to the cursor top.
int x = cursor_bounds.x() - kFollowCursorOffset;
int y = cursor_bounds.y() + cursor_bounds.height() + kFollowCursorMargin;
if (width < screen_width && x + width > screen_width)
x = screen_width - width;
if (height < screen_height && y + height > screen_height)
y = cursor_bounds.y() - height - kFollowCursorMargin;
window_bounds.set_x(x);
window_bounds.set_y(y);
SetBounds(window_bounds);
}
int ImeWindow::GetFrameId() const {
return web_contents_->GetMainFrame()->GetRoutingID();
}
void ImeWindow::OnWindowDestroyed() {
for (ImeWindowObserver& observer : observers_)
observer.OnWindowDestroyed(this);
native_window_ = nullptr;
delete this;
}
void ImeWindow::AddObserver(ImeWindowObserver* observer) {
observers_.AddObserver(observer);
}
void ImeWindow::RemoveObserver(ImeWindowObserver* observer) {
observers_.RemoveObserver(observer);
}
void ImeWindow::OnExtensionIconImageChanged(extensions::IconImage* image) {
if (native_window_)
native_window_->UpdateWindowIcon();
}
ImeWindow::~ImeWindow() {}
void ImeWindow::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type);
Close();
}
content::WebContents* ImeWindow::OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) {
source->GetController().LoadURLWithParams(
content::NavigationController::LoadURLParams(params));
return source;
}
bool ImeWindow::CanDragEnter(content::WebContents* source,
const content::DropData& data,
blink::WebDragOperationsMask operations_allowed) {
return false;
}
void ImeWindow::CloseContents(content::WebContents* source) {
Close();
}
void ImeWindow::SetContentsBounds(content::WebContents* source,
const gfx::Rect& bounds) {
if (!native_window_)
return;
if (mode_ == NORMAL) {
native_window_->SetBounds(bounds);
return;
}
// Follow-cursor window needs to remain the x/y and only allow JS to
// change the size.
gfx::Rect native_bounds = native_window_->GetBounds();
native_bounds.set_width(bounds.width());
native_bounds.set_height(bounds.height());
native_window_->SetBounds(native_bounds);
}
} // namespace ui
// Copyright 2016 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 CHROME_BROWSER_UI_INPUT_METHOD_IME_WINDOW_H_
#define CHROME_BROWSER_UI_INPUT_METHOD_IME_WINDOW_H_
#include <memory>
#include <string>
#include "base/strings/string16.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "extensions/browser/extension_icon_image.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/image/image.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/widget/widget_observer.h"
class GURL;
class Profile;
namespace content {
class RenderFrameHost;
class WebContents;
} // namespace content
namespace extensions {
class Extension;
}
namespace gfx {
class Rect;
}
namespace ui {
class ImeNativeWindow;
class ImeWindowObserver;
// The implementation for the IME window.
// This is used in the IME extension API.
// The IME window is in-activatable & always-on-top.
// There are 2 types of IME window:
// - Normal type: the titlebar is located at top.
// - Follow-cursor type: the titlebar is located at left, and the window is
// auto-aligned with the text cursor or composition.
// The destructor is private, so the client should call Close() to release
// the instance. And Close() is async.
class ImeWindow : public content::NotificationObserver,
public extensions::IconImage::Observer,
public content::WebContentsDelegate {
public:
enum Mode { NORMAL, FOLLOW_CURSOR };
// Takes |url| as string instead of GURL because resolving GURL requires
// |extension|. As the client code already passes in |extension|, it'd be
// better to simply the client code.
// |opener_render_frame_host| is the RenderFrameHost from where the IME window
// is opened so that the security origin can be correctly set.
ImeWindow(Profile* profile,
const extensions::Extension* extension,
content::RenderFrameHost* opener_render_frame_host,
const std::string& url,
Mode mode,
const gfx::Rect& bounds);
// Methods delegate to ImeNativeWindow.
void Show();
void Hide();
void Close();
void SetBounds(const gfx::Rect& bounds);
// Aligns the follow-cursor window to the given cursor bounds.
// If no follow-cursor window is at present, this method does nothing.
void FollowCursor(const gfx::Rect& cursor_bounds);
// Gets the web contents' frame ID, which is used to get the JS 'window'
// object in the custom bindings.
int GetFrameId() const;
// The callback that is called when the native window has been destroyed.
void OnWindowDestroyed();
void AddObserver(ImeWindowObserver* observer);
void RemoveObserver(ImeWindowObserver* observer);
// Getters.
Mode mode() const { return mode_; }
const std::string& title() const { return title_; }
const extensions::IconImage* icon() const { return icon_.get(); }
const ImeNativeWindow* ime_native_window() const { return native_window_; }
// extensions::IconImage::Observer:
void OnExtensionIconImageChanged(extensions::IconImage* image) override;
private:
~ImeWindow() override;
// content::NotificationObserver:
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
// content::WebContentsDelegate overrides.
content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params) override;
bool CanDragEnter(content::WebContents* source,
const content::DropData& data,
blink::WebDragOperationsMask operations_allowed) override;
void CloseContents(content::WebContents* source) override;
void SetContentsBounds(content::WebContents* source,
const gfx::Rect& bounds) override;
// Creates the native window.
ImeNativeWindow* CreateNativeWindow(ImeWindow* ime_window,
const gfx::Rect& bounds,
content::WebContents* contents);
content::NotificationRegistrar registrar_;
// The mode of this IME window which is either normal or follow-cursor.
// The follow-cursor window has the non client view on the left instead
// of top, and its position can auto-change according to the text cursor
// or composition.
Mode mode_;
// The window title which is shown in the non client view.
const std::string title_;
// The window icon which is shown in the non client view.
const std::unique_ptr<extensions::IconImage> icon_;
// The web contents for the IME window page web UI.
std::unique_ptr<content::WebContents> web_contents_;
ImeNativeWindow* native_window_; // Weak, it does self-destruction.
base::ObserverList<ImeWindowObserver>::Unchecked observers_;
DISALLOW_COPY_AND_ASSIGN(ImeWindow);
};
} // namespace ui
#endif // CHROME_BROWSER_UI_INPUT_METHOD_IME_WINDOW_H_
// Copyright 2016 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 CHROME_BROWSER_UI_INPUT_METHOD_IME_WINDOW_OBSERVER_H_
#define CHROME_BROWSER_UI_INPUT_METHOD_IME_WINDOW_OBSERVER_H_
namespace ui {
class ImeWindowObserver {
public:
ImeWindowObserver() {}
virtual void OnWindowDestroyed(ImeWindow* ime_window) = 0;
protected:
virtual ~ImeWindowObserver() {}
private:
DISALLOW_COPY_AND_ASSIGN(ImeWindowObserver);
};
} // namespace ui
#endif // CHROME_BROWSER_UI_INPUT_METHOD_IME_WINDOW_OBSERVER_H_
This diff is collapsed.
// Copyright 2016 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 CHROME_BROWSER_UI_INPUT_METHOD_INPUT_METHOD_ENGINE_H_
#define CHROME_BROWSER_UI_INPUT_METHOD_INPUT_METHOD_ENGINE_H_
#include <string>
#include <vector>
#include "chrome/browser/ui/input_method/ime_window.h"
#include "chrome/browser/ui/input_method/ime_window_observer.h"
#include "chrome/browser/ui/input_method/input_method_engine_base.h"
namespace content {
class RenderFrameHost;
} // namespace content
namespace input_method {
class InputMethodEngine : public InputMethodEngineBase,
public ui::ImeWindowObserver {
public:
InputMethodEngine();
~InputMethodEngine() override;
// input_method::InputMethodEngineBase overrides:
void FocusOut() override;
void SetCompositionBounds(const std::vector<gfx::Rect>& bounds) override;
void UpdateComposition(const ui::CompositionText& composition_text,
uint32_t cursor_pos,
bool is_visible) override;
bool SetCompositionRange(
uint32_t before,
uint32_t after,
const std::vector<ui::ImeTextSpan>& text_spans) override;
bool SetSelectionRange(uint32_t start, uint32_t end) override;
void CommitTextToInputContext(int context_id,
const std::string& text) override;
bool SendKeyEvent(ui::KeyEvent* ui_event,
const std::string& code,
std::string* error) override;
bool IsActive() const override;
std::string GetExtensionId() const;
// Creates and shows the IME window.
// Returns 0 for errors and |error| will contains the error message.
int CreateImeWindow(const extensions::Extension* extension,
content::RenderFrameHost* render_frame_host,
const std::string& url,
ui::ImeWindow::Mode mode,
const gfx::Rect& bounds,
std::string* error);
void ShowImeWindow(int window_id);
void HideImeWindow(int window_id);
void CloseImeWindows();
private:
// ui::ImeWindowObserver:
void OnWindowDestroyed(ui::ImeWindow* ime_window) override;
// input_method::InputMethodEngineBase override:
bool IsValidKeyEvent(const ui::KeyEvent* ui_event) override;
ui::ImeWindow* FindWindowById(int window_id) const;
// Checks if the page is special page that we want to disable some key events.
bool IsSpecialPage(ui::InputMethod* method);
// Checks if the key event are whitelisted key for all pages.
bool IsValidKeyForAllPages(const ui::KeyEvent* ui_event);
// Holds the IME window instances for properly closing in the destructor.
// The follow-cursor window is singleton.
// The normal windows cannot exceed the max count.
ui::ImeWindow* follow_cursor_window_; // Weak.
std::vector<ui::ImeWindow*> normal_windows_; // Weak.
// Tracks the current cursor bounds so that the new follow cursor window can
// be aligned with cursor once it being created.
gfx::Rect current_cursor_bounds_;
DISALLOW_COPY_AND_ASSIGN(InputMethodEngine);
};
} // namespace input_method
#endif // CHROME_BROWSER_UI_INPUT_METHOD_INPUT_METHOD_ENGINE_H_
...@@ -100,7 +100,6 @@ ...@@ -100,7 +100,6 @@
#include "chrome/browser/ui/views/fullscreen_control/fullscreen_control_host.h" #include "chrome/browser/ui/views/fullscreen_control/fullscreen_control_host.h"
#include "chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.h" #include "chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.h"
#include "chrome/browser/ui/views/hats/hats_bubble_view.h" #include "chrome/browser/ui/views/hats/hats_bubble_view.h"
#include "chrome/browser/ui/views/ime/ime_warning_bubble_view.h"
#include "chrome/browser/ui/views/infobars/infobar_container_view.h" #include "chrome/browser/ui/views/infobars/infobar_container_view.h"
#include "chrome/browser/ui/views/location_bar/intent_picker_view.h" #include "chrome/browser/ui/views/location_bar/intent_picker_view.h"
#include "chrome/browser/ui/views/location_bar/location_bar_view.h" #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
...@@ -3275,13 +3274,6 @@ ExclusiveAccessContext* BrowserView::GetExclusiveAccessContext() { ...@@ -3275,13 +3274,6 @@ ExclusiveAccessContext* BrowserView::GetExclusiveAccessContext() {
return this; return this;
} }
void BrowserView::ShowImeWarningBubble(
const extensions::Extension* extension,
const base::Callback<void(ImeWarningBubblePermissionStatus status)>&
callback) {
ImeWarningBubbleView::ShowBubble(extension, this, callback);
}
std::string BrowserView::GetWorkspace() const { std::string BrowserView::GetWorkspace() const {
return frame_->GetWorkspace(); return frame_->GetWorkspace();
} }
......
...@@ -422,10 +422,6 @@ class BrowserView : public BrowserWindow, ...@@ -422,10 +422,6 @@ class BrowserView : public BrowserWindow,
void ExecuteExtensionCommand(const extensions::Extension* extension, void ExecuteExtensionCommand(const extensions::Extension* extension,
const extensions::Command& command) override; const extensions::Command& command) override;
ExclusiveAccessContext* GetExclusiveAccessContext() override; ExclusiveAccessContext* GetExclusiveAccessContext() override;
void ShowImeWarningBubble(
const extensions::Extension* extension,
const base::Callback<void(ImeWarningBubblePermissionStatus status)>&
callback) override;
std::string GetWorkspace() const override; std::string GetWorkspace() const override;
bool IsVisibleOnAllWorkspaces() const override; bool IsVisibleOnAllWorkspaces() const override;
void HideDownloadShelf(); void HideDownloadShelf();
......
shuchen@chromium.org
azurewei@chromium.org
keithlee@chromium.org
// Copyright 2016 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 "base/bind.h"
#include "chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/views/extensions/extensions_toolbar_container.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
#include "chrome/browser/ui/views/ime/ime_warning_bubble_view.h"
#include "content/public/test/browser_test.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/layout/animating_layout_manager_test_util.h"
class ImeWarningBubbleTest : public extensions::ExtensionBrowserTest {
public:
ImeWarningBubbleTest();
~ImeWarningBubbleTest() override {}
void SetUpOnMainThread() override;
protected:
void OnPermissionBubbleFinished(ImeWarningBubblePermissionStatus status);
bool IsVisible();
void CloseBubble(bool ok, bool checked);
const extensions::Extension* extension_;
ImeWarningBubbleView* ime_warning_bubble_;
base::Callback<void(ImeWarningBubblePermissionStatus status)> callback_;
bool ok_button_pressed_;
bool never_show_checked_;
ui::ScopedAnimationDurationScaleMode disable_animation_{
ui::ScopedAnimationDurationScaleMode::ZERO_DURATION};
DISALLOW_COPY_AND_ASSIGN(ImeWarningBubbleTest);
};
ImeWarningBubbleTest::ImeWarningBubbleTest()
: extension_(nullptr),
ime_warning_bubble_(nullptr),
ok_button_pressed_(false),
never_show_checked_(false) {}
void ImeWarningBubbleTest::SetUpOnMainThread() {
ToolbarActionsBar::disable_animations_for_testing_ = true;
extensions::ExtensionBrowserTest::SetUpOnMainThread();
extension_ = LoadExtension(test_data_dir_.AppendASCII("input_ime"));
callback_ =
base::Bind(&ImeWarningBubbleTest::OnPermissionBubbleFinished,
base::Unretained(this));
browser()->window()->ShowImeWarningBubble(extension_, callback_);
ime_warning_bubble_ = ImeWarningBubbleView::ime_warning_bubble_for_test_;
if (base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu)) {
// Wait for the animation to finish so that the bubble is visible.
views::test::WaitForAnimatingLayoutManager(
BrowserView::GetBrowserViewForBrowser(browser())
->toolbar_button_provider()
->GetExtensionsToolbarContainer());
}
}
void ImeWarningBubbleTest::OnPermissionBubbleFinished(
ImeWarningBubblePermissionStatus status) {
if (status == ImeWarningBubblePermissionStatus::GRANTED ||
status == ImeWarningBubblePermissionStatus::GRANTED_AND_NEVER_SHOW) {
ok_button_pressed_ = true;
} else {
ok_button_pressed_ = false;
}
if (status == ImeWarningBubblePermissionStatus::GRANTED_AND_NEVER_SHOW) {
never_show_checked_ = true;
} else {
never_show_checked_ = false;
}
}
bool ImeWarningBubbleTest::IsVisible() {
return ime_warning_bubble_->GetWidget() &&
ime_warning_bubble_->GetWidget()->IsVisible();
}
void ImeWarningBubbleTest::CloseBubble(bool ok, bool checked) {
ime_warning_bubble_->never_show_checkbox_->SetChecked(checked);
if (ok)
ime_warning_bubble_->Accept();
else
ime_warning_bubble_->Cancel();
}
IN_PROC_BROWSER_TEST_F(ImeWarningBubbleTest, PressOKButton) {
ASSERT_TRUE(!!ime_warning_bubble_);
EXPECT_TRUE(IsVisible());
CloseBubble(true, true);
EXPECT_TRUE(ok_button_pressed_);
EXPECT_TRUE(never_show_checked_);
}
IN_PROC_BROWSER_TEST_F(ImeWarningBubbleTest, PressCANCELButton) {
ASSERT_TRUE(!!ime_warning_bubble_);
EXPECT_TRUE(IsVisible());
CloseBubble(false, false);
EXPECT_FALSE(ok_button_pressed_);
EXPECT_FALSE(never_show_checked_);
}
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/ime/ime_warning_bubble_view.h"
#include <string>
#include <utility>
#include "chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/browser/ui/views/chrome_typography.h"
#include "chrome/browser/ui/views/extensions/extensions_toolbar_container.h"
#include "chrome/browser/ui/views/frame/app_menu_button.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
#include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "chrome/grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/views/controls/button/checkbox.h"
using extensions::Extension;
namespace {
// The column width of the warning bubble.
const int kColumnWidth = 285;
std::unique_ptr<views::Label> CreateExtensionNameLabel(
const base::string16& text) {
auto label = std::make_unique<views::Label>(text, CONTEXT_BODY_TEXT_SMALL);
label->SetMultiLine(true);
label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
return label;
}
} // namespace
// static
void ImeWarningBubbleView::ShowBubble(
const extensions::Extension* extension,
BrowserView* browser_view,
const ImeWarningBubbleResponseCallback& callback) {
// The ImeWarningBubbleView is self-owned, it deletes itself when the widget
// is closed or the parent browser is destroyed.
ImeWarningBubbleView::ime_warning_bubble_for_test_ =
new ImeWarningBubbleView(extension, browser_view, callback);
}
void ImeWarningBubbleView::OnToolbarActionsBarAnimationEnded() {
if (!bubble_has_shown_) {
views::BubbleDialogDelegateView::CreateBubble(this)->Show();
bubble_has_shown_ = true;
}
}
void ImeWarningBubbleView::OnBrowserRemoved(Browser* browser) {
// |browser_| is being destroyed before the bubble is successfully shown.
if ((browser_ == browser) && !bubble_has_shown_)
delete this;
}
// static
ImeWarningBubbleView* ImeWarningBubbleView::ime_warning_bubble_for_test_ =
nullptr;
ImeWarningBubbleView::ImeWarningBubbleView(
const extensions::Extension* extension,
BrowserView* browser_view,
const ImeWarningBubbleResponseCallback& callback)
: extension_(extension),
browser_view_(browser_view),
browser_(browser_view->browser()),
response_callback_(callback) {
BrowserList::AddObserver(this);
SetAcceptCallback(base::BindOnce(
[](ImeWarningBubbleView* bubble) {
const bool never_show = bubble->never_show_checkbox_->GetChecked();
std::move(bubble->response_callback_)
.Run(never_show
? ImeWarningBubblePermissionStatus::GRANTED_AND_NEVER_SHOW
: ImeWarningBubblePermissionStatus::GRANTED);
},
base::Unretained(this)));
SetCancelCallback(base::BindOnce(
[](ImeWarningBubbleView* bubble) {
std::move(bubble->response_callback_)
.Run(ImeWarningBubblePermissionStatus::DENIED);
},
base::Unretained(this)));
// The lifetime of this bubble is tied to the lifetime of the browser.
set_parent_window(
platform_util::GetViewForWindow(browser_view_->GetNativeWindow()));
InitAnchorView();
InitLayout();
if (base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu)) {
// TODO(pbos): During cleanup (default-enabling this), remove
// OnBrowserRemoved and stop observing the browser. The widget will now
// always be created and always have ownership.
// TODO(pbos): Move widget creation outside this class when this is being
// cleaned up. ::ShowBubble should create the Widget and queue showing it.
bubble_has_shown_ = true;
ExtensionsToolbarContainer* const container =
browser_view_->toolbar_button_provider()
->GetExtensionsToolbarContainer();
views::Widget* const widget =
views::BubbleDialogDelegateView::CreateBubble(this);
if (container) {
container->ShowWidgetForExtension(widget, extension_->id());
} else {
widget->Show();
}
chrome::RecordDialogCreation(chrome::DialogIdentifier::IME_WARNING);
return;
}
// If the toolbar is not animating, shows the warning bubble directly.
// Otherwise, shows the bubble in method OnToolbarActionsBarAnimationEnded().
if (IsToolbarAnimating()) {
toolbar_actions_bar_observer_.Add(
browser_view_->toolbar()->browser_actions()->toolbar_actions_bar());
return;
}
views::BubbleDialogDelegateView::CreateBubble(this)->Show();
bubble_has_shown_ = true;
chrome::RecordDialogCreation(chrome::DialogIdentifier::IME_WARNING);
}
ImeWarningBubbleView::~ImeWarningBubbleView() {
if (!response_callback_.is_null()) {
std::move(response_callback_)
.Run(ImeWarningBubblePermissionStatus::ABORTED);
}
BrowserList::RemoveObserver(this);
}
void ImeWarningBubbleView::InitAnchorView() {
views::View* anchor_view = nullptr;
if (anchor_to_action_) {
ExtensionsToolbarContainer* const container =
browser_view_->toolbar_button_provider()
->GetExtensionsToolbarContainer();
if (container) {
anchor_view = container->GetViewForId(extension_->id());
} else if (!base::FeatureList::IsEnabled(
features::kExtensionsToolbarMenu)) {
BrowserActionsContainer* const browser_actions_container =
browser_view_->toolbar_button_provider()
->GetBrowserActionsContainer();
ToolbarActionView* const reference_view =
browser_actions_container->GetViewForId(extension_->id());
if (reference_view && reference_view->GetVisible())
anchor_view = reference_view;
}
}
if (!anchor_view) {
anchor_view = browser_view_->toolbar_button_provider()
->GetDefaultExtensionDialogAnchorView();
}
SetAnchorView(anchor_view);
SetArrow(views::BubbleBorder::TOP_RIGHT);
}
void ImeWarningBubbleView::InitLayout() {
// The Ime warning bubble is like this:
//
// -----------------------------------------
// | Warning info |
// | |
// | [check box] Never show this again. |
// | |
// | -------- -------- |
// | |CANCEL| | OK | |
// | -------- -------- |
// -----------------------------------------
//
views::GridLayout* layout =
SetLayoutManager(std::make_unique<views::GridLayout>());
int cs_id = 0;
views::ColumnSet* main_cs = layout->AddColumnSet(cs_id);
// The first row which shows the warning info.
main_cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING,
views::GridLayout::kFixedSize,
views::GridLayout::ColumnSize::kFixed, kColumnWidth, 0);
ChromeLayoutProvider* provider = ChromeLayoutProvider::Get();
const int vertical_spacing =
provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL);
layout->StartRow(views::GridLayout::kFixedSize, cs_id);
base::string16 extension_name = base::UTF8ToUTF16(extension_->name());
base::i18n::AdjustStringForLocaleDirection(&extension_name);
std::unique_ptr<views::Label> warning =
CreateExtensionNameLabel(l10n_util::GetStringFUTF16(
IDS_IME_API_ACTIVATED_WARNING, extension_name));
layout->AddView(std::move(warning));
layout->AddPaddingRow(views::GridLayout::kFixedSize, vertical_spacing);
// The seconde row which shows the check box.
layout->StartRow(views::GridLayout::kFixedSize, cs_id);
never_show_checkbox_ = layout->AddView(std::make_unique<views::Checkbox>(
l10n_util::GetStringUTF16(IDS_IME_API_NEVER_SHOW)));
}
bool ImeWarningBubbleView::IsToolbarAnimating() {
DCHECK(!base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu));
return anchor_to_action_ &&
browser_view_->toolbar()->browser_actions()->animating();
}
// Copyright 2016 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 CHROME_BROWSER_UI_VIEWS_IME_IME_WARNING_BUBBLE_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_IME_IME_WARNING_BUBBLE_VIEW_H_
#include "base/macros.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
#include "chrome/browser/ui/toolbar/toolbar_actions_bar_observer.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
class BrowserView;
enum class ImeWarningBubblePermissionStatus;
namespace extensions {
class Extension;
}
namespace views {
class Checkbox;
}
using ImeWarningBubbleResponseCallback =
base::Callback<void(ImeWarningBubblePermissionStatus status)>;
// The implementation for the IME warning bubble. Provides warning information
// to the user upon the activation of an IME extension.
// The ImeWarningBubbleView is self-owned and deletes itself when it is closed
// or the parent browser is being destroyed.
class ImeWarningBubbleView : public views::BubbleDialogDelegateView,
public ToolbarActionsBarObserver,
public BrowserListObserver {
public:
static void ShowBubble(const extensions::Extension* extension,
BrowserView* browser_view,
const ImeWarningBubbleResponseCallback& callback);
// ToolbarActionsBarObserver:
void OnToolbarActionsBarAnimationEnded() override;
// BrowserListObserver:
void OnBrowserRemoved(Browser* browser) override;
private:
friend class ImeWarningBubbleTest;
static ImeWarningBubbleView* ime_warning_bubble_for_test_;
ImeWarningBubbleView(const extensions::Extension* extension,
BrowserView* browser_view,
const ImeWarningBubbleResponseCallback& callback);
~ImeWarningBubbleView() override;
// Recalculates the anchor position for this bubble.
void InitAnchorView();
// Intializes the layout for the bubble.
void InitLayout();
// Returns true if the action toolbar is animating.
bool IsToolbarAnimating();
const extensions::Extension* extension_;
BrowserView* const browser_view_;
// Saves the Browser instance of the browser view, which will be used in
// OnBrowserRemoved(), as browser_view_->browser() may be null when
// OnBrowserRemoved() is called.
Browser* const browser_;
// True if bubble anchors to the action of the extension.
bool anchor_to_action_ = false;
// The check box on the bubble view.
views::Checkbox* never_show_checkbox_ = nullptr;
ImeWarningBubbleResponseCallback response_callback_;
// True if the warning bubble has been shown.
bool bubble_has_shown_ = false;
ScopedObserver<ToolbarActionsBar, ToolbarActionsBarObserver>
toolbar_actions_bar_observer_{this};
base::WeakPtrFactory<ImeWarningBubbleView> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ImeWarningBubbleView);
};
#endif // CHROME_BROWSER_UI_VIEWS_IME_IME_WARNING_BUBBLE_VIEW_H_
// Copyright 2016 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 "base/run_loop.h"
#include "build/build_config.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/input_method/ime_native_window.h"
#include "chrome/browser/ui/input_method/ime_window.h"
#include "chrome/browser/ui/input_method/ime_window_observer.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "content/public/test/browser_test.h"
#include "ui/views/widget/widget.h"
namespace ui {
namespace test {
class ImeWindowBrowserTest : public InProcessBrowserTest,
public ImeWindowObserver {
public:
ImeWindowBrowserTest() : ime_window_(nullptr) {}
~ImeWindowBrowserTest() override {}
void TearDownOnMainThread() override {
if (ime_window_) {
ime_window_->Close();
WaitForWindowClosing();
ime_window_ = nullptr;
}
}
protected:
// ImeWindowObserver:
void OnWindowDestroyed(ImeWindow* ime_window) override {
message_loop_runner_->Quit();
}
void WaitForWindowClosing() {
message_loop_runner_ = std::make_unique<base::RunLoop>();
message_loop_runner_->Run();
}
void CreateImeWindow(const gfx::Rect& bounds, bool follow_cursor) {
ime_window_ = new ImeWindow(
browser()->profile(), nullptr, nullptr, "about:blank",
follow_cursor ? ImeWindow::FOLLOW_CURSOR : ImeWindow::NORMAL, bounds);
ime_window_->AddObserver(this);
EXPECT_FALSE(ime_window_->ime_native_window()->IsVisible());
ime_window_->Show();
EXPECT_TRUE(ime_window_->ime_native_window()->IsVisible());
}
void VerifyImeWindow(const gfx::Rect& expected_bounds) {
EXPECT_EQ(expected_bounds,
ime_window_->ime_native_window()->GetBounds());
EXPECT_GT(ime_window_->GetFrameId(), 0);
}
ImeWindow* ime_window_;
std::unique_ptr<base::RunLoop> message_loop_runner_;
DISALLOW_COPY_AND_ASSIGN(ImeWindowBrowserTest);
};
// https://crbug.com/919624 : Flaky on Win7 bots
#if defined(OS_WIN)
#define MAYBE_CreateNormalWindow DISABLED_CreateNormalWindow
#define MAYBE_CreateFollowCursorWindow DISABLED_CreateFollowCursorWindow
#else
#define MAYBE_CreateNormalWindow CreateNormalWindow
#define MAYBE_CreateFollowCursorWindow CreateFollowCursorWindow
#endif
IN_PROC_BROWSER_TEST_F(ImeWindowBrowserTest, MAYBE_CreateNormalWindow) {
gfx::Rect expected_bounds(100, 200, 300, 400);
CreateImeWindow(expected_bounds, false);
VerifyImeWindow(expected_bounds);
}
IN_PROC_BROWSER_TEST_F(ImeWindowBrowserTest, MAYBE_CreateFollowCursorWindow) {
gfx::Rect expected_bounds(100, 200, 300, 400);
CreateImeWindow(expected_bounds, true);
VerifyImeWindow(expected_bounds);
}
IN_PROC_BROWSER_TEST_F(ImeWindowBrowserTest, FollowCursor) {
gfx::Rect expected_bounds(100, 200, 100, 100);
CreateImeWindow(expected_bounds, true);
ime_window_->FollowCursor(gfx::Rect(50, 50, 1, 10));
expected_bounds.set_x(18); // cursor left - titlebar width(32).
expected_bounds.set_y(63); // cursor top + cursor height + margin(3).
VerifyImeWindow(expected_bounds);
}
} // namespace test
} // namespace ui
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/ime/ime_window_frame_view.h"
#include "chrome/browser/ui/views/ime/ime_window_view.h"
#include "chrome/grit/browser_resources.h"
#include "content/public/browser/web_contents.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/base/hit_test.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font_list.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/flex_layout.h"
#include "ui/views/view_class_properties.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
namespace ui {
ImeWindowFrameView::ImeWindowFrameView(ImeWindowView* ime_window_view,
ImeWindow::Mode mode)
: ime_window_view_(ime_window_view), mode_(mode) {}
ImeWindowFrameView::~ImeWindowFrameView() = default;
void ImeWindowFrameView::Init() {
auto* outer_layout = SetLayoutManager(std::make_unique<views::FlexLayout>());
auto* titlebar = AddChildView(std::make_unique<views::View>());
auto* titlebar_layout =
titlebar->SetLayoutManager(std::make_unique<views::FlexLayout>());
titlebar_layout->SetCrossAxisAlignment(views::LayoutAlignment::kCenter);
auto content = std::make_unique<views::View>();
content->SetProperty(
views::kFlexBehaviorKey,
views::FlexSpecification(views::MinimumFlexSizeRule::kPreferred,
views::MaximumFlexSizeRule::kUnbounded));
constexpr int kLeadingMarginDp = 8, kTrailingMarginDp = 6;
if (in_follow_cursor_mode()) {
titlebar->SetPreferredSize({kTitlebarHeight, 0});
titlebar_layout->SetOrientation(views::LayoutOrientation::kVertical)
.SetInteriorMargin({kLeadingMarginDp, 0, kTrailingMarginDp, 0});
content->SetBorder(views::CreateEmptyBorder(
{kImeBorderThickness, 0, kImeBorderThickness, kImeBorderThickness}));
} else {
outer_layout->SetOrientation(views::LayoutOrientation::kVertical);
titlebar->SetPreferredSize({0, kTitlebarHeight});
titlebar_layout->SetInteriorMargin(
{0, kLeadingMarginDp, 0, kTrailingMarginDp});
content->SetBorder(views::CreateEmptyBorder(
{0, kImeBorderThickness, kImeBorderThickness, kImeBorderThickness}));
}
content_ = AddChildView(std::move(content));
auto title_icon = std::make_unique<views::ImageView>();
title_icon->SetImage(ime_window_view_->GetWindowIcon());
title_icon->SetImageSize({16, 16});
title_icon->set_tooltip_text(ime_window_view_->GetWindowTitle());
title_icon->SetProperty(
views::kFlexBehaviorKey,
views::FlexSpecification(views::MinimumFlexSizeRule::kPreferred,
views::MaximumFlexSizeRule::kUnbounded)
.WithAlignment(views::LayoutAlignment::kStart));
title_icon_ = titlebar->AddChildView(std::move(title_icon));
if (!in_follow_cursor_mode()) {
auto close_button = std::make_unique<views::ImageButton>(this);
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
close_button->SetImage(views::Button::STATE_NORMAL,
rb.GetImageSkiaNamed(IDR_IME_WINDOW_CLOSE));
close_button->SetImage(views::Button::STATE_HOVERED,
rb.GetImageSkiaNamed(IDR_IME_WINDOW_CLOSE_H));
close_button->SetImage(views::Button::STATE_PRESSED,
rb.GetImageSkiaNamed(IDR_IME_WINDOW_CLOSE_C));
close_button->SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
close_button->SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
close_button->SetAccessibleName(
l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE));
close_button->SetProperty(
views::kFlexBehaviorKey,
views::FlexSpecification(views::MinimumFlexSizeRule::kPreferred,
views::MaximumFlexSizeRule::kUnbounded)
.WithAlignment(views::LayoutAlignment::kEnd));
close_button_ = titlebar->AddChildView(std::move(close_button));
}
}
void ImeWindowFrameView::UpdateIcon() {
UpdateWindowIcon();
}
gfx::Rect ImeWindowFrameView::GetBoundsForClientView() const {
return content_->ConvertRectToParent(content_->GetContentsBounds());
}
gfx::Rect ImeWindowFrameView::GetWindowBoundsForClientBounds(
const gfx::Rect& client_bounds) const {
// The window bounds include both client area and non-client area (titlebar
// and left, right and bottom borders).
if (in_follow_cursor_mode()) {
return gfx::Rect(
client_bounds.x() - kTitlebarHeight,
client_bounds.y() - kImeBorderThickness,
client_bounds.width() + kTitlebarHeight + kImeBorderThickness,
client_bounds.height() + kImeBorderThickness * 2);
}
return gfx::Rect(
client_bounds.x() - kImeBorderThickness,
client_bounds.y() - kTitlebarHeight,
client_bounds.width() + kImeBorderThickness * 2,
client_bounds.height() + kTitlebarHeight + kImeBorderThickness);
}
int ImeWindowFrameView::NonClientHitTest(const gfx::Point& point) {
int client_component =
ime_window_view_->window()->client_view()->NonClientHitTest(point);
if (client_component != HTNOWHERE)
return client_component;
return (close_button_ && close_button_->GetMirroredBounds().Contains(point))
? HTCLOSE
: HTNOWHERE;
}
void ImeWindowFrameView::GetWindowMask(const gfx::Size& size,
SkPath* window_mask) {
int width = size.width();
int height = size.height();
window_mask->moveTo(0, 0);
window_mask->lineTo(SkIntToScalar(width), 0);
window_mask->lineTo(SkIntToScalar(width), SkIntToScalar(height));
window_mask->lineTo(0, SkIntToScalar(height));
window_mask->close();
}
void ImeWindowFrameView::ResetWindowControls() {}
void ImeWindowFrameView::UpdateWindowIcon() {
title_icon_->SchedulePaint();
}
void ImeWindowFrameView::UpdateWindowTitle() {}
void ImeWindowFrameView::SizeConstraintsChanged() {}
gfx::Size ImeWindowFrameView::CalculatePreferredSize() const {
gfx::Size pref_size =
ime_window_view_->window()->client_view()->GetPreferredSize();
gfx::Rect bounds(0, 0, pref_size.width(), pref_size.height());
return ime_window_view_->window()
->non_client_view()
->GetWindowBoundsForClientBounds(bounds)
.size();
}
gfx::Size ImeWindowFrameView::GetMinimumSize() const {
return ime_window_view_->GetMinimumSize();
}
gfx::Size ImeWindowFrameView::GetMaximumSize() const {
return ime_window_view_->GetMaximumSize();
}
void ImeWindowFrameView::OnPaint(gfx::Canvas* canvas) {
PaintFrameBackground(canvas);
}
bool ImeWindowFrameView::OnMousePressed(const ui::MouseEvent& event) {
if (event.IsOnlyLeftMouseButton()) {
gfx::Point mouse_location = event.location();
views::View::ConvertPointToScreen(this, &mouse_location);
return ime_window_view_->OnTitlebarPointerPressed(
mouse_location, ImeWindowView::PointerType::MOUSE);
}
return false;
}
bool ImeWindowFrameView::OnMouseDragged(const ui::MouseEvent& event) {
gfx::Point mouse_location = event.location();
views::View::ConvertPointToScreen(this, &mouse_location);
return ime_window_view_->OnTitlebarPointerDragged(
mouse_location, ImeWindowView::PointerType::MOUSE);
}
void ImeWindowFrameView::OnMouseReleased(const ui::MouseEvent& event) {
ime_window_view_->OnTitlebarPointerReleased(
ImeWindowView::PointerType::MOUSE);
}
void ImeWindowFrameView::OnMouseCaptureLost() {
ime_window_view_->OnTitlebarPointerCaptureLost();
}
void ImeWindowFrameView::OnGestureEvent(ui::GestureEvent* event) {
bool handled = false;
switch (event->type()) {
case ui::ET_GESTURE_TAP_DOWN: {
gfx::Point loc(event->location());
views::View::ConvertPointToScreen(this, &loc);
handled = ime_window_view_->OnTitlebarPointerPressed(
loc, ImeWindowView::PointerType::TOUCH);
break;
}
case ui::ET_GESTURE_SCROLL_UPDATE: {
gfx::Point loc(event->location());
views::View::ConvertPointToScreen(this, &loc);
handled = ime_window_view_->OnTitlebarPointerDragged(
loc, ImeWindowView::PointerType::TOUCH);
break;
}
case ui::ET_GESTURE_END:
ime_window_view_->OnTitlebarPointerReleased(
ImeWindowView::PointerType::TOUCH);
handled = true;
break;
default:
break;
}
if (handled)
event->SetHandled();
}
void ImeWindowFrameView::ButtonPressed(views::Button* sender,
const ui::Event& event) {
DCHECK_EQ(close_button_, sender);
ime_window_view_->OnCloseButtonClicked();
}
void ImeWindowFrameView::PaintFrameBackground(gfx::Canvas* canvas) {
canvas->DrawColor(kImeBackgroundColor);
// left border.
canvas->FillRect(gfx::Rect(0, 0, kImeBorderThickness, height()),
kBorderColor);
// top border.
canvas->FillRect(gfx::Rect(0, 0, width(), kImeBorderThickness), kBorderColor);
// right border.
canvas->FillRect(gfx::Rect(width() - kImeBorderThickness, 0,
kImeBorderThickness, height()),
kBorderColor);
// bottom border.
canvas->FillRect(gfx::Rect(0, height() - kImeBorderThickness, width(),
kImeBorderThickness),
kBorderColor);
}
} // namespace ui
// Copyright 2016 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 CHROME_BROWSER_UI_VIEWS_IME_IME_WINDOW_FRAME_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_IME_IME_WINDOW_FRAME_VIEW_H_
#include "chrome/browser/ui/input_method/ime_window.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/window/non_client_view.h"
namespace views {
class ImageButton;
class ImageView;
}
namespace ui {
class ImeWindowView;
// The non-client frame view implementation for the IME window UI.
class ImeWindowFrameView : public views::NonClientFrameView,
public views::ButtonListener {
public:
// According to the UX spec, the follow-cursor window needs to have the title
// bar on the side instead of on the top (because the follow-cursor window is
// majorly used as suggestion list which can be shown in horizontal).
// TODO(shuchen): locate the title bar on the right in the RTL case.
ImeWindowFrameView(ImeWindowView* ime_window_view,
ImeWindow::Mode mode);
~ImeWindowFrameView() override;
void Init();
void UpdateIcon();
private:
static constexpr int kImeBorderThickness = 1;
static constexpr int kTitlebarHeight = 32;
// Colors used to draw border, titlebar background and title text.
static constexpr SkColor kImeBackgroundColor =
SkColorSetRGB(0xec, 0xef, 0xf1);
static constexpr SkColor kBorderColor = SkColorSetRGB(0xda, 0xdf, 0xe1);
// views::NonClientFrameView:
gfx::Rect GetBoundsForClientView() const override;
gfx::Rect GetWindowBoundsForClientBounds(
const gfx::Rect& client_bounds) const override;
int NonClientHitTest(const gfx::Point& point) override;
void GetWindowMask(const gfx::Size& size, SkPath* window_mask) override;
void ResetWindowControls() override;
void UpdateWindowIcon() override;
void UpdateWindowTitle() override;
void SizeConstraintsChanged() override;
// views::View:
gfx::Size CalculatePreferredSize() const override;
gfx::Size GetMinimumSize() const override;
gfx::Size GetMaximumSize() const override;
void OnPaint(gfx::Canvas* canvas) override;
bool OnMousePressed(const ui::MouseEvent& event) override;
bool OnMouseDragged(const ui::MouseEvent& event) override;
void OnMouseReleased(const ui::MouseEvent& event) override;
void OnMouseCaptureLost() override;
void OnGestureEvent(ui::GestureEvent* event) override;
// views::ButtonListener:
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
// Update control styles to indicate if the titlebar is active or not.
void UpdateControlStyles();
// Custom draw the frame.
void PaintFrameBackground(gfx::Canvas* canvas);
bool in_follow_cursor_mode() const {
return mode_ == ImeWindow::FOLLOW_CURSOR;
}
ImeWindowView* const ime_window_view_;
const ImeWindow::Mode mode_;
views::ImageButton* close_button_ = nullptr;
views::ImageView* title_icon_ = nullptr;
views::View* content_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(ImeWindowFrameView);
};
} // namespace ui
#endif // CHROME_BROWSER_UI_VIEWS_IME_IME_WINDOW_FRAME_VIEW_H_
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/views/ime/ime_window_view.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/input_method/ime_window.h"
#include "chrome/browser/ui/views/ime/ime_window_frame_view.h"
#include "content/public/browser/web_contents.h"
#include "ui/gfx/image/image.h"
#include "ui/views/controls/webview/webview.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/widget/widget.h"
#if defined(OS_WIN)
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
#endif
namespace ui {
ImeNativeWindow* ImeWindow::CreateNativeWindow(ImeWindow* ime_window,
const gfx::Rect& bounds,
content::WebContents* contents) {
return new ImeWindowView(ime_window, bounds, contents);
}
ImeWindowView::ImeWindowView(ImeWindow* ime_window,
const gfx::Rect& bounds,
content::WebContents* contents)
: ime_window_(ime_window),
dragging_pointer_type_(PointerType::MOUSE),
dragging_state_(DragState::NO_DRAG),
window_(nullptr),
web_view_(nullptr) {
SetCanActivate(false);
SetTitle(base::UTF8ToUTF16(ime_window_->title()));
window_ = new views::Widget;
views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
params.delegate = this;
params.wants_mouse_events_when_inactive = true;
params.remove_standard_frame = false;
params.z_order = ui::ZOrderLevel::kFloatingWindow;
params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
params.visible_on_all_workspaces = false;
params.bounds = bounds;
window_->set_focus_on_creation(false);
window_->set_frame_type(views::Widget::FrameType::kForceCustom);
window_->Init(std::move(params));
window_->UpdateWindowTitle();
UpdateWindowIcon();
web_view_ = new views::WebView(nullptr);
web_view_->SetWebContents(contents);
web_view_->SetFocusBehavior(FocusBehavior::NEVER);
AddChildView(web_view_);
SetLayoutManager(std::make_unique<views::FillLayout>());
Layout();
// TODO(shuchen): supports auto cursor/composition aligning for
// follow-cursor window.
}
ImeWindowView::~ImeWindowView() {}
void ImeWindowView::Show() {
window_->ShowInactive();
}
void ImeWindowView::Hide() {
window_->Hide();
}
void ImeWindowView::Close() {
window_->Close();
}
void ImeWindowView::SetBounds(const gfx::Rect& bounds) {
window_->SetBounds(bounds);
}
gfx::Rect ImeWindowView::GetBounds() const {
return GetWidget()->GetWindowBoundsInScreen();
}
void ImeWindowView::UpdateWindowIcon() {
SetIcon(ime_window_->icon() ? ime_window_->icon()->image_skia()
: gfx::ImageSkia());
window_->UpdateWindowIcon();
}
bool ImeWindowView::IsVisible() const {
return GetWidget()->IsVisible();
}
void ImeWindowView::OnCloseButtonClicked() {
ime_window_->Close();
}
bool ImeWindowView::OnTitlebarPointerPressed(
const gfx::Point& pointer_location, PointerType pointer_type) {
if (dragging_state_ != DragState::NO_DRAG &&
dragging_pointer_type_ != pointer_type) {
return false;
}
dragging_state_ = DragState::POSSIBLE_DRAG;
pointer_location_on_press_ = pointer_location;
dragging_pointer_type_ = pointer_type;
return true;
}
bool ImeWindowView::OnTitlebarPointerDragged(
const gfx::Point& pointer_location, PointerType pointer_type) {
if (dragging_state_ == DragState::NO_DRAG)
return false;
if (dragging_pointer_type_ != pointer_type)
return false;
if (dragging_state_ == DragState::POSSIBLE_DRAG &&
ExceededDragThreshold(pointer_location - pointer_location_on_press_)) {
gfx::Rect bounds = GetWidget()->GetWindowBoundsInScreen();
bounds_on_drag_start_ = bounds;
dragging_state_ = DragState::ACTIVE_DRAG;
}
if (dragging_state_ == DragState::ACTIVE_DRAG) {
gfx::Point target_position = pointer_location -
(pointer_location_on_press_ - bounds_on_drag_start_.origin());
gfx::Rect bounds = GetWidget()->GetWindowBoundsInScreen();
bounds.set_origin(target_position);
GetWidget()->SetBounds(bounds);
}
return true;
}
void ImeWindowView::OnTitlebarPointerReleased(PointerType pointer_type) {
if (dragging_pointer_type_ == pointer_type &&
dragging_state_ == DragState::ACTIVE_DRAG) {
EndDragging();
}
}
void ImeWindowView::OnTitlebarPointerCaptureLost() {
if (dragging_state_ == DragState::ACTIVE_DRAG) {
GetWidget()->SetBounds(bounds_on_drag_start_);
EndDragging();
}
}
views::NonClientFrameView* ImeWindowView::CreateNonClientFrameView(
views::Widget* widget) {
ImeWindowFrameView* frame_view = new ImeWindowFrameView(
this, ime_window_->mode());
frame_view->Init();
return frame_view;
}
void ImeWindowView::DeleteDelegate() {
ime_window_->OnWindowDestroyed();
delete this;
}
ImeWindowFrameView* ImeWindowView::GetFrameView() const {
return static_cast<ImeWindowFrameView*>(
window_->non_client_view()->frame_view());
}
void ImeWindowView::EndDragging() {
dragging_state_ = DragState::NO_DRAG;
}
} // namespace ui
// Copyright 2016 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 CHROME_BROWSER_UI_VIEWS_IME_IME_WINDOW_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_IME_IME_WINDOW_VIEW_H_
#include <memory>
#include <string>
#include "base/strings/string16.h"
#include "chrome/browser/ui/input_method/ime_native_window.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/web_contents_observer.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/image/image.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/widget/widget_observer.h"
namespace views {
class WebView;
}
namespace ui {
class ImeWindow;
class ImeWindowFrameView;
// The views implementation for the IME window UI.
// This interacts with ImeWindow through the ImeNativeWindow interface.
class ImeWindowView : public ImeNativeWindow,
public views::WidgetDelegateView {
public:
enum class PointerType { MOUSE, TOUCH };
ImeWindowView(ImeWindow* ime_window,
const gfx::Rect& bounds,
content::WebContents* contents);
~ImeWindowView() override;
void OnCloseButtonClicked();
// Methods to deal with mouse/touch dragging on the non client view.
bool OnTitlebarPointerPressed(const gfx::Point& pointer_location,
PointerType pointer_type);
bool OnTitlebarPointerDragged(const gfx::Point& pointer_location,
PointerType pointer_type);
void OnTitlebarPointerReleased(PointerType pointer_type);
void OnTitlebarPointerCaptureLost();
// ui::ImeNativeWindow:
void Show() override;
void Hide() override;
void Close() override;
void SetBounds(const gfx::Rect& bounds) override;
gfx::Rect GetBounds() const override;
void UpdateWindowIcon() override;
bool IsVisible() const override;
// views::WidgetDelegateView:
views::NonClientFrameView* CreateNonClientFrameView(
views::Widget* widget) override;
void DeleteDelegate() override;
ImeWindowFrameView* GetFrameView() const;
views::Widget* window() const { return window_; }
views::WebView* web_view() const { return web_view_; }
private:
enum class DragState { NO_DRAG, POSSIBLE_DRAG, ACTIVE_DRAG };
void EndDragging();
ImeWindow* ime_window_;
// Member variables for dragging.
PointerType dragging_pointer_type_;
gfx::Point pointer_location_on_press_;
DragState dragging_state_;
gfx::Rect bounds_on_drag_start_;
// The native window.
views::Widget* window_;
// The web view control which hosts the web contents.
views::WebView* web_view_;
DISALLOW_COPY_AND_ASSIGN(ImeWindowView);
};
} // namespace ui
#endif // CHROME_BROWSER_UI_VIEWS_IME_IME_WINDOW_VIEW_H_
// Copyright 2016 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 "base/auto_reset.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/test/browser_test.h"
#include "extensions/test/extension_test_message_listener.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/ime/composition_text.h"
#include "ui/base/ime/dummy_text_input_client.h"
#include "ui/base/ime/input_method.h"
namespace extensions {
class InputImeApiTest : public ExtensionApiTest {
public:
InputImeApiTest() {}
protected:
// Sets the private flag of |track_key_events_for_testing_| in InputMethod.
void SetTrackKeyEvents(ui::InputMethod* input_method, bool track) {
input_method->track_key_events_for_testing_ = track;
}
// Returns true if the key events get from input method equals to the expected
// key events.
bool CompareKeyEvents(
const std::vector<std::unique_ptr<ui::KeyEvent>>& expected_key_events,
ui::InputMethod* input_method) {
if (expected_key_events.size() != GetKeyEvents(input_method).size())
return false;
for (size_t i = 0; i < expected_key_events.size(); i++) {
ui::KeyEvent* event1 = expected_key_events[i].get();
ui::KeyEvent* event2 = GetKeyEvents(input_method)[i].get();
if (event1->type() != event2->type() ||
event1->key_code() != event2->key_code() ||
event1->flags() != event2->flags()) {
return false;
}
}
return true;
}
private:
// Returns the tracked key events of using input.ime.sendKeyEvents API.
const std::vector<std::unique_ptr<ui::KeyEvent>>& GetKeyEvents(
ui::InputMethod* input_method) {
return input_method->GetKeyEventsForTesting();
}
DISALLOW_COPY_AND_ASSIGN(InputImeApiTest);
};
// TODO(crbug.com/882338) This test fails basically once per try run.
// See bug for details.
IN_PROC_BROWSER_TEST_F(InputImeApiTest, DISABLED_BasicApiTest) {
// Manipulates the focused text input client because the follow cursor
// window requires the text input focus.
ui::InputMethod* input_method =
browser()->window()->GetNativeWindow()->GetHost()->GetInputMethod();
std::unique_ptr<ui::DummyTextInputClient> client(
new ui::DummyTextInputClient(ui::TEXT_INPUT_TYPE_TEXT));
input_method->SetFocusedTextInputClient(client.get());
ExtensionFunction::ScopedUserGestureForTests scoped_user_gesture;
base::AutoReset<bool> auto_reset_disable_bubble(
&InputImeActivateFunction::disable_bubble_for_testing_, true);
SetTrackKeyEvents(input_method, true);
// Listens for the input.ime.onBlur event.
ExtensionTestMessageListener blur_listener("get_blur_event", false);
ASSERT_TRUE(RunExtensionTest("input_ime_nonchromeos")) << message_;
// Test the input.ime.commitText API.
const std::vector<base::string16>& insert_text_history =
client->insert_text_history();
ASSERT_EQ(1UL, insert_text_history.size());
EXPECT_EQ(base::UTF8ToUTF16("test_commit_text"), insert_text_history[0]);
// Test the input.ime.setComposition API.
ui::CompositionText composition;
composition.text = base::UTF8ToUTF16("test_set_composition");
composition.ime_text_spans.push_back(ui::ImeTextSpan(
ui::ImeTextSpan::Type::kComposition, 0, composition.text.length(),
ui::ImeTextSpan::Thickness::kThin,
ui::ImeTextSpan::UnderlineStyle::kSolid, SK_ColorTRANSPARENT));
composition.selection = gfx::Range(2, 2);
const std::vector<ui::CompositionText>& composition_history =
client->composition_history();
ASSERT_EQ(2UL, composition_history.size());
EXPECT_EQ(base::UTF8ToUTF16("test_set_composition"),
composition_history[0].text);
EXPECT_EQ(base::UTF8ToUTF16(""), composition_history[1].text);
// Tests input.ime.onBlur API should get event when focusing to another
// text input client.
std::unique_ptr<ui::DummyTextInputClient> client2(
new ui::DummyTextInputClient(ui::TEXT_INPUT_TYPE_TEXT));
input_method->SetFocusedTextInputClient(client2.get());
ASSERT_TRUE(blur_listener.WaitUntilSatisfied()) << message_;
input_method->DetachTextInputClient(client2.get());
}
// The following test verifies that key events do not get sent on any page.
// This is in preparation of deprecating the sendKeyEvents API.
// TODO(crbug.com/1004628) Flakes on Windows and Linux
IN_PROC_BROWSER_TEST_F(InputImeApiTest, DISABLED_SendKeyEventsOnNormalPage) {
// Navigates to special page that sendKeyEvents API has limitation with.
ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL));
// Manipulates the focused text input client because the follow cursor
// window requires the text input focus.
ui::InputMethod* input_method =
browser()->window()->GetNativeWindow()->GetHost()->GetInputMethod();
std::unique_ptr<ui::DummyTextInputClient> client(
new ui::DummyTextInputClient(ui::TEXT_INPUT_TYPE_TEXT));
input_method->SetFocusedTextInputClient(client.get());
ExtensionFunction::ScopedUserGestureForTests scoped_user_gesture;
base::AutoReset<bool> auto_reset_disable_bubble(
&InputImeActivateFunction::disable_bubble_for_testing_, true);
SetTrackKeyEvents(input_method, true);
ASSERT_TRUE(RunExtensionTest("input_ime_nonchromeos")) << message_;
std::vector<std::unique_ptr<ui::KeyEvent>> key_events;
EXPECT_TRUE(CompareKeyEvents(key_events, input_method));
input_method->DetachTextInputClient(client.get());
}
// The following test verifies that key events do not get sent on any page.
// This is in preparation of deprecating the sendKeyEvents API.
// TODO(https://crbug.com/795631): This test is failing on the Linux bot.
// TODO(https://crbug.com/795631): This testis failing on Windows bot.
IN_PROC_BROWSER_TEST_F(InputImeApiTest, DISABLED_SendKeyEventsOnSpecialPage) {
// Navigates to special page that sendKeyEvents API has limitation with.
ui_test_utils::NavigateToURL(browser(), GURL("chrome://flags"));
ui::InputMethod* input_method =
browser()->window()->GetNativeWindow()->GetHost()->GetInputMethod();
std::unique_ptr<ui::DummyTextInputClient> client(
new ui::DummyTextInputClient(ui::TEXT_INPUT_TYPE_TEXT));
input_method->SetFocusedTextInputClient(client.get());
ExtensionFunction::ScopedUserGestureForTests scoped_user_gesture;
base::AutoReset<bool> auto_reset_disable_bubble(
&InputImeActivateFunction::disable_bubble_for_testing_, true);
SetTrackKeyEvents(input_method, true);
ASSERT_TRUE(RunExtensionTest("input_ime_nonchromeos")) << message_;
std::vector<std::unique_ptr<ui::KeyEvent>> key_events;
EXPECT_TRUE(CompareKeyEvents(key_events, input_method));
input_method->DetachTextInputClient(client.get());
}
} // namespace extensions
...@@ -102,36 +102,6 @@ ...@@ -102,36 +102,6 @@
"type": "string", "type": "string",
"description": "Which mouse buttons was clicked.", "description": "Which mouse buttons was clicked.",
"enum": ["left", "middle", "right"] "enum": ["left", "middle", "right"]
},
{
"id": "WindowType",
"type": "string",
"description": "The IME window types.",
"platforms": ["win", "linux"],
"enum": ["normal", "followCursor"]
},
{
"id": "Bounds",
"type": "object",
"description": "Describes the screen coordinates of a rect.",
"platforms": ["win", "linux"],
"properties": {
"left": {"type": "integer", "description": "The left of the bounds."},
"top": {"type": "integer", "description": "The top of the bounds."},
"width": {"type": "integer", "description": "The width of the bounds." },
"height": {"type": "integer", "description": "The height of the bounds ."}
}
},
{
"id": "CreateWindowOptions",
"type": "object",
"description": "The options to create an IME window",
"platforms": ["win", "linux"],
"properties": {
"windowType": {"$ref": "WindowType"},
"url": {"type": "string", "optional": true},
"bounds": {"$ref": "Bounds", "optional": true}
}
} }
], ],
"functions": [ "functions": [
...@@ -139,7 +109,7 @@ ...@@ -139,7 +109,7 @@
"name": "setComposition", "name": "setComposition",
"type": "function", "type": "function",
"description": "Set the current composition. If this extension does not own the active IME, this fails.", "description": "Set the current composition. If this extension does not own the active IME, this fails.",
"platforms": ["chromeos", "win", "linux"], "platforms": ["chromeos"],
"parameters": [ "parameters": [
{ {
"name": "parameters", "name": "parameters",
...@@ -239,7 +209,7 @@ ...@@ -239,7 +209,7 @@
"name": "commitText", "name": "commitText",
"type": "function", "type": "function",
"description": "Commits the provided text to the current input.", "description": "Commits the provided text to the current input.",
"platforms": ["chromeos", "win", "linux"], "platforms": ["chromeos"],
"parameters": [ "parameters": [
{ {
"name": "parameters", "name": "parameters",
...@@ -273,7 +243,7 @@ ...@@ -273,7 +243,7 @@
"name": "sendKeyEvents", "name": "sendKeyEvents",
"type": "function", "type": "function",
"description": "Sends the key events. This function is expected to be used by virtual keyboards. When key(s) on a virtual keyboard is pressed by a user, this function is used to propagate that event to the system.", "description": "Sends the key events. This function is expected to be used by virtual keyboards. When key(s) on a virtual keyboard is pressed by a user, this function is used to propagate that event to the system.",
"platforms": ["chromeos", "win", "linux"], "platforms": ["chromeos"],
"parameters": [ "parameters": [
{ {
"name": "parameters", "name": "parameters",
...@@ -581,107 +551,11 @@ ...@@ -581,107 +551,11 @@
"name": "keyEventHandled", "name": "keyEventHandled",
"type": "function", "type": "function",
"description": "Indicates that the key event received by onKeyEvent is handled. This should only be called if the onKeyEvent listener is asynchronous.", "description": "Indicates that the key event received by onKeyEvent is handled. This should only be called if the onKeyEvent listener is asynchronous.",
"platforms": ["chromeos", "win", "linux"], "platforms": ["chromeos"],
"parameters": [ "parameters": [
{"type": "string", "name": "requestId", "description": "Request id of the event that was handled. This should come from keyEvent.requestId"}, {"type": "string", "name": "requestId", "description": "Request id of the event that was handled. This should come from keyEvent.requestId"},
{"type": "boolean", "name": "response", "description": "True if the keystroke was handled, false if not"} {"type": "boolean", "name": "response", "description": "True if the keystroke was handled, false if not"}
] ]
},
{
"name": "createWindow",
"type": "function",
"description": "Creates IME window.",
"platforms": ["win", "linux"],
"parameters": [
{
"$ref": "CreateWindowOptions",
"name": "options",
"description": "The options of the newly created IME window."
},
{
"type": "function",
"name": "callback",
"description": "Called when the operation completes.",
"parameters": [
{
"name": "windowObject",
"type": "object",
"isInstanceOf": "Window",
"description": "The JavaScript 'window' object of the newly created IME window. It contains the additional 'id' property for the parameters of the other functions like showWindow/hideWindow."
}
]
}
]
},
{
"name": "showWindow",
"type": "function",
"description": "Shows the IME window. This makes the hidden window visible.",
"platforms": ["win", "linux"],
"parameters": [
{
"type": "integer",
"name": "windowId",
"description": "The ID of the IME window."
},
{
"type": "function",
"name": "callback",
"optional": true,
"description": "Called when the operation completes.",
"parameters": []
}
]
},
{
"name": "hideWindow",
"type": "function",
"description": "Hides the IME window. This doesn't close the window. Instead, it makes the window invisible. The extension can cache the window and show/hide it for better performance.",
"platforms": ["win", "linux"],
"parameters": [
{
"type": "integer",
"name": "windowId",
"description": "The ID of the IME window."
},
{
"type": "function",
"name": "callback",
"optional": true,
"description": "Called when the operation completes.",
"parameters": []
}
]
},
{
"name": "activate",
"type": "function",
"description": "Activates the IME extension so that it can receive events.",
"platforms": ["win", "linux"],
"parameters": [
{
"type": "function",
"name": "callback",
"optional": true,
"description": "Called when the operation completes.",
"parameters": []
}
]
},
{
"name": "deactivate",
"type": "function",
"description": "Deactivates the IME extension so that it cannot receive events.",
"platforms": ["win", "linux"],
"parameters": [
{
"type": "function",
"name": "callback",
"optional": true,
"description": "Called when the operation completes.",
"parameters": []
}
]
} }
], ],
"events": [ "events": [
...@@ -689,7 +563,7 @@ ...@@ -689,7 +563,7 @@
"name": "onActivate", "name": "onActivate",
"type": "function", "type": "function",
"description": "This event is sent when an IME is activated. It signals that the IME will be receiving onKeyPress events.", "description": "This event is sent when an IME is activated. It signals that the IME will be receiving onKeyPress events.",
"platforms": ["chromeos", "win", "linux"], "platforms": ["chromeos"],
"parameters": [ "parameters": [
{ {
"type": "string", "type": "string",
...@@ -707,7 +581,7 @@ ...@@ -707,7 +581,7 @@
"name": "onDeactivated", "name": "onDeactivated",
"type": "function", "type": "function",
"description": "This event is sent when an IME is deactivated. It signals that the IME will no longer be receiving onKeyPress events.", "description": "This event is sent when an IME is deactivated. It signals that the IME will no longer be receiving onKeyPress events.",
"platforms": ["chromeos", "win", "linux"], "platforms": ["chromeos"],
"parameters": [ "parameters": [
{ {
"type": "string", "type": "string",
...@@ -720,7 +594,7 @@ ...@@ -720,7 +594,7 @@
"name": "onFocus", "name": "onFocus",
"type": "function", "type": "function",
"description": "This event is sent when focus enters a text box. It is sent to all extensions that are listening to this event, and enabled by the user.", "description": "This event is sent when focus enters a text box. It is sent to all extensions that are listening to this event, and enabled by the user.",
"platforms": ["chromeos", "win", "linux"], "platforms": ["chromeos"],
"parameters": [ "parameters": [
{ {
"$ref": "InputContext", "$ref": "InputContext",
...@@ -733,7 +607,7 @@ ...@@ -733,7 +607,7 @@
"name": "onBlur", "name": "onBlur",
"type": "function", "type": "function",
"description": "This event is sent when focus leaves a text box. It is sent to all extensions that are listening to this event, and enabled by the user.", "description": "This event is sent when focus leaves a text box. It is sent to all extensions that are listening to this event, and enabled by the user.",
"platforms": ["chromeos", "win", "linux"], "platforms": ["chromeos"],
"parameters": [ "parameters": [
{ {
"type": "integer", "type": "integer",
...@@ -759,7 +633,7 @@ ...@@ -759,7 +633,7 @@
"name": "onKeyEvent", "name": "onKeyEvent",
"type": "function", "type": "function",
"description": "Fired when a key event is sent from the operating system. The event will be sent to the extension if this extension owns the active IME. The listener function should return true if the event was handled false if it was not. If the event will be evaluated asynchronously, this function must return undefined and the IME must later call keyEventHandled() with the result.", "description": "Fired when a key event is sent from the operating system. The event will be sent to the extension if this extension owns the active IME. The listener function should return true if the event was handled false if it was not. If the event will be evaluated asynchronously, this function must return undefined and the IME must later call keyEventHandled() with the result.",
"platforms": ["chromeos", "win", "linux"], "platforms": ["chromeos"],
"options": { "options": {
"supportsFilters": false, "supportsFilters": false,
"supportsListeners": true, "supportsListeners": true,
...@@ -870,7 +744,7 @@ ...@@ -870,7 +744,7 @@
"name": "onReset", "name": "onReset",
"type": "function", "type": "function",
"description": "This event is sent when chrome terminates ongoing text input session.", "description": "This event is sent when chrome terminates ongoing text input session.",
"platforms": ["chromeos", "win", "linux"], "platforms": ["chromeos"],
"parameters": [ "parameters": [
{ {
"type": "string", "type": "string",
...@@ -878,20 +752,6 @@ ...@@ -878,20 +752,6 @@
"description": "ID of the engine receiving the event" "description": "ID of the engine receiving the event"
} }
] ]
},
{
"name": "onCompositionBoundsChanged",
"type": "function",
"description": "Triggered when the bounds of the IME composition text or cursor are changed. The IME composition text is the instance of text produced in the input method editor.",
"platforms": ["win", "linux"],
"parameters": [
{
"type": "array",
"name": "boundsList",
"description": "List of bounds information for each character on IME composition text. If there's no composition text in the editor, this array contains the bound information of the cursor.",
"items": { "$ref": "Bounds" }
}
]
} }
] ]
} }
......
...@@ -1577,11 +1577,6 @@ if (!is_android) { ...@@ -1577,11 +1577,6 @@ if (!is_android) {
if (enable_nacl_nonsfi) { if (enable_nacl_nonsfi) {
data_deps += [ "//components/nacl/loader:helper_nonsfi" ] data_deps += [ "//components/nacl/loader:helper_nonsfi" ]
} }
} else if (is_linux || is_win) {
sources += [
"../browser/ui/views/ime/ime_warning_bubble_browsertest.cc",
"../browser/ui/views/ime/ime_window_browsertest.cc",
]
} }
if (is_win || is_linux) { if (is_win || is_linux) {
...@@ -2526,10 +2521,6 @@ if (!is_android) { ...@@ -2526,10 +2521,6 @@ if (!is_android) {
"../browser/ui/views/select_file_dialog_extension_browsertest.cc", "../browser/ui/views/select_file_dialog_extension_browsertest.cc",
] ]
} }
if (is_win || is_linux) {
sources +=
[ "../browser/ui/views/ime/input_ime_apitest_nonchromeos.cc" ]
}
} }
if (enable_kaleidoscope) { if (enable_kaleidoscope) {
deps += [ "../browser/media/kaleidoscope/internal:browser_tests_js" ] deps += [ "../browser/media/kaleidoscope/internal:browser_tests_js" ]
...@@ -4943,7 +4934,6 @@ test("unit_tests") { ...@@ -4943,7 +4934,6 @@ test("unit_tests") {
if (!is_chromeos && is_linux) { if (!is_chromeos && is_linux) {
sources += [ sources += [
"../browser/shell_integration_linux_unittest.cc", "../browser/shell_integration_linux_unittest.cc",
"../browser/ui/input_method/input_method_engine_unittest.cc",
"../browser/upgrade_detector/get_installed_version_linux_unittest.cc", "../browser/upgrade_detector/get_installed_version_linux_unittest.cc",
] ]
} }
...@@ -5270,7 +5260,6 @@ test("unit_tests") { ...@@ -5270,7 +5260,6 @@ test("unit_tests") {
sources += [ sources += [
"../browser/notifications/win/notification_image_retainer_unittest.cc", "../browser/notifications/win/notification_image_retainer_unittest.cc",
"../browser/notifications/win/notification_template_builder_unittest.cc", "../browser/notifications/win/notification_template_builder_unittest.cc",
"../browser/ui/input_method/input_method_engine_unittest.cc",
"../browser/ui/views/uninstall_view_unittest.cc", "../browser/ui/views/uninstall_view_unittest.cc",
] ]
deps += [ deps += [
......
...@@ -185,10 +185,6 @@ class TestBrowserWindow : public BrowserWindow { ...@@ -185,10 +185,6 @@ class TestBrowserWindow : public BrowserWindow {
void ExecuteExtensionCommand(const extensions::Extension* extension, void ExecuteExtensionCommand(const extensions::Extension* extension,
const extensions::Command& command) override; const extensions::Command& command) override;
ExclusiveAccessContext* GetExclusiveAccessContext() override; ExclusiveAccessContext* GetExclusiveAccessContext() override;
void ShowImeWarningBubble(
const extensions::Extension* extension,
const base::Callback<void(ImeWarningBubblePermissionStatus status)>&
callback) override {}
std::string GetWorkspace() const override; std::string GetWorkspace() const override;
bool IsVisibleOnAllWorkspaces() const override; bool IsVisibleOnAllWorkspaces() const override;
void ShowEmojiPanel() override {} void ShowEmojiPanel() override {}
......
...@@ -31,6 +31,11 @@ ...@@ -31,6 +31,11 @@
namespace ui { namespace ui {
ui::IMEEngineHandlerInterface* GetEngine() {
auto* bridge = ui::IMEBridge::Get();
return bridge ? bridge->GetCurrentEngineHandler() : nullptr;
}
// InputMethodChromeOS implementation ----------------------------------------- // InputMethodChromeOS implementation -----------------------------------------
InputMethodChromeOS::InputMethodChromeOS( InputMethodChromeOS::InputMethodChromeOS(
internal::InputMethodDelegate* delegate) internal::InputMethodDelegate* delegate)
......
...@@ -18,11 +18,6 @@ ...@@ -18,11 +18,6 @@
namespace ui { namespace ui {
ui::IMEEngineHandlerInterface* InputMethodBase::GetEngine() {
auto* bridge = ui::IMEBridge::Get();
return bridge ? bridge->GetCurrentEngineHandler() : nullptr;
}
InputMethodBase::InputMethodBase(internal::InputMethodDelegate* delegate) InputMethodBase::InputMethodBase(internal::InputMethodDelegate* delegate)
: InputMethodBase(delegate, nullptr) {} : InputMethodBase(delegate, nullptr) {}
......
...@@ -134,8 +134,6 @@ class COMPONENT_EXPORT(UI_BASE_IME) InputMethodBase ...@@ -134,8 +134,6 @@ class COMPONENT_EXPORT(UI_BASE_IME) InputMethodBase
internal::InputMethodDelegate* delegate() const { return delegate_; } internal::InputMethodDelegate* delegate() const { return delegate_; }
static IMEEngineHandlerInterface* GetEngine();
private: private:
internal::InputMethodDelegate* delegate_; internal::InputMethodDelegate* delegate_;
......
...@@ -88,42 +88,9 @@ ui::EventDispatchDetails InputMethodAuraLinux::DispatchKeyEvent( ...@@ -88,42 +88,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); 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::EventDispatchDetails InputMethodAuraLinux::ProcessKeyEventDone(
ui::KeyEvent* event, ui::KeyEvent* event,
bool filtered, bool filtered,
...@@ -256,14 +223,6 @@ void InputMethodAuraLinux::UpdateContextFocusState() { ...@@ -256,14 +223,6 @@ void InputMethodAuraLinux::UpdateContextFocusState() {
GetTextInputType(), GetTextInputMode(), GetTextInputFlags(), GetTextInputType(), GetTextInputMode(), GetTextInputFlags(),
ui::TextInputClient::FOCUS_REASON_OTHER, GetClientShouldDoLearning()); ui::TextInputClient::FOCUS_REASON_OTHER, GetClientShouldDoLearning());
ui::IMEBridge::Get()->SetCurrentInputContext(context); 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( void InputMethodAuraLinux::OnTextInputTypeChanged(
...@@ -286,19 +245,12 @@ void InputMethodAuraLinux::OnCaretBoundsChanged(const TextInputClient* client) { ...@@ -286,19 +245,12 @@ void InputMethodAuraLinux::OnCaretBoundsChanged(const TextInputClient* client) {
client->GetEditableSelectionRange(&selection_range)) { client->GetEditableSelectionRange(&selection_range)) {
context_->SetSurroundingText(text, 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) { void InputMethodAuraLinux::CancelComposition(const TextInputClient* client) {
if (!IsTextInputClientFocused(client)) if (!IsTextInputClientFocused(client))
return; return;
if (GetEngine())
GetEngine()->Reset();
ResetContext(); ResetContext();
} }
...@@ -457,8 +409,6 @@ void InputMethodAuraLinux::ConfirmCompositionText(bool reset_engine, ...@@ -457,8 +409,6 @@ void InputMethodAuraLinux::ConfirmCompositionText(bool reset_engine,
NOTIMPLEMENTED_LOG_ONCE(); NOTIMPLEMENTED_LOG_ONCE();
} }
InputMethodBase::ConfirmCompositionText(reset_engine, keep_selection); InputMethodBase::ConfirmCompositionText(reset_engine, keep_selection);
if (reset_engine && GetEngine())
GetEngine()->Reset();
ResetContext(); ResetContext();
} }
......
...@@ -65,18 +65,6 @@ class COMPONENT_EXPORT(UI_BASE_IME_LINUX) InputMethodAuraLinux ...@@ -65,18 +65,6 @@ class COMPONENT_EXPORT(UI_BASE_IME_LINUX) InputMethodAuraLinux
bool is_handled) bool is_handled)
WARN_UNUSED_RESULT; 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_;
std::unique_ptr<LinuxInputMethodContext> context_simple_; std::unique_ptr<LinuxInputMethodContext> context_simple_;
......
...@@ -237,21 +237,6 @@ ui::EventDispatchDetails InputMethodWinBase::DispatchKeyEvent( ...@@ -237,21 +237,6 @@ ui::EventDispatchDetails InputMethodWinBase::DispatchKeyEvent(
!std::iswcntrl(static_cast<wint_t>(char_msgs[0].wParam))) !std::iswcntrl(static_cast<wint_t>(char_msgs[0].wParam)))
event->set_character(static_cast<base::char16>(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); return ProcessUnhandledKeyEvent(event, &char_msgs);
} }
...@@ -506,48 +491,14 @@ ui::EventDispatchDetails InputMethodWinBase::ProcessUnhandledKeyEvent( ...@@ -506,48 +491,14 @@ ui::EventDispatchDetails InputMethodWinBase::ProcessUnhandledKeyEvent(
return details; 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() { void InputMethodWinBase::UpdateEngineFocusAndInputContext() {
if (!ui::IMEBridge::Get()) // IMEBridge could be null for tests. if (!ui::IMEBridge::Get()) // IMEBridge could be null for tests.
return; return;
const TextInputType old_text_input_type =
ui::IMEBridge::Get()->GetCurrentInputContext().type;
ui::IMEEngineHandlerInterface::InputContext context( ui::IMEEngineHandlerInterface::InputContext context(
GetTextInputType(), GetTextInputMode(), GetTextInputFlags(), GetTextInputType(), GetTextInputMode(), GetTextInputFlags(),
ui::TextInputClient::FOCUS_REASON_OTHER, GetClientShouldDoLearning()); ui::TextInputClient::FOCUS_REASON_OTHER, GetClientShouldDoLearning());
ui::IMEBridge::Get()->SetCurrentInputContext(context); 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 } // namespace ui
...@@ -62,15 +62,6 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) InputMethodWinBase ...@@ -62,15 +62,6 @@ class COMPONENT_EXPORT(UI_BASE_IME_WIN) InputMethodWinBase
ui::KeyEvent* event, ui::KeyEvent* event,
const std::vector<MSG>* char_msgs); 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 // Update focus state for Chromium IME extension and update input context in
// ui::IMEBridge. // ui::IMEBridge.
void UpdateEngineFocusAndInputContext(); void UpdateEngineFocusAndInputContext();
......
...@@ -101,7 +101,6 @@ void InputMethodWinImm32::OnCaretBoundsChanged(const TextInputClient* client) { ...@@ -101,7 +101,6 @@ void InputMethodWinImm32::OnCaretBoundsChanged(const TextInputClient* client) {
if (!IsTextInputClientFocused(client) || !IsWindowFocused(client)) if (!IsTextInputClientFocused(client) || !IsWindowFocused(client))
return; return;
NotifyTextInputCaretBoundsChanged(client); NotifyTextInputCaretBoundsChanged(client);
InputMethodWinBase::UpdateCompositionBoundsForEngine(client);
if (!enabled_) if (!enabled_)
return; return;
...@@ -126,13 +125,8 @@ void InputMethodWinImm32::OnCaretBoundsChanged(const TextInputClient* client) { ...@@ -126,13 +125,8 @@ void InputMethodWinImm32::OnCaretBoundsChanged(const TextInputClient* client) {
} }
void InputMethodWinImm32::CancelComposition(const TextInputClient* client) { void InputMethodWinImm32::CancelComposition(const TextInputClient* client) {
if (IsTextInputClientFocused(client)) { if (IsTextInputClientFocused(client) && enabled_) {
// |enabled_| == false could be faked, and the engine should rely on the imm32_manager_.CancelIME(toplevel_window_handle_);
// real type get from GetTextInputType().
InputMethodWinBase::CancelCompositionForEngine();
if (enabled_)
imm32_manager_.CancelIME(toplevel_window_handle_);
} }
} }
...@@ -326,8 +320,6 @@ void InputMethodWinImm32::RefreshInputLanguage() { ...@@ -326,8 +320,6 @@ void InputMethodWinImm32::RefreshInputLanguage() {
void InputMethodWinImm32::ConfirmCompositionText(bool reset_engine, void InputMethodWinImm32::ConfirmCompositionText(bool reset_engine,
bool keep_selection) { bool keep_selection) {
InputMethodBase::ConfirmCompositionText(reset_engine, 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 // Makes sure the native IME app can be informed about the composition is
// cleared, so that it can clean up its internal states. // cleared, so that it can clean up its internal states.
...@@ -339,8 +331,7 @@ void InputMethodWinImm32::UpdateIMEState() { ...@@ -339,8 +331,7 @@ void InputMethodWinImm32::UpdateIMEState() {
// Use switch here in case we are going to add more text input types. // Use switch here in case we are going to add more text input types.
// We disable input method in password field. // We disable input method in password field.
const HWND window_handle = toplevel_window_handle_; const HWND window_handle = toplevel_window_handle_;
const TextInputType text_input_type = const TextInputType text_input_type = GetTextInputType();
GetEngine() ? TEXT_INPUT_TYPE_NONE : GetTextInputType();
const TextInputMode text_input_mode = GetTextInputMode(); const TextInputMode text_input_mode = GetTextInputMode();
switch (text_input_type) { switch (text_input_type) {
case ui::TEXT_INPUT_TYPE_NONE: case ui::TEXT_INPUT_TYPE_NONE:
......
...@@ -110,14 +110,12 @@ void InputMethodWinTSF::OnCaretBoundsChanged(const TextInputClient* client) { ...@@ -110,14 +110,12 @@ void InputMethodWinTSF::OnCaretBoundsChanged(const TextInputClient* client) {
} }
NotifyTextInputCaretBoundsChanged(client); NotifyTextInputCaretBoundsChanged(client);
ui::TSFBridge::GetInstance()->OnTextLayoutChanged(); ui::TSFBridge::GetInstance()->OnTextLayoutChanged();
InputMethodWinBase::UpdateCompositionBoundsForEngine(client);
} }
void InputMethodWinTSF::CancelComposition(const TextInputClient* client) { void InputMethodWinTSF::CancelComposition(const TextInputClient* client) {
if (ui::TSFBridge::GetInstance() && IsTextInputClientFocused(client) && if (ui::TSFBridge::GetInstance() && IsTextInputClientFocused(client) &&
IsWindowFocused(client)) { IsWindowFocused(client)) {
ui::TSFBridge::GetInstance()->CancelComposition(); ui::TSFBridge::GetInstance()->CancelComposition();
InputMethodWinBase::CancelCompositionForEngine();
} }
} }
...@@ -181,8 +179,6 @@ void InputMethodWinTSF::ConfirmCompositionText(bool reset_engine, ...@@ -181,8 +179,6 @@ void InputMethodWinTSF::ConfirmCompositionText(bool reset_engine,
if (IsTextInputTypeNone()) if (IsTextInputTypeNone())
return; return;
if (reset_engine && GetTextInputClient()->HasCompositionText())
InputMethodWinBase::ResetEngine();
if (ui::TSFBridge::GetInstance()) if (ui::TSFBridge::GetInstance())
ui::TSFBridge::GetInstance()->ConfirmComposition(); ui::TSFBridge::GetInstance()->ConfirmComposition();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment