Index: webkit/plugins/ppapi/ppapi_plugin_instance.cc |
diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.cc b/webkit/plugins/ppapi/ppapi_plugin_instance.cc |
index 435cafb1f1b9eec4222632f70f431fcd6287e033..32a76594535d707f1c149757bce63db6d756ee78 100644 |
--- a/webkit/plugins/ppapi/ppapi_plugin_instance.cc |
+++ b/webkit/plugins/ppapi/ppapi_plugin_instance.cc |
@@ -8,6 +8,7 @@ |
#include "base/memory/scoped_ptr.h" |
#include "base/message_loop.h" |
#include "base/metrics/histogram.h" |
+#include "base/utf_offset_string_conversions.h" |
#include "base/utf_string_conversions.h" |
#include "ppapi/c/dev/ppb_console_dev.h" |
#include "ppapi/c/dev/ppb_find_dev.h" |
@@ -32,6 +33,7 @@ |
#include "ppapi/c/private/ppp_instance_private.h" |
#include "ppapi/shared_impl/input_event_impl.h" |
#include "ppapi/shared_impl/resource.h" |
+#include "ppapi/shared_impl/time_conversion.h" |
#include "ppapi/shared_impl/var.h" |
#include "ppapi/thunk/enter.h" |
#include "ppapi/thunk/ppb_buffer_api.h" |
@@ -246,6 +248,22 @@ PluginInstance::PluginInstance( |
sad_plugin_(NULL), |
input_event_mask_(0), |
filtered_input_event_mask_(0), |
+#if !defined(TOUCH_UI) |
brettw
2011/10/03 16:46:01
I think having these ifdefs and comments in the in
kinaba
2011/10/05 04:43:19
Done. It now looks much better, thanks!
|
+ // The default mode is to regard the plugin always accept text input. |
+ // This is for allowing users to use input methods even on completely-IME- |
+ // unaware plugins (e.g., PPAPI Flash or PDF plugin for M16). |
+ // Plugins need to explicitly opt out the text input mode if they know |
+ // that they don't accept texts. |
+ text_input_type_(ui::TEXT_INPUT_TYPE_TEXT), |
+#else |
+ // On the other hand, for touch ui, accepting text input implies to pop up |
+ // virtual keyboard always. It makes IME-unaware plugins almost unusable, |
+ // and hence is disabled by default (codereview.chromium.org/7800044). |
+ text_input_type_(ui::TEXT_INPUT_TYPE_NONE), |
+#endif |
+ text_input_caret_(0,0,0,0), |
brettw
2011/10/03 16:46:01
Can you put spaces after the commas?
kinaba
2011/10/05 04:43:19
Done.
|
+ text_input_caret_bounds_(0,0,0,0), |
+ text_input_caret_set_(false), |
lock_mouse_callback_(PP_BlockUntilComplete()) { |
pp_instance_ = ResourceTracker::Get()->AddInstance(this); |
@@ -450,6 +468,144 @@ bool PluginInstance::HandleDocumentLoad(PPB_URLLoader_Impl* loader) { |
pp_instance(), loader->pp_resource())); |
} |
+bool PluginInstance::SendCompositionEventToPlugin(PP_InputEvent_Type type, |
+ const string16& text) { |
+ std::vector<WebKit::WebCompositionUnderline> empty; |
+ return SendCompositionEventWithUnderlineInformationToPlugin( |
+ type, text, empty, static_cast<int>(text.size()), |
+ static_cast<int>(text.size())); |
+} |
+ |
+bool PluginInstance::SendCompositionEventWithUnderlineInformationToPlugin( |
+ PP_InputEvent_Type type, |
+ const string16& text, |
+ const std::vector<WebKit::WebCompositionUnderline>& underlines, |
+ int selection_start, |
+ int selection_end) { |
+ // Keep a reference on the stack. See NOTE above. |
+ scoped_refptr<PluginInstance> ref(this); |
+ |
+ if (!LoadInputEventInterface()) |
+ return false; |
+ |
+ PP_InputEvent_Class event_class = PP_INPUTEVENT_CLASS_IME; |
+ if (!(filtered_input_event_mask_ & event_class) && |
+ !(input_event_mask_ & event_class)) |
+ return false; |
+ |
+ ::ppapi::InputEventData event; |
+ event.event_type = type; |
+ event.event_time_stamp = ::ppapi::TimeTicksToPPTimeTicks( |
+ base::TimeTicks::Now()); |
+ |
+ // Convert UTF16 text to UTF8 with offset conversion. |
+ std::vector<size_t> utf16_offsets; |
+ utf16_offsets.push_back(selection_start); |
+ utf16_offsets.push_back(selection_end); |
+ for (size_t i=0; i<underlines.size(); ++i) { |
brettw
2011/10/03 16:46:01
Can you put spaces around the = and < (same in the
kinaba
2011/10/05 04:43:19
Done.
|
+ utf16_offsets.push_back(underlines[i].startOffset); |
+ utf16_offsets.push_back(underlines[i].endOffset); |
+ } |
+ std::vector<size_t> utf8_offsets(utf16_offsets); |
+ event.character_text = UTF16ToUTF8AndAdjustOffsets(text, &utf8_offsets); |
+ |
+ // Set the converted selection range. |
+ event.composition_selection_start = (utf8_offsets[0]==std::string::npos ? |
brettw
2011/10/03 16:46:01
Spaces around the == (same below)
kinaba
2011/10/05 04:43:19
Done.
|
+ event.character_text.size() : utf8_offsets[0]); |
+ event.composition_selection_end = (utf8_offsets[1]==std::string::npos ? |
+ event.character_text.size() : utf8_offsets[1]); |
+ |
+ // Set the converted segmentation points. |
+ // Be sure to add 0 and size(), and remove duplication or errors. |
+ std::set<size_t> offset_set(utf8_offsets.begin()+2, utf8_offsets.end()); |
+ offset_set.insert(0); |
+ offset_set.insert(event.character_text.size()); |
+ offset_set.erase(std::string::npos); |
+ event.composition_segment_offsets.assign(offset_set.begin(), |
+ offset_set.end()); |
+ |
+ // Set the composition target. |
+ for (size_t i=0; i<underlines.size(); ++i) { |
+ if (underlines[i].thick) { |
+ std::vector<uint32_t>::iterator it = |
+ std::find(event.composition_segment_offsets.begin(), |
+ event.composition_segment_offsets.end(), |
+ utf8_offsets[2*i+2]); |
+ if (it != event.composition_segment_offsets.end()) { |
+ event.composition_target_segment = |
+ it - event.composition_segment_offsets.begin(); |
+ break; |
+ } |
+ } |
+ } |
+ |
+ // Send the event. |
+ if (filtered_input_event_mask_ & event_class) |
+ event.is_filtered = true; |
+ scoped_refptr<InputEventImpl> event_resource( |
+ new InputEventImpl(InputEventImpl::InitAsImpl(), |
+ pp_instance(), event)); |
+ return PP_ToBool(plugin_input_event_interface_->HandleInputEvent( |
brettw
2011/10/03 16:46:01
Can you make it always return true if the event is
kinaba
2011/10/05 04:43:19
Done.
|
+ pp_instance(), event_resource->pp_resource())); |
+} |
+ |
+bool PluginInstance::HandleCompositionStart(const string16& text) { |
+ return SendCompositionEventToPlugin(PP_INPUTEVENT_TYPE_IME_COMPOSITION_START, |
+ text); |
+} |
+ |
+bool PluginInstance::HandleCompositionUpdate( |
+ const string16& text, |
+ const std::vector<WebKit::WebCompositionUnderline>& underlines, |
+ int selection_start, |
+ int selection_end) { |
+ return SendCompositionEventWithUnderlineInformationToPlugin( |
+ PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE, |
+ text, underlines, selection_start, selection_end); |
+} |
+ |
+bool PluginInstance::HandleCompositionEnd(const string16& text) { |
+ return SendCompositionEventToPlugin(PP_INPUTEVENT_TYPE_IME_COMPOSITION_END, |
+ text); |
+} |
+ |
+bool PluginInstance::HandleTextInput(const string16& text) { |
+ return SendCompositionEventToPlugin(PP_INPUTEVENT_TYPE_IME_TEXT, |
+ text); |
+} |
+ |
+void PluginInstance::UpdateCaretPosition(const gfx::Rect& caret, |
+ const gfx::Rect& bounding_box) { |
+ text_input_caret_ = caret; |
+ text_input_caret_bounds_ = bounding_box; |
+ text_input_caret_set_ = true; |
+} |
+ |
+void PluginInstance::SetTextInputType(ui::TextInputType type) { |
+ text_input_type_ = type; |
+} |
+ |
+bool PluginInstance::IsPluginAcceptingCompositionEvents() const { |
+ return (filtered_input_event_mask_ & PP_INPUTEVENT_CLASS_IME) || |
+ (input_event_mask_ & PP_INPUTEVENT_CLASS_IME); |
+} |
+ |
+gfx::Rect PluginInstance::GetCaretBounds() const { |
+ if (!text_input_caret_set_) { |
+ // If it is never set by the plugin, use the bottom left corner. |
+ return gfx::Rect(position().x(), position().y()+position().height(), 0, 0); |
+ } |
+ |
+ // TODO(kinaba) Take CSS transformation into accont. |
+ // TODO(kinaba) Take bounding_box into account. On some platforms, an |
+ // "exclude rectangle" where candidate window must avoid the region can be |
+ // passed to IME. Currently, we pass only the caret rectangle because |
+ // it is the only information supported uniformly in Chromium. |
+ gfx::Rect caret(text_input_caret_); |
+ caret.Offset(position().origin()); |
+ return caret; |
+} |
+ |
bool PluginInstance::HandleInputEvent(const WebKit::WebInputEvent& event, |
WebCursorInfo* cursor_info) { |
// Don't dispatch input events to crashed plugins. |
@@ -552,7 +708,7 @@ void PluginInstance::SetWebKitFocus(bool has_focus) { |
bool old_plugin_focus = PluginHasFocus(); |
has_webkit_focus_ = has_focus; |
if (PluginHasFocus() != old_plugin_focus) { |
- delegate()->PluginFocusChanged(PluginHasFocus()); |
+ delegate()->PluginFocusChanged(this, PluginHasFocus()); |
instance_interface_->DidChangeFocus(pp_instance(), |
PP_FromBool(PluginHasFocus())); |
} |