diff options
31 files changed, 677 insertions, 68 deletions
diff --git a/content/renderer/pepper/pepper_plugin_delegate_impl.cc b/content/renderer/pepper/pepper_plugin_delegate_impl.cc index a68ab1c..8118150 100644 --- a/content/renderer/pepper/pepper_plugin_delegate_impl.cc +++ b/content/renderer/pepper/pepper_plugin_delegate_impl.cc @@ -415,6 +415,12 @@ void PepperPluginDelegateImpl::PluginRequestedCancelComposition( render_view_->PpapiPluginCancelComposition(); } +void PepperPluginDelegateImpl::PluginSelectionChanged( + webkit::ppapi::PluginInstance* instance) { + if (focused_plugin_ == instance && render_view_) + render_view_->PpapiPluginSelectionChanged(); +} + void PepperPluginDelegateImpl::OnImeSetComposition( const string16& text, const std::vector<WebKit::WebCompositionUnderline>& underlines, @@ -486,6 +492,13 @@ ui::TextInputType PepperPluginDelegateImpl::GetTextInputType() const { return focused_plugin_->text_input_type(); } +void PepperPluginDelegateImpl::GetSurroundingText(string16* text, + ui::Range* range) const { + if (!focused_plugin_) + return; + return focused_plugin_->GetSurroundingText(text, range); +} + bool PepperPluginDelegateImpl::IsPluginAcceptingCompositionEvents() const { if (!focused_plugin_) return false; diff --git a/content/renderer/pepper/pepper_plugin_delegate_impl.h b/content/renderer/pepper/pepper_plugin_delegate_impl.h index 932dbe4..2f0b38c 100644 --- a/content/renderer/pepper/pepper_plugin_delegate_impl.h +++ b/content/renderer/pepper/pepper_plugin_delegate_impl.h @@ -47,6 +47,10 @@ namespace IPC { struct ChannelHandle; } +namespace ui { +class Range; +} + namespace webkit { struct WebPluginInfo; namespace ppapi { @@ -130,6 +134,7 @@ class PepperPluginDelegateImpl ui::TextInputType GetTextInputType() const; bool IsPluginAcceptingCompositionEvents() const; bool CanComposeInline() const; + void GetSurroundingText(string16* text, ui::Range* range) const; // IME events. void OnImeSetComposition( @@ -151,6 +156,8 @@ class PepperPluginDelegateImpl webkit::ppapi::PluginInstance* instance) OVERRIDE; virtual void PluginRequestedCancelComposition( webkit::ppapi::PluginInstance* instance) OVERRIDE; + virtual void PluginSelectionChanged( + webkit::ppapi::PluginInstance* instance) OVERRIDE; virtual void PluginCrashed(webkit::ppapi::PluginInstance* instance) OVERRIDE; virtual void InstanceCreated( webkit::ppapi::PluginInstance* instance) OVERRIDE; diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index dcabfc4..b1bb198 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -3650,34 +3650,42 @@ void RenderViewImpl::SyncSelectionIfRequired() { if (!frame) return; - size_t location, length; - if (!webview()->caretOrSelectionRange(&location, &length)) - return; - string16 text; size_t offset; - ui::Range range(location, location + length); - - if (webview()->textInputType() != WebKit::WebTextInputTypeNone) { - // If current focused element is editable, we will send 100 more chars - // before and after selection. It is for input method surrounding text - // feature. - if (location > kExtraCharsBeforeAndAfterSelection) - offset = location - kExtraCharsBeforeAndAfterSelection; - else - offset = 0; - length = location + length - offset + kExtraCharsBeforeAndAfterSelection; - WebRange webrange = WebRange::fromDocumentRange(frame, offset, length); - if (!webrange.isNull()) - text = WebRange::fromDocumentRange(frame, offset, length).toPlainText(); + ui::Range range; + + if (pepper_delegate_.IsPluginFocused()) { + pepper_delegate_.GetSurroundingText(&text, &range); + offset = 0; // Pepper API does not support offset reporting. + // TODO(kinaba): cut as needed. } else { - offset = location; - text = frame->selectionAsText(); - // http://crbug.com/101435 - // In some case, frame->selectionAsText() returned text's length is not - // equal to the length returned from webview()->caretOrSelectionRange(). - // So we have to set the range according to text.length(). - range.set_end(range.start() + text.length()); + size_t location, length; + if (!webview()->caretOrSelectionRange(&location, &length)) + return; + + range = ui::Range(location, location + length); + + if (webview()->textInputType() != WebKit::WebTextInputTypeNone) { + // If current focused element is editable, we will send 100 more chars + // before and after selection. It is for input method surrounding text + // feature. + if (location > kExtraCharsBeforeAndAfterSelection) + offset = location - kExtraCharsBeforeAndAfterSelection; + else + offset = 0; + length = location + length - offset + kExtraCharsBeforeAndAfterSelection; + WebRange webrange = WebRange::fromDocumentRange(frame, offset, length); + if (!webrange.isNull()) + text = WebRange::fromDocumentRange(frame, offset, length).toPlainText(); + } else { + offset = location; + text = frame->selectionAsText(); + // http://crbug.com/101435 + // In some case, frame->selectionAsText() returned text's length is not + // equal to the length returned from webview()->caretOrSelectionRange(). + // So we have to set the range according to text.length(). + range.set_end(range.start() + text.length()); + } } // Sometimes we get repeated didChangeSelection calls from webkit when @@ -4767,6 +4775,10 @@ void RenderViewImpl::PpapiPluginCancelComposition() { Send(new ViewHostMsg_ImeCompositionRangeChanged(routing_id(), range)); } +void RenderViewImpl::PpapiPluginSelectionChanged() { + SyncSelectionIfRequired(); +} + void RenderViewImpl::OnImeSetComposition( const string16& text, const std::vector<WebKit::WebCompositionUnderline>& underlines, diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index 8d7683f..a104ebe 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h @@ -271,6 +271,9 @@ class RenderViewImpl : public RenderWidget, // Cancels current composition. void PpapiPluginCancelComposition(); + // Informs the render view that a PPAPI plugin has changed selection. + void PpapiPluginSelectionChanged(); + // Retrieves the current caret position if a PPAPI plugin has focus. bool GetPpapiPluginCaretBounds(gfx::Rect* rect); diff --git a/ppapi/api/dev/ppb_text_input_dev.idl b/ppapi/api/dev/ppb_text_input_dev.idl index fde2574..d8c4176 100644 --- a/ppapi/api/dev/ppb_text_input_dev.idl +++ b/ppapi/api/dev/ppb_text_input_dev.idl @@ -8,7 +8,8 @@ */ label Chrome { - M16 = 0.1 + M16 = 0.1, + M19 = 0.2 }; /** @@ -66,4 +67,43 @@ interface PPB_TextInput_Dev { * Cancels the current composition in IME. */ void CancelCompositionText([in] PP_Instance instance); + + /** + * In response to the <code>PPP_TextInput_Dev::RequestSurroundingText</code> + * call, informs the browser about the current text selection and surrounding + * text. <code>text</code> is a UTF-8 string that contains the current range + * of text selection in the plugin. <code>caret</code> is the byte-index of + * the caret poisition within <code>text</code>. <code>anchor</code> is the + * byte-index of the anchor position (i.e., if a range of text is selected, + * it is the other edge of selection diffrent from <code>caret</code>. If + * there are no selection, <code>anchor</code> is equal to <code>caret</code>. + * + * Typical use of this information in the browser is to enable "reconversion" + * features of IME that puts back the already committed text into the + * pre-commit composition state. Another use is to improve the precision + * of suggestion of IME by taking the context into account (e.g., if the caret + * looks to be on the begining of a sentense, suggest capital letters in a + * virtual keyboard). + * + * When the focus is not on text, call this function setting <code>text</code> + * to an empty string and <code>caret</code> and <code>anchor</code> to zero. + * Also, the plugin should send the empty text when it does not want to reveal + * the selection to IME (e.g., when the surrounding text is containing + * password text). + */ + [version=0.2] + void UpdateSurroundingText([in] PP_Instance instance, + [in] str_t text, + [in] uint32_t caret, + [in] uint32_t anchor); + + /** + * Informs the browser when a range of text selection is changed in a plugin. + * When the browser needs to know the content of the updated selection, it + * pings back by <code>PPP_TextInput_Dev::RequestSurroundingText</code>. The + * plugin then should send the information with + * <code>UpdateSurroundingText</code>. + */ + [version=0.2] + void SelectionChanged([in] PP_Instance instance); }; diff --git a/ppapi/api/dev/ppp_text_input_dev.idl b/ppapi/api/dev/ppp_text_input_dev.idl new file mode 100644 index 0000000..6e692bf --- /dev/null +++ b/ppapi/api/dev/ppp_text_input_dev.idl @@ -0,0 +1,27 @@ +/* Copyright (c) 2012 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * This file defines the <code>PPP_TextInput_Dev</code> interface. + */ + +label Chrome { + M19 = 0.1 +}; + +/** + * <code>PPP_TextInput_Dev</code> is a set of function pointers that the + * plugin has to implement to provide hints for text input system (IME). + */ +interface PPP_TextInput_Dev { + /** + * Requests the plugin to send back the text arround the current caret or + * selection by <code>PPB_TextInput_Dev::UpdateSurroundingText</code>. + * It is recommended to include the <code>desired_number_of_characters</code> + * characters before and after the selection, but not mandatory. + */ + void RequestSurroundingText([in] PP_Instance instance, + [in] uint32_t desired_number_of_characters); +}; diff --git a/ppapi/c/dev/ppb_text_input_dev.h b/ppapi/c/dev/ppb_text_input_dev.h index 286ec34..7870f7e 100644 --- a/ppapi/c/dev/ppb_text_input_dev.h +++ b/ppapi/c/dev/ppb_text_input_dev.h @@ -3,7 +3,7 @@ * found in the LICENSE file. */ -/* From dev/ppb_text_input_dev.idl modified Wed Oct 5 14:06:02 2011. */ +/* From dev/ppb_text_input_dev.idl modified Tue Mar 13 21:18:47 2012. */ #ifndef PPAPI_C_DEV_PPB_TEXT_INPUT_DEV_H_ #define PPAPI_C_DEV_PPB_TEXT_INPUT_DEV_H_ @@ -16,7 +16,8 @@ #include "ppapi/c/pp_stdint.h" #define PPB_TEXTINPUT_DEV_INTERFACE_0_1 "PPB_TextInput(Dev);0.1" -#define PPB_TEXTINPUT_DEV_INTERFACE PPB_TEXTINPUT_DEV_INTERFACE_0_1 +#define PPB_TEXTINPUT_DEV_INTERFACE_0_2 "PPB_TextInput(Dev);0.2" +#define PPB_TEXTINPUT_DEV_INTERFACE PPB_TEXTINPUT_DEV_INTERFACE_0_2 /** * @file @@ -66,7 +67,7 @@ PP_COMPILE_ASSERT_SIZE_IN_BYTES(PP_TextInput_Type, 4); * to the browser about the text input status of plugins, and functions for * controlling input method editors (IMEs). */ -struct PPB_TextInput_Dev_0_1 { +struct PPB_TextInput_Dev_0_2 { /** * Informs the browser about the current text input mode of the plugin. * Typical use of this information in the browser is to properly @@ -87,9 +88,52 @@ struct PPB_TextInput_Dev_0_1 { * Cancels the current composition in IME. */ void (*CancelCompositionText)(PP_Instance instance); + /** + * In response to the <code>PPP_TextInput_Dev::RequestSurroundingText</code> + * call, informs the browser about the current text selection and surrounding + * text. <code>text</code> is a UTF-8 string that contains the current range + * of text selection in the plugin. <code>caret</code> is the byte-index of + * the caret poisition within <code>text</code>. <code>anchor</code> is the + * byte-index of the anchor position (i.e., if a range of text is selected, + * it is the other edge of selection diffrent from <code>caret</code>. If + * there are no selection, <code>anchor</code> is equal to <code>caret</code>. + * + * Typical use of this information in the browser is to enable "reconversion" + * features of IME that puts back the already committed text into the + * pre-commit composition state. Another use is to improve the precision + * of suggestion of IME by taking the context into account (e.g., if the caret + * looks to be on the begining of a sentense, suggest capital letters in a + * virtual keyboard). + * + * When the focus is not on text, call this function setting <code>text</code> + * to an empty string and <code>caret</code> and <code>anchor</code> to zero. + * Also, the plugin should send the empty text when it does not want to reveal + * the selection to IME (e.g., when the surrounding text is containing + * password text). + */ + void (*UpdateSurroundingText)(PP_Instance instance, + const char* text, + uint32_t caret, + uint32_t anchor); + /** + * Informs the browser when a range of text selection is changed in a plugin. + * When the browser needs to know the content of the updated selection, it + * pings back by <code>PPP_TextInput_Dev::RequestSurroundingText</code>. The + * plugin then should send the information with + * <code>UpdateSurroundingText</code>. + */ + void (*SelectionChanged)(PP_Instance instance); }; -typedef struct PPB_TextInput_Dev_0_1 PPB_TextInput_Dev; +typedef struct PPB_TextInput_Dev_0_2 PPB_TextInput_Dev; + +struct PPB_TextInput_Dev_0_1 { + void (*SetTextInputType)(PP_Instance instance, PP_TextInput_Type type); + void (*UpdateCaretPosition)(PP_Instance instance, + const struct PP_Rect* caret, + const struct PP_Rect* bounding_box); + void (*CancelCompositionText)(PP_Instance instance); +}; /** * @} */ diff --git a/ppapi/c/dev/ppp_text_input_dev.h b/ppapi/c/dev/ppp_text_input_dev.h new file mode 100644 index 0000000..3bfea58 --- /dev/null +++ b/ppapi/c/dev/ppp_text_input_dev.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2012 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* From dev/ppp_text_input_dev.idl modified Tue Mar 13 20:19:19 2012. */ + +#ifndef PPAPI_C_DEV_PPP_TEXT_INPUT_DEV_H_ +#define PPAPI_C_DEV_PPP_TEXT_INPUT_DEV_H_ + +#include "ppapi/c/pp_instance.h" +#include "ppapi/c/pp_macros.h" +#include "ppapi/c/pp_stdint.h" + +#define PPP_TEXTINPUT_DEV_INTERFACE_0_1 "PPP_TextInput(Dev);0.1" +#define PPP_TEXTINPUT_DEV_INTERFACE PPP_TEXTINPUT_DEV_INTERFACE_0_1 + +/** + * @file + * This file defines the <code>PPP_TextInput_Dev</code> interface. + */ + + +/** + * @addtogroup Interfaces + * @{ + */ +/** + * <code>PPP_TextInput_Dev</code> is a set of function pointers that the + * plugin has to implement to provide hints for text input system (IME). + */ +struct PPP_TextInput_Dev_0_1 { + /** + * Requests the plugin to send back the text arround the current caret or + * selection by <code>PPB_TextInput_Dev::UpdateSurroundingText</code>. + * It is recommended to include the <code>desired_number_of_characters</code> + * characters before and after the selection, but not mandatory. + */ + void (*RequestSurroundingText)(PP_Instance instance, + uint32_t desired_number_of_characters); +}; + +typedef struct PPP_TextInput_Dev_0_1 PPP_TextInput_Dev; +/** + * @} + */ + +#endif /* PPAPI_C_DEV_PPP_TEXT_INPUT_DEV_H_ */ + diff --git a/ppapi/cpp/dev/text_input_dev.cc b/ppapi/cpp/dev/text_input_dev.cc index 6783892..3b38df8 100644 --- a/ppapi/cpp/dev/text_input_dev.cc +++ b/ppapi/cpp/dev/text_input_dev.cc @@ -1,9 +1,11 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ppapi/cpp/dev/text_input_dev.h" +#include "ppapi/c/dev/ppp_text_input_dev.h" +#include "ppapi/cpp/instance.h" #include "ppapi/cpp/instance_handle.h" #include "ppapi/cpp/module_impl.h" #include "ppapi/cpp/rect.h" @@ -12,40 +14,95 @@ namespace pp { namespace { -template <> const char* interface_name<PPB_TextInput_Dev>() { - return PPB_TEXTINPUT_DEV_INTERFACE; +static const char kPPPTextInputInterface[] = PPP_TEXTINPUT_DEV_INTERFACE; + +void RequestSurroundingText(PP_Instance instance, + uint32_t desired_number_of_characters) { + void* object = Instance::GetPerInstanceObject(instance, + kPPPTextInputInterface); + if (!object) + return; + static_cast<TextInput_Dev*>(object)->RequestSurroundingText( + desired_number_of_characters); +} + +const PPP_TextInput_Dev ppp_text_input = { + &RequestSurroundingText +}; + +template <> const char* interface_name<PPB_TextInput_Dev_0_2>() { + return PPB_TEXTINPUT_DEV_INTERFACE_0_2; +} + +template <> const char* interface_name<PPB_TextInput_Dev_0_1>() { + return PPB_TEXTINPUT_DEV_INTERFACE_0_1; } } // namespace -TextInput_Dev::TextInput_Dev(const InstanceHandle& instance) +TextInput_Dev::TextInput_Dev(Instance* instance) : instance_(instance) { + Module::Get()->AddPluginInterface(kPPPTextInputInterface, + &ppp_text_input); + instance->AddPerInstanceObject(kPPPTextInputInterface, this); } TextInput_Dev::~TextInput_Dev() { + Instance::RemovePerInstanceObject(instance_, kPPPTextInputInterface, this); +} + +void TextInput_Dev::RequestSurroundingText(uint32_t) { + // Default implementation. Send a null range. + UpdateSurroundingText("", 0, 0); } void TextInput_Dev::SetTextInputType(PP_TextInput_Type type) { - if (!has_interface<PPB_TextInput_Dev>()) - return; - get_interface<PPB_TextInput_Dev>()->SetTextInputType( - instance_.pp_instance(), type); + if (has_interface<PPB_TextInput_Dev_0_2>()) { + get_interface<PPB_TextInput_Dev_0_2>()->SetTextInputType( + instance_.pp_instance(), type); + } else if (has_interface<PPB_TextInput_Dev_0_1>()) { + get_interface<PPB_TextInput_Dev_0_1>()->SetTextInputType( + instance_.pp_instance(), type); + } } void TextInput_Dev::UpdateCaretPosition(const Rect& caret, const Rect& bounding_box) { - if (!has_interface<PPB_TextInput_Dev>()) - return; - get_interface<PPB_TextInput_Dev>()->UpdateCaretPosition( - instance_.pp_instance(), &caret.pp_rect(), &bounding_box.pp_rect()); + if (has_interface<PPB_TextInput_Dev_0_2>()) { + get_interface<PPB_TextInput_Dev_0_2>()->UpdateCaretPosition( + instance_.pp_instance(), &caret.pp_rect(), &bounding_box.pp_rect()); + } else if (has_interface<PPB_TextInput_Dev_0_1>()) { + get_interface<PPB_TextInput_Dev_0_1>()->UpdateCaretPosition( + instance_.pp_instance(), &caret.pp_rect(), &bounding_box.pp_rect()); + } } void TextInput_Dev::CancelCompositionText() { - if (!has_interface<PPB_TextInput_Dev>()) - return; - get_interface<PPB_TextInput_Dev>()->CancelCompositionText( - instance_.pp_instance()); + if (has_interface<PPB_TextInput_Dev_0_2>()) { + get_interface<PPB_TextInput_Dev_0_2>()->CancelCompositionText( + instance_.pp_instance()); + } else if (has_interface<PPB_TextInput_Dev_0_1>()) { + get_interface<PPB_TextInput_Dev_0_1>()->CancelCompositionText( + instance_.pp_instance()); + } +} + +void TextInput_Dev::SelectionChanged() { + if (has_interface<PPB_TextInput_Dev_0_2>()) { + get_interface<PPB_TextInput_Dev_0_2>()->SelectionChanged( + instance_.pp_instance()); + } +} + +void TextInput_Dev::UpdateSurroundingText(const std::string& text, + uint32_t caret, + uint32_t anchor) { + if (has_interface<PPB_TextInput_Dev_0_2>()) { + get_interface<PPB_TextInput_Dev_0_2>()->UpdateSurroundingText( + instance_.pp_instance(), text.c_str(), caret, anchor); + } } + } // namespace pp diff --git a/ppapi/cpp/dev/text_input_dev.h b/ppapi/cpp/dev/text_input_dev.h index af21a90..ea75597 100644 --- a/ppapi/cpp/dev/text_input_dev.h +++ b/ppapi/cpp/dev/text_input_dev.h @@ -1,27 +1,56 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef PPAPI_CPP_DEV_TEXT_INPUT_DEV_H_ #define PPAPI_CPP_DEV_TEXT_INPUT_DEV_H_ +#include <string> + #include "ppapi/c/dev/ppb_text_input_dev.h" #include "ppapi/cpp/instance_handle.h" -/// @file -/// This file defines the API for controlling text input methods. namespace pp { class Rect; - +class Instance; + +// This class allows you to associate the PPP_TextInput_Dev and +// PPB_TextInput_Dev C-based interfaces with an object. It associates itself +// with the given instance, and registers as the global handler for handling the +// PPP_TextInput_Dev interface that the browser calls. +// +// You would typically use this either via inheritance on your instance: +// class MyInstance : public pp::Instance, public pp::TextInput_Dev { +// MyInstance() : pp::TextInput_Dev(this) { +// } +// ... +// }; +// +// or by composition: +// class MyTextInput : public pp::TextInput_Dev { +// ... +// }; +// +// class MyInstance : public pp::Instance { +// MyInstance() : text_input_(this) { +// } +// +// MyTextInput text_input_; +// }; class TextInput_Dev { public: - explicit TextInput_Dev(const InstanceHandle& instance); + explicit TextInput_Dev(Instance* instance); virtual ~TextInput_Dev(); + virtual void RequestSurroundingText(uint32_t desired_number_of_characters); + void SetTextInputType(PP_TextInput_Type type); void UpdateCaretPosition(const Rect& caret, const Rect& bounding_box); void CancelCompositionText(); + void SelectionChanged(); + void UpdateSurroundingText(const std::string& text, + uint32_t caret, uint32_t anchor); private: InstanceHandle instance_; diff --git a/ppapi/examples/ime/ime.cc b/ppapi/examples/ime/ime.cc index 2c3ee0b..e217145 100644 --- a/ppapi/examples/ime/ime.cc +++ b/ppapi/examples/ime/ime.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -92,15 +92,17 @@ class TextFieldStatusHandler { virtual ~TextFieldStatusHandler() {} virtual void FocusIn(const pp::Rect& caret, const pp::Rect& bounding_box) {} virtual void FocusOut() {} + virtual void UpdateSelection(const std::string& text) {} }; -class TextFieldStatusNotifyingHanlder : public TextFieldStatusHandler { +class TextFieldStatusNotifyingHandler : public TextFieldStatusHandler { public: - explicit TextFieldStatusNotifyingHanlder(pp::Instance* instance) - : instance_(instance), - textinput_control_(instance) {} + explicit TextFieldStatusNotifyingHandler(pp::Instance* instance) + : textinput_control_(instance) { + } protected: + // Implement TextFieldStatusHandler. virtual void FocusIn(const pp::Rect& caret, const pp::Rect& bounding_box) { textinput_control_.SetTextInputType(PP_TEXTINPUT_TYPE_TEXT); textinput_control_.UpdateCaretPosition(caret, bounding_box); @@ -109,10 +111,22 @@ class TextFieldStatusNotifyingHanlder : public TextFieldStatusHandler { textinput_control_.CancelCompositionText(); textinput_control_.SetTextInputType(PP_TEXTINPUT_TYPE_NONE); } + virtual void UpdateSelection(const std::string& text) { + textinput_control_.SetSelectionText(text); + textinput_control_.SelectionChanged(); + } private: - pp::Instance* instance_; - pp::TextInput_Dev textinput_control_; + class MyTextInput : public pp::TextInput_Dev { + public: + MyTextInput(pp::Instance* instance) : pp::TextInput_Dev(instance) {} + virtual void RequestSurroundingText(uint32_t characters) { + UpdateSurroundingText(selection_text_, 0, selection_text_.size()); + } + void SetSelectionText(const std::string& text) { selection_text_ = text; } + std::string selection_text_; + }; + MyTextInput textinput_control_; }; // Hand-made text field for demonstrating text input API. @@ -361,6 +375,9 @@ class MyTextField { int px = font_.MeasureSimpleText(str); pp::Rect caret(area_.x() + px, area_.y(), 0, area_.height() + 2); status_handler_->FocusIn(caret, area_); + status_handler_->UpdateSelection( + utf8_text_.substr(SelectionLeft(), + SelectionRight() - SelectionLeft())); } } size_t SelectionLeft() const { @@ -430,14 +447,14 @@ class MyInstance : public pp::Instance { // say, show virtual keyboards or IMEs only at appropriate timing // that the plugin does need to accept text input. delete status_handler_; - status_handler_ = new TextFieldStatusNotifyingHanlder(this); + status_handler_ = new TextFieldStatusNotifyingHandler(this); } else if (argv[i] == std::string("full")) { // Demonstrating the behavior of plugins fully supporting IME. // // It notifies updates of caret positions to the browser, // and handles all text input events by itself. delete status_handler_; - status_handler_ = new TextFieldStatusNotifyingHanlder(this); + status_handler_ = new TextFieldStatusNotifyingHandler(this); RequestInputEvents(PP_INPUTEVENT_CLASS_IME); } break; diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi index 855c7e2..c23fd49 100644 --- a/ppapi/ppapi_proxy.gypi +++ b/ppapi/ppapi_proxy.gypi @@ -141,6 +141,8 @@ 'proxy/ppp_mouse_lock_proxy.h', 'proxy/ppp_printing_proxy.cc', 'proxy/ppp_printing_proxy.h', + 'proxy/ppp_text_input_proxy.cc', + 'proxy/ppp_text_input_proxy.h', 'proxy/ppp_video_decoder_proxy.cc', 'proxy/ppp_video_decoder_proxy.h', 'proxy/proxy_channel.cc', diff --git a/ppapi/ppapi_sources.gypi b/ppapi/ppapi_sources.gypi index 80677d9..2770212 100644 --- a/ppapi/ppapi_sources.gypi +++ b/ppapi/ppapi_sources.gypi @@ -72,6 +72,7 @@ 'c/dev/ppb_resource_array_dev.h', 'c/dev/ppb_scrollbar_dev.h', 'c/dev/ppb_testing_dev.h', + 'c/dev/ppb_text_input_dev.h', 'c/dev/ppb_url_util_dev.h', 'c/dev/ppb_video_decoder_dev.h', 'c/dev/ppb_widget_dev.h', @@ -81,7 +82,7 @@ 'c/dev/ppp_network_state_dev.h', 'c/dev/ppp_scrollbar_dev.h', 'c/dev/ppp_selection_dev.h', - 'c/dev/ppb_text_input_dev.h', + 'c/dev/ppp_text_input_dev.h', 'c/dev/ppp_video_decoder_dev.h', 'c/dev/ppp_widget_dev.h', 'c/dev/ppp_zoom_dev.h', diff --git a/ppapi/proxy/interface_list.cc b/ppapi/proxy/interface_list.cc index 374bbf2..e746ffd 100644 --- a/ppapi/proxy/interface_list.cc +++ b/ppapi/proxy/interface_list.cc @@ -109,6 +109,7 @@ #include "ppapi/proxy/ppp_messaging_proxy.h" #include "ppapi/proxy/ppp_mouse_lock_proxy.h" #include "ppapi/proxy/ppp_printing_proxy.h" +#include "ppapi/proxy/ppp_text_input_proxy.h" #include "ppapi/proxy/ppp_video_decoder_proxy.h" #include "ppapi/proxy/resource_creation_proxy.h" #include "ppapi/shared_impl/ppb_opengles2_shared.h" @@ -222,6 +223,9 @@ InterfaceList::InterfaceList() { AddProxy(API_ID_PPP_PRINTING, &ProxyFactory<PPP_Printing_Proxy>); AddPPP(PPP_PRINTING_DEV_INTERFACE, API_ID_PPP_PRINTING, PPP_Printing_Proxy::GetProxyInterface()); + AddProxy(API_ID_PPP_TEXT_INPUT, &ProxyFactory<PPP_TextInput_Proxy>); + AddPPP(PPP_TEXTINPUT_DEV_INTERFACE, API_ID_PPP_TEXT_INPUT, + PPP_TextInput_Proxy::GetProxyInterface()); // Old-style GetInfo PPP interfaces. // Do not add more stuff here, they should be added to interface_list*.h diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index f1cd174..7a5c2f4 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h @@ -513,6 +513,11 @@ IPC_SYNC_MESSAGE_ROUTED1_1(PpapiMsg_PPPPrinting_IsScalingDisabled, PP_Instance /* instance */, bool /* result */) +// PPP_TextInput. +IPC_MESSAGE_ROUTED2(PpapiMsg_PPPTextInput_RequestSurroundingText, + PP_Instance /* instance */, + uint32_t /* desired_number_of_characters */) + // PPB_URLLoader // (Messages from browser to plugin to notify it of changes in state.) IPC_MESSAGE_ROUTED1( @@ -943,6 +948,13 @@ IPC_MESSAGE_ROUTED3(PpapiHostMsg_PPBTextInput_UpdateCaretPosition, PP_Rect /* bounding_box */) IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBTextInput_CancelCompositionText, PP_Instance /* instance */) +IPC_MESSAGE_ROUTED1(PpapiHostMsg_PPBTextInput_SelectionChanged, + PP_Instance /* instance */) +IPC_MESSAGE_ROUTED4(PpapiHostMsg_PPBTextInput_UpdateSurroundingText, + PP_Instance /* instance */, + std::string /* text */, + uint32_t /* caret */, + uint32_t /* anchor */) // PPB_URLLoader. IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBURLLoader_Create, diff --git a/ppapi/proxy/ppb_text_input_proxy.cc b/ppapi/proxy/ppb_text_input_proxy.cc index 7a48912..e7434e0 100644 --- a/ppapi/proxy/ppb_text_input_proxy.cc +++ b/ppapi/proxy/ppb_text_input_proxy.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -42,6 +42,19 @@ void PPB_TextInput_Proxy::CancelCompositionText(PP_Instance instance) { API_ID_PPB_TEXT_INPUT, instance)); } +void PPB_TextInput_Proxy::SelectionChanged(PP_Instance instance) { + dispatcher()->Send(new PpapiHostMsg_PPBTextInput_SelectionChanged( + API_ID_PPB_TEXT_INPUT, instance)); +} + +void PPB_TextInput_Proxy::UpdateSurroundingText(PP_Instance instance, + const char* text, + uint32_t caret, + uint32_t anchor) { + dispatcher()->Send(new PpapiHostMsg_PPBTextInput_UpdateSurroundingText( + API_ID_PPB_TEXT_INPUT, instance, text, caret, anchor)); +} + bool PPB_TextInput_Proxy::OnMessageReceived(const IPC::Message& msg) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(PPB_TextInput_Proxy, msg) @@ -51,6 +64,10 @@ bool PPB_TextInput_Proxy::OnMessageReceived(const IPC::Message& msg) { OnMsgUpdateCaretPosition) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTextInput_CancelCompositionText, OnMsgCancelCompositionText) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTextInput_SelectionChanged, + OnMsgSelectionChanged) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTextInput_UpdateSurroundingText, + OnMsgUpdateSurroundingText) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -80,5 +97,23 @@ void PPB_TextInput_Proxy::OnMsgCancelCompositionText(PP_Instance instance) { enter.functions()->CancelCompositionText(instance); } +void PPB_TextInput_Proxy::OnMsgSelectionChanged(PP_Instance instance) { + ppapi::thunk::EnterFunctionNoLock<PPB_TextInput_FunctionAPI> enter(instance, + true); + if (enter.succeeded()) + enter.functions()->SelectionChanged(instance); +} + +void PPB_TextInput_Proxy::OnMsgUpdateSurroundingText(PP_Instance instance, + const std::string& text, + uint32_t caret, + uint32_t anchor) { + ppapi::thunk::EnterFunctionNoLock<PPB_TextInput_FunctionAPI> enter(instance, + true); + if (enter.succeeded()) + enter.functions()->UpdateSurroundingText(instance, + text.c_str(), caret, anchor); +} + } // namespace proxy } // namespace ppapi diff --git a/ppapi/proxy/ppb_text_input_proxy.h b/ppapi/proxy/ppb_text_input_proxy.h index 92a8b12..e5226a4 100644 --- a/ppapi/proxy/ppb_text_input_proxy.h +++ b/ppapi/proxy/ppb_text_input_proxy.h @@ -1,10 +1,12 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef PPAPI_PROXY_PPB_TEXT_INPUT_PROXY_H_ #define PPAPI_PROXY_PPB_TEXT_INPUT_PROXY_H_ +#include <string> + #include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_rect.h" #include "ppapi/proxy/interface_proxy.h" @@ -31,6 +33,11 @@ class PPB_TextInput_Proxy const PP_Rect& caret, const PP_Rect& bounding_box) OVERRIDE; virtual void CancelCompositionText(PP_Instance instance) OVERRIDE; + virtual void SelectionChanged(PP_Instance instance) OVERRIDE; + virtual void UpdateSurroundingText(PP_Instance instance, + const char* text, + uint32_t caret, + uint32_t anchor) OVERRIDE; // InterfaceProxy implementation. virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; @@ -44,6 +51,11 @@ class PPB_TextInput_Proxy PP_Rect caret, PP_Rect bounding_box); void OnMsgCancelCompositionText(PP_Instance instance); + void OnMsgSelectionChanged(PP_Instance instance); + void OnMsgUpdateSurroundingText(PP_Instance instance, + const std::string& text, + uint32_t caret, + uint32_t anchor); DISALLOW_COPY_AND_ASSIGN(PPB_TextInput_Proxy); }; diff --git a/ppapi/proxy/ppp_text_input_proxy.cc b/ppapi/proxy/ppp_text_input_proxy.cc new file mode 100644 index 0000000..8a8254a --- /dev/null +++ b/ppapi/proxy/ppp_text_input_proxy.cc @@ -0,0 +1,73 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ppapi/proxy/ppp_text_input_proxy.h" + +#include "ppapi/c/dev/ppp_text_input_dev.h" +#include "ppapi/proxy/host_dispatcher.h" +#include "ppapi/proxy/ppapi_messages.h" +#include "ppapi/shared_impl/proxy_lock.h" + +namespace ppapi { +namespace proxy { + +namespace { + +void RequestSurroundingText(PP_Instance instance, + uint32_t desired_number_of_characters) { + proxy::HostDispatcher* dispatcher = + proxy::HostDispatcher::GetForInstance(instance); + if (!dispatcher) { + // The dispatcher should always be valid. + NOTREACHED(); + return; + } + + dispatcher->Send(new PpapiMsg_PPPTextInput_RequestSurroundingText( + API_ID_PPP_TEXT_INPUT, instance, desired_number_of_characters)); +} + +const PPP_TextInput_Dev g_ppp_text_input_thunk = { + &RequestSurroundingText +}; + +} // namespace + +// static +const PPP_TextInput_Dev* PPP_TextInput_Proxy::GetProxyInterface() { + return &g_ppp_text_input_thunk; +} + +PPP_TextInput_Proxy::PPP_TextInput_Proxy(Dispatcher* dispatcher) + : InterfaceProxy(dispatcher), + ppp_text_input_impl_(NULL) { + if (dispatcher->IsPlugin()) { + ppp_text_input_impl_ = static_cast<const PPP_TextInput_Dev*>( + dispatcher->local_get_interface()(PPP_TEXTINPUT_DEV_INTERFACE)); + } +} + +PPP_TextInput_Proxy::~PPP_TextInput_Proxy() { +} + +bool PPP_TextInput_Proxy::OnMessageReceived(const IPC::Message& msg) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(PPP_TextInput_Proxy, msg) + IPC_MESSAGE_HANDLER(PpapiMsg_PPPTextInput_RequestSurroundingText, + OnMsgRequestSurroundingText) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void PPP_TextInput_Proxy::OnMsgRequestSurroundingText( + PP_Instance instance, uint32_t desired_number_of_characters) { + if (ppp_text_input_impl_) { + CallWhileUnlocked(ppp_text_input_impl_->RequestSurroundingText, + instance, desired_number_of_characters); + } +} + +} // namespace proxy +} // namespace ppapi diff --git a/ppapi/proxy/ppp_text_input_proxy.h b/ppapi/proxy/ppp_text_input_proxy.h new file mode 100644 index 0000000..c4f09db --- /dev/null +++ b/ppapi/proxy/ppp_text_input_proxy.h @@ -0,0 +1,41 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PPAPI_PROXY_PPP_TEXT_INPUT_PROXY_H_ +#define PPAPI_PROXY_PPP_TEXT_INPUT_PROXY_H_ + +#include "ppapi/c/dev/ppp_text_input_dev.h" +#include "ppapi/c/pp_instance.h" +#include "ppapi/proxy/interface_proxy.h" + +namespace ppapi { +namespace proxy { + +class PPP_TextInput_Proxy : public InterfaceProxy { + public: + PPP_TextInput_Proxy(Dispatcher* dispatcher); + virtual ~PPP_TextInput_Proxy(); + + static const PPP_TextInput_Dev* GetProxyInterface(); + + // InterfaceProxy implementation. + virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE; + + private: + // Message handlers. + void OnMsgRequestSurroundingText(PP_Instance instance, + uint32_t desired_number_of_characters); + + // When this proxy is in the plugin side, this value caches the interface + // pointer so we don't have to retrieve it from the dispatcher each time. + // In the host, this value is always NULL. + const PPP_TextInput_Dev* ppp_text_input_impl_; + + DISALLOW_COPY_AND_ASSIGN(PPP_TextInput_Proxy); +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_PPP_TEXT_INPUT_PROXY_H_ diff --git a/ppapi/shared_impl/api_id.h b/ppapi/shared_impl/api_id.h index 60aa90b..325247f 100644 --- a/ppapi/shared_impl/api_id.h +++ b/ppapi/shared_impl/api_id.h @@ -60,6 +60,7 @@ enum ApiID { API_ID_PPP_MESSAGING, API_ID_PPP_MOUSE_LOCK, API_ID_PPP_PRINTING, + API_ID_PPP_TEXT_INPUT, API_ID_PPP_VIDEO_CAPTURE_DEV, API_ID_PPP_VIDEO_DECODER_DEV, diff --git a/ppapi/thunk/interfaces_ppb_public_dev.h b/ppapi/thunk/interfaces_ppb_public_dev.h index 7d81554..72de91e 100644 --- a/ppapi/thunk/interfaces_ppb_public_dev.h +++ b/ppapi/thunk/interfaces_ppb_public_dev.h @@ -56,6 +56,8 @@ UNPROXIED_IFACE(PPB_Scrollbar, PPB_SCROLLBAR_DEV_INTERFACE_0_5, PPB_Scrollbar_Dev_0_5) PROXIED_IFACE(PPB_TextInput, PPB_TEXTINPUT_DEV_INTERFACE_0_1, PPB_TextInput_Dev_0_1) +PROXIED_IFACE(PPB_TextInput, PPB_TEXTINPUT_DEV_INTERFACE_0_2, + PPB_TextInput_Dev_0_2) UNPROXIED_IFACE(PPB_Transport, PPB_TRANSPORT_DEV_INTERFACE_0_7, PPB_Transport_Dev_0_7) PROXIED_IFACE(PPB_VideoCapture, PPB_VIDEOCAPTURE_DEV_INTERFACE_0_1, diff --git a/ppapi/thunk/ppb_text_input_api.h b/ppapi/thunk/ppb_text_input_api.h index d826b20..65589a0 100644 --- a/ppapi/thunk/ppb_text_input_api.h +++ b/ppapi/thunk/ppb_text_input_api.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -21,6 +21,11 @@ class PPB_TextInput_FunctionAPI { const PP_Rect& caret, const PP_Rect& bounding_box) = 0; virtual void CancelCompositionText(PP_Instance instance) = 0; + virtual void SelectionChanged(PP_Instance instance) = 0; + virtual void UpdateSurroundingText(PP_Instance instance, + const char* text, + uint32_t caret, + uint32_t anchor) = 0; static const ApiID kApiID = API_ID_PPB_TEXT_INPUT; }; diff --git a/ppapi/thunk/ppb_text_input_thunk.cc b/ppapi/thunk/ppb_text_input_thunk.cc index dda6864..b5b1753 100644 --- a/ppapi/thunk/ppb_text_input_thunk.cc +++ b/ppapi/thunk/ppb_text_input_thunk.cc @@ -31,16 +31,41 @@ void CancelCompositionText(PP_Instance instance) { enter.functions()->CancelCompositionText(instance); } -const PPB_TextInput_Dev g_ppb_textinput_thunk = { +void UpdateSurroundingText(PP_Instance instance, const char* text, + uint32_t caret, uint32_t anchor) { + EnterFunction<PPB_TextInput_FunctionAPI> enter(instance, true); + if (enter.succeeded()) + enter.functions()->UpdateSurroundingText(instance, text, caret, anchor); +} + +void SelectionChanged(PP_Instance instance) { + EnterFunction<PPB_TextInput_FunctionAPI> enter(instance, true); + if (enter.succeeded()) + enter.functions()->SelectionChanged(instance); +} + +const PPB_TextInput_Dev_0_1 g_ppb_textinput_0_1_thunk = { &SetTextInputType, &UpdateCaretPosition, &CancelCompositionText, }; +const PPB_TextInput_Dev g_ppb_textinput_0_2_thunk = { + &SetTextInputType, + &UpdateCaretPosition, + &CancelCompositionText, + &UpdateSurroundingText, + &SelectionChanged, +}; + } // namespace const PPB_TextInput_Dev_0_1* GetPPB_TextInput_Dev_0_1_Thunk() { - return &g_ppb_textinput_thunk; + return &g_ppb_textinput_0_1_thunk; +} + +const PPB_TextInput_Dev_0_2* GetPPB_TextInput_Dev_0_2_Thunk() { + return &g_ppb_textinput_0_2_thunk; } } // namespace thunk diff --git a/webkit/plugins/ppapi/DEPS b/webkit/plugins/ppapi/DEPS index 5cb4caa..aafe281 100644 --- a/webkit/plugins/ppapi/DEPS +++ b/webkit/plugins/ppapi/DEPS @@ -5,4 +5,5 @@ include_rules = [ "+printing", "+media/video", "+ui/base/ime", + "+ui/base/range", ] diff --git a/webkit/plugins/ppapi/mock_plugin_delegate.cc b/webkit/plugins/ppapi/mock_plugin_delegate.cc index 51713ef..c30b845 100644 --- a/webkit/plugins/ppapi/mock_plugin_delegate.cc +++ b/webkit/plugins/ppapi/mock_plugin_delegate.cc @@ -34,6 +34,9 @@ void MockPluginDelegate::PluginRequestedCancelComposition( PluginInstance* instance) { } +void MockPluginDelegate::PluginSelectionChanged(PluginInstance* instance) { +} + void MockPluginDelegate::PluginCrashed(PluginInstance* instance) { } diff --git a/webkit/plugins/ppapi/mock_plugin_delegate.h b/webkit/plugins/ppapi/mock_plugin_delegate.h index 38bfa58..15c6311 100644 --- a/webkit/plugins/ppapi/mock_plugin_delegate.h +++ b/webkit/plugins/ppapi/mock_plugin_delegate.h @@ -22,6 +22,7 @@ class MockPluginDelegate : public PluginDelegate { virtual void PluginTextInputTypeChanged(PluginInstance* instance); virtual void PluginCaretPositionChanged(PluginInstance* instance); virtual void PluginRequestedCancelComposition(PluginInstance* instance); + virtual void PluginSelectionChanged(PluginInstance* instance); virtual void PluginCrashed(PluginInstance* instance); virtual void InstanceCreated(PluginInstance* instance); virtual void InstanceDeleted(PluginInstance* instance); diff --git a/webkit/plugins/ppapi/plugin_delegate.h b/webkit/plugins/ppapi/plugin_delegate.h index be8cd16..f357158 100644 --- a/webkit/plugins/ppapi/plugin_delegate.h +++ b/webkit/plugins/ppapi/plugin_delegate.h @@ -297,6 +297,9 @@ class PluginDelegate { // Notification that the plugin requested to cancel the current composition. virtual void PluginRequestedCancelComposition( webkit::ppapi::PluginInstance* instance) = 0; + // Notification that the text selection in the given plugin is changed. + virtual void PluginSelectionChanged( + webkit::ppapi::PluginInstance* instance) = 0; // Notification that the given plugin has crashed. When a plugin crashes, all // instances associated with that plugin will notify that they've crashed via diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.cc b/webkit/plugins/ppapi/ppapi_plugin_instance.cc index 91d2f2b..e4c13c4 100644 --- a/webkit/plugins/ppapi/ppapi_plugin_instance.cc +++ b/webkit/plugins/ppapi/ppapi_plugin_instance.cc @@ -17,6 +17,7 @@ #include "ppapi/c/dev/ppb_zoom_dev.h" #include "ppapi/c/dev/ppp_find_dev.h" #include "ppapi/c/dev/ppp_selection_dev.h" +#include "ppapi/c/dev/ppp_text_input_dev.h" #include "ppapi/c/dev/ppp_zoom_dev.h" #include "ppapi/c/pp_rect.h" #include "ppapi/c/ppb_audio_config.h" @@ -55,6 +56,7 @@ #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLRequest.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" +#include "ui/base/range/range.h" #include "webkit/plugins/ppapi/common.h" #include "webkit/plugins/ppapi/event_conversion.h" #include "webkit/plugins/ppapi/fullscreen_container.h" @@ -155,6 +157,11 @@ namespace { // that they don't accept texts. const ui::TextInputType kPluginDefaultTextInputType = ui::TEXT_INPUT_TYPE_TEXT; +// The length of text to request as a surrounding context of selection. +// For now, the value is copied from the one with render_view_impl.cc. +// TODO(kinaba) implement a way to dynamically sync the requirement. +static const size_t kExtraCharsBeforeAndAfterSelection = 100; + #define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, np_name) \ COMPILE_ASSERT(static_cast<int>(WebCursorInfo::webkit_name) \ == static_cast<int>(np_name), \ @@ -286,6 +293,7 @@ PluginInstance::PluginInstance( plugin_private_interface_(NULL), plugin_pdf_interface_(NULL), plugin_selection_interface_(NULL), + plugin_textinput_interface_(NULL), plugin_zoom_interface_(NULL), checked_for_plugin_input_event_interface_(false), checked_for_plugin_messaging_interface_(false), @@ -303,6 +311,8 @@ PluginInstance::PluginInstance( text_input_caret_(0, 0, 0, 0), text_input_caret_bounds_(0, 0, 0, 0), text_input_caret_set_(false), + selection_caret_(0), + selection_anchor_(0), lock_mouse_callback_(PP_BlockUntilComplete()), pending_user_gesture_(0.0) { pp_instance_ = HostGlobals::Get()->AddInstance(this); @@ -636,6 +646,31 @@ void PluginInstance::SetTextInputType(ui::TextInputType type) { delegate()->PluginTextInputTypeChanged(this); } +void PluginInstance::SelectionChanged() { + // TODO(kinaba): currently the browser always calls RequestSurroundingText. + // It can be optimized so that it won't call it back until the information + // is really needed. + RequestSurroundingText(kExtraCharsBeforeAndAfterSelection); +} + +void PluginInstance::UpdateSurroundingText(const std::string& text, + size_t caret, size_t anchor) { + surrounding_text_ = text; + selection_caret_ = caret; + selection_anchor_ = anchor; + delegate()->PluginSelectionChanged(this); +} + +void PluginInstance::GetSurroundingText(string16* text, + ui::Range* range) const { + std::vector<size_t> offsets; + offsets.push_back(selection_anchor_); + offsets.push_back(selection_caret_); + *text = UTF8ToUTF16AndAdjustOffsets(surrounding_text_, &offsets); + range->set_start(offsets[0] == string16::npos ? text->size() : offsets[0]); + range->set_end(offsets[1] == string16::npos ? text->size() : offsets[1]); +} + bool PluginInstance::IsPluginAcceptingCompositionEvents() const { return (filtered_input_event_mask_ & PP_INPUTEVENT_CLASS_IME) || (input_event_mask_ & PP_INPUTEVENT_CLASS_IME); @@ -904,6 +939,17 @@ string16 PluginInstance::GetLinkAtPosition(const gfx::Point& point) { return link; } +bool PluginInstance::RequestSurroundingText( + size_t desired_number_of_characters) { + // Keep a reference on the stack. See NOTE above. + scoped_refptr<PluginInstance> ref(this); + if (!LoadTextInputInterface()) + return false; + plugin_textinput_interface_->RequestSurroundingText( + pp_instance(), desired_number_of_characters); + return true; +} + void PluginInstance::Zoom(double factor, bool text_only) { // Keep a reference on the stack. See NOTE above. scoped_refptr<PluginInstance> ref(this); @@ -1020,6 +1066,16 @@ bool PluginInstance::LoadSelectionInterface() { return !!plugin_selection_interface_; } +bool PluginInstance::LoadTextInputInterface() { + if (!plugin_textinput_interface_) { + plugin_textinput_interface_ = + static_cast<const PPP_TextInput_Dev*>(module_->GetPluginInterface( + PPP_TEXTINPUT_DEV_INTERFACE)); + } + + return !!plugin_textinput_interface_; +} + bool PluginInstance::LoadZoomInterface() { if (!plugin_zoom_interface_) { plugin_zoom_interface_ = diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.h b/webkit/plugins/ppapi/ppapi_plugin_instance.h index c9387bb..d19a709 100644 --- a/webkit/plugins/ppapi/ppapi_plugin_instance.h +++ b/webkit/plugins/ppapi/ppapi_plugin_instance.h @@ -19,6 +19,7 @@ #include "ppapi/c/dev/ppp_printing_dev.h" #include "ppapi/c/dev/ppp_find_dev.h" #include "ppapi/c/dev/ppp_selection_dev.h" +#include "ppapi/c/dev/ppp_text_input_dev.h" #include "ppapi/c/dev/ppp_zoom_dev.h" #include "ppapi/c/pp_completion_callback.h" #include "ppapi/c/pp_instance.h" @@ -65,6 +66,10 @@ struct PPP_Instance_Combined; class Resource; } +namespace ui { +class Range; +} + namespace webkit { namespace ppapi { @@ -181,11 +186,15 @@ class WEBKIT_PLUGINS_EXPORT PluginInstance : void UpdateCaretPosition(const gfx::Rect& caret, const gfx::Rect& bounding_box); void SetTextInputType(ui::TextInputType type); + void SelectionChanged(); + void UpdateSurroundingText(const std::string& text, + size_t caret, size_t anchor); // Gets the current text input status. ui::TextInputType text_input_type() const { return text_input_type_; } gfx::Rect GetCaretBounds() const; bool IsPluginAcceptingCompositionEvents() const; + void GetSurroundingText(string16* text, ui::Range* range) const; // Notifications about focus changes, see has_webkit_focus_ below. void SetWebKitFocus(bool has_focus); @@ -217,6 +226,7 @@ class WEBKIT_PLUGINS_EXPORT PluginInstance : string16 GetSelectedText(bool html); string16 GetLinkAtPosition(const gfx::Point& point); + bool RequestSurroundingText(size_t desired_number_of_characters); void Zoom(double factor, bool text_only); bool StartFind(const string16& search_text, bool case_sensitive, @@ -402,6 +412,7 @@ class WEBKIT_PLUGINS_EXPORT PluginInstance : bool LoadPrintInterface(); bool LoadPrivateInterface(); bool LoadSelectionInterface(); + bool LoadTextInputInterface(); bool LoadZoomInterface(); // Determines if we think the plugin has focus, both content area and webkit @@ -530,6 +541,7 @@ class WEBKIT_PLUGINS_EXPORT PluginInstance : const PPP_Instance_Private* plugin_private_interface_; const PPP_Pdf* plugin_pdf_interface_; const PPP_Selection_Dev* plugin_selection_interface_; + const PPP_TextInput_Dev* plugin_textinput_interface_; const PPP_Zoom_Dev* plugin_zoom_interface_; // Flags indicating whether we have asked this plugin instance for the @@ -624,6 +636,11 @@ class WEBKIT_PLUGINS_EXPORT PluginInstance : gfx::Rect text_input_caret_bounds_; bool text_input_caret_set_; + // Text selection status. + std::string surrounding_text_; + size_t selection_caret_; + size_t selection_anchor_; + PP_CompletionCallback lock_mouse_callback_; // Track pending user gestures so out-of-process plugins can respond to diff --git a/webkit/plugins/ppapi/ppb_text_input_impl.cc b/webkit/plugins/ppapi/ppb_text_input_impl.cc index 9a1cc92..4fac5ca 100644 --- a/webkit/plugins/ppapi/ppb_text_input_impl.cc +++ b/webkit/plugins/ppapi/ppb_text_input_impl.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -61,5 +61,17 @@ void PPB_TextInput_Impl::CancelCompositionText(PP_Instance instance) { instance_->delegate()->PluginRequestedCancelComposition(instance_); } +void PPB_TextInput_Impl::SelectionChanged(PP_Instance instance) { + instance_->SelectionChanged(); +} + +void PPB_TextInput_Impl::UpdateSurroundingText(PP_Instance instance, + const char* text, + uint32_t caret, + uint32_t anchor) { + instance_->UpdateSurroundingText(text, caret, anchor); +} + + } // namespace ppapi } // namespace webkit diff --git a/webkit/plugins/ppapi/ppb_text_input_impl.h b/webkit/plugins/ppapi/ppb_text_input_impl.h index b6d25e1..20978480 100644 --- a/webkit/plugins/ppapi/ppb_text_input_impl.h +++ b/webkit/plugins/ppapi/ppb_text_input_impl.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -32,6 +32,11 @@ class PPB_TextInput_Impl const PP_Rect& caret, const PP_Rect& bounding_box) OVERRIDE; virtual void CancelCompositionText(PP_Instance instance) OVERRIDE; + virtual void SelectionChanged(PP_Instance instance) OVERRIDE; + virtual void UpdateSurroundingText(PP_Instance instance, + const char* text, + uint32_t caret, + uint32_t anchor) OVERRIDE; private: PluginInstance* instance_; |