summaryrefslogtreecommitdiffstats
path: root/ppapi
diff options
context:
space:
mode:
authorkinaba@chromium.org <kinaba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-21 07:09:32 +0000
committerkinaba@chromium.org <kinaba@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-21 07:09:32 +0000
commit397c2396865ba5bd314827141f647a47d1cbb3fb (patch)
treea6b3972a4d3904940df315b8385aa77b625d4541 /ppapi
parent455258051a2cb4591155cd099e959ce593340736 (diff)
downloadchromium_src-397c2396865ba5bd314827141f647a47d1cbb3fb.zip
chromium_src-397c2396865ba5bd314827141f647a47d1cbb3fb.tar.gz
chromium_src-397c2396865ba5bd314827141f647a47d1cbb3fb.tar.bz2
Test for Pepper IME events.
This patch adds a way to simulate IME composition events inside the renderer process, and tests that IME events are properly passed between the renderer and plugins. ppapi/tests/test_ime_input_event.cc: is the actual test case ppapi/{api,c,cpp}/dev/*ime_input_event_dev*: implements an API to create IME events from plugins for testing. other files: wire necessary stuff for simulating IME events. Since Pepper IME events are not delivered through WebKit/DOM layer but rather directly sent from renderer to plugins, the simulation part also follows the similar code path. BUG=126714 TEST=browser_tests PPAPITest.ImeInputEvent Review URL: https://chromiumcodereview.appspot.com/10391101 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@138080 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi')
-rw-r--r--ppapi/api/dev/ppb_ime_input_event_dev.idl52
-rw-r--r--ppapi/c/dev/ppb_ime_input_event_dev.h66
-rw-r--r--ppapi/cpp/dev/ime_input_event_dev.cc112
-rw-r--r--ppapi/cpp/dev/ime_input_event_dev.h31
-rw-r--r--ppapi/ppapi_sources.gypi2
-rw-r--r--ppapi/proxy/resource_creation_proxy.cc71
-rw-r--r--ppapi/proxy/resource_creation_proxy.h9
-rw-r--r--ppapi/shared_impl/ppb_input_event_shared.cc118
-rw-r--r--ppapi/shared_impl/ppb_input_event_shared.h36
-rw-r--r--ppapi/tests/test_ime_input_event.cc425
-rw-r--r--ppapi/tests/test_ime_input_event.h60
-rw-r--r--ppapi/thunk/interfaces_ppb_public_dev.h2
-rw-r--r--ppapi/thunk/ppb_input_event_thunk.cc38
-rw-r--r--ppapi/thunk/resource_creation_api.h9
14 files changed, 946 insertions, 85 deletions
diff --git a/ppapi/api/dev/ppb_ime_input_event_dev.idl b/ppapi/api/dev/ppb_ime_input_event_dev.idl
index 3e2deba..9e728d6 100644
--- a/ppapi/api/dev/ppb_ime_input_event_dev.idl
+++ b/ppapi/api/dev/ppb_ime_input_event_dev.idl
@@ -8,12 +8,60 @@
*/
label Chrome {
- M16 = 0.1
+ M16 = 0.1,
+ M21 = 0.2
};
-[version=0.1, macro="PPB_IME_INPUT_EVENT_DEV_INTERFACE"]
+[macro="PPB_IME_INPUT_EVENT_DEV_INTERFACE"]
interface PPB_IMEInputEvent_Dev {
/**
+ * Create() creates an IME input event with the given parameters. Normally
+ * you will get an IME event passed through the <code>HandleInputEvent</code>
+ * and will not need to create them, but some applications may want to create
+ * their own for internal use.
+ *
+ * @param[in] instance The instance for which this event occurred.
+ *
+ * @param[in] type A <code>PP_InputEvent_Type</code> identifying the type of
+ * input event. The type must be one of the IME event types.
+ *
+ * @param[in] time_stamp A <code>PP_TimeTicks</code> indicating the time
+ * when the event occurred.
+ *
+ * @param[in] text The string returned by <code>GetText</code>.
+ *
+ * @param[in] segment_number The number returned by
+ * <code>GetSegmentNumber</code>.
+ *
+ * @param[in] segment_offsets The array of numbers returned by
+ * <code>GetSegmentOffset</code>. If <code>segment_number</code> is zero,
+ * the number of elements of the array should be zero. If
+ * <code>segment_number</code> is non-zero, the length of the array must be
+ * <code>segment_number</code> + 1.
+ *
+ * @param[in] target_segment The number returned by
+ * <code>GetTargetSegment</code>.
+ *
+ * @param[in] selection_start The start index returned by
+ * <code>GetSelection</code>.
+ *
+ * @param[in] selection_end The end index returned by
+ * <code>GetSelection</code>.
+ *
+ * @return A <code>PP_Resource</code> containing the new IME input event.
+ */
+ [version=0.2]
+ PP_Resource Create([in] PP_Instance instance,
+ [in] PP_InputEvent_Type type,
+ [in] PP_TimeTicks time_stamp,
+ [in] PP_Var text,
+ [in] uint32_t segment_number,
+ [in] uint32_t[] segment_offsets,
+ [in] int32_t target_segment,
+ [in] uint32_t selection_start,
+ [in] uint32_t selection_end);
+
+ /**
* IsIMEInputEvent() determines if a resource is an IME event.
*
* @param[in] resource A <code>PP_Resource</code> corresponding to an event.
diff --git a/ppapi/c/dev/ppb_ime_input_event_dev.h b/ppapi/c/dev/ppb_ime_input_event_dev.h
index cb1af78..590a1d9 100644
--- a/ppapi/c/dev/ppb_ime_input_event_dev.h
+++ b/ppapi/c/dev/ppb_ime_input_event_dev.h
@@ -3,19 +3,23 @@
* found in the LICENSE file.
*/
-/* From dev/ppb_ime_input_event_dev.idl modified Wed Oct 5 14:06:02 2011. */
+/* From dev/ppb_ime_input_event_dev.idl modified Wed May 16 17:08:03 2012. */
#ifndef PPAPI_C_DEV_PPB_IME_INPUT_EVENT_DEV_H_
#define PPAPI_C_DEV_PPB_IME_INPUT_EVENT_DEV_H_
#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_macros.h"
#include "ppapi/c/pp_resource.h"
#include "ppapi/c/pp_stdint.h"
+#include "ppapi/c/pp_time.h"
#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppb_input_event.h"
#define PPB_IME_INPUT_EVENT_DEV_INTERFACE_0_1 "PPB_IMEInputEvent(Dev);0.1"
-#define PPB_IME_INPUT_EVENT_DEV_INTERFACE PPB_IME_INPUT_EVENT_DEV_INTERFACE_0_1
+#define PPB_IME_INPUT_EVENT_DEV_INTERFACE_0_2 "PPB_IMEInputEvent(Dev);0.2"
+#define PPB_IME_INPUT_EVENT_DEV_INTERFACE PPB_IME_INPUT_EVENT_DEV_INTERFACE_0_2
/**
* @file
@@ -27,7 +31,52 @@
* @addtogroup Interfaces
* @{
*/
-struct PPB_IMEInputEvent_Dev_0_1 {
+struct PPB_IMEInputEvent_Dev_0_2 {
+ /**
+ * Create() creates an IME input event with the given parameters. Normally
+ * you will get an IME event passed through the <code>HandleInputEvent</code>
+ * and will not need to create them, but some applications may want to create
+ * their own for internal use.
+ *
+ * @param[in] instance The instance for which this event occurred.
+ *
+ * @param[in] type A <code>PP_InputEvent_Type</code> identifying the type of
+ * input event. The type must be one of the IME event types.
+ *
+ * @param[in] time_stamp A <code>PP_TimeTicks</code> indicating the time
+ * when the event occurred.
+ *
+ * @param[in] text The string returned by <code>GetText</code>.
+ *
+ * @param[in] segment_number The number returned by
+ * <code>GetSegmentNumber</code>.
+ *
+ * @param[in] segment_offsets The array of numbers returned by
+ * <code>GetSegmentOffset</code>. If <code>segment_number</code> is zero,
+ * the number of elements of the array should be zero. If
+ * <code>segment_number</code> is non-zero, the length of the array must be
+ * <code>segment_number</code> + 1.
+ *
+ * @param[in] target_segment The number returned by
+ * <code>GetTargetSegment</code>.
+ *
+ * @param[in] selection_start The start index returned by
+ * <code>GetSelection</code>.
+ *
+ * @param[in] selection_end The end index returned by
+ * <code>GetSelection</code>.
+ *
+ * @return A <code>PP_Resource</code> containing the new IME input event.
+ */
+ PP_Resource (*Create)(PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ struct PP_Var text,
+ uint32_t segment_number,
+ const uint32_t segment_offsets[],
+ int32_t target_segment,
+ uint32_t selection_start,
+ uint32_t selection_end);
/**
* IsIMEInputEvent() determines if a resource is an IME event.
*
@@ -101,7 +150,16 @@ struct PPB_IMEInputEvent_Dev_0_1 {
void (*GetSelection)(PP_Resource ime_event, uint32_t* start, uint32_t* end);
};
-typedef struct PPB_IMEInputEvent_Dev_0_1 PPB_IMEInputEvent_Dev;
+typedef struct PPB_IMEInputEvent_Dev_0_2 PPB_IMEInputEvent_Dev;
+
+struct PPB_IMEInputEvent_Dev_0_1 {
+ PP_Bool (*IsIMEInputEvent)(PP_Resource resource);
+ struct PP_Var (*GetText)(PP_Resource ime_event);
+ uint32_t (*GetSegmentNumber)(PP_Resource ime_event);
+ uint32_t (*GetSegmentOffset)(PP_Resource ime_event, uint32_t index);
+ int32_t (*GetTargetSegment)(PP_Resource ime_event);
+ void (*GetSelection)(PP_Resource ime_event, uint32_t* start, uint32_t* end);
+};
/**
* @}
*/
diff --git a/ppapi/cpp/dev/ime_input_event_dev.cc b/ppapi/cpp/dev/ime_input_event_dev.cc
index 6f920e9..99fe66d 100644
--- a/ppapi/cpp/dev/ime_input_event_dev.cc
+++ b/ppapi/cpp/dev/ime_input_event_dev.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.
@@ -13,8 +13,12 @@ namespace pp {
namespace {
-template <> const char* interface_name<PPB_IMEInputEvent_Dev>() {
- return PPB_IME_INPUT_EVENT_DEV_INTERFACE;
+template <> const char* interface_name<PPB_IMEInputEvent_Dev_0_2>() {
+ return PPB_IME_INPUT_EVENT_DEV_INTERFACE_0_2;
+}
+
+template <> const char* interface_name<PPB_IMEInputEvent_Dev_0_1>() {
+ return PPB_IME_INPUT_EVENT_DEV_INTERFACE_0_1;
}
} // namespace
@@ -25,51 +29,101 @@ IMEInputEvent_Dev::IMEInputEvent_Dev() : InputEvent() {
}
IMEInputEvent_Dev::IMEInputEvent_Dev(const InputEvent& event) : InputEvent() {
- // Type check the input event before setting it.
- if (!has_interface<PPB_IMEInputEvent_Dev>())
- return;
- if (get_interface<PPB_IMEInputEvent_Dev>()->IsIMEInputEvent(
- event.pp_resource())) {
+ bool is_ime_event = false;
+ if (has_interface<PPB_IMEInputEvent_Dev_0_2>()) {
+ if (get_interface<PPB_IMEInputEvent_Dev_0_2>()->IsIMEInputEvent(
+ event.pp_resource())) {
+ is_ime_event = true;
+ }
+ } else if (has_interface<PPB_IMEInputEvent_Dev_0_1>()) {
+ if (get_interface<PPB_IMEInputEvent_Dev_0_1>()->IsIMEInputEvent(
+ event.pp_resource())) {
+ is_ime_event = true;
+ }
+ }
+
+ if (is_ime_event) {
Module::Get()->core()->AddRefResource(event.pp_resource());
PassRefFromConstructor(event.pp_resource());
}
}
+IMEInputEvent_Dev::IMEInputEvent_Dev(
+ const InstanceHandle& instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ Var text,
+ const std::vector<uint32_t>& segment_offsets,
+ int32_t target_segment,
+ const std::pair<uint32_t, uint32_t>& selection) : InputEvent() {
+ if (!has_interface<PPB_IMEInputEvent_Dev_0_2>())
+ return;
+ uint32_t dummy = 0;
+ PassRefFromConstructor(get_interface<PPB_IMEInputEvent_Dev_0_2>()->Create(
+ instance.pp_instance(), type, time_stamp, text.pp_var(),
+ segment_offsets.empty() ? 0 : segment_offsets.size() - 1,
+ segment_offsets.empty() ? &dummy : &segment_offsets[0],
+ target_segment, selection.first, selection.second));
+}
+
+
Var IMEInputEvent_Dev::GetText() const {
- if (!has_interface<PPB_IMEInputEvent_Dev>())
- return Var();
- return Var(PASS_REF,
- get_interface<PPB_IMEInputEvent_Dev>()->GetText(pp_resource()));
+ if (has_interface<PPB_IMEInputEvent_Dev_0_2>()) {
+ return Var(PASS_REF,
+ get_interface<PPB_IMEInputEvent_Dev_0_2>()->GetText(
+ pp_resource()));
+ } else if (has_interface<PPB_IMEInputEvent_Dev_0_1>()) {
+ return Var(PASS_REF,
+ get_interface<PPB_IMEInputEvent_Dev_0_1>()->GetText(
+ pp_resource()));
+ }
+ return Var();
}
uint32_t IMEInputEvent_Dev::GetSegmentNumber() const {
- if (!has_interface<PPB_IMEInputEvent_Dev>())
- return 0;
- return get_interface<PPB_IMEInputEvent_Dev>()->GetSegmentNumber(
- pp_resource());
+ if (has_interface<PPB_IMEInputEvent_Dev_0_2>()) {
+ return get_interface<PPB_IMEInputEvent_Dev_0_2>()->GetSegmentNumber(
+ pp_resource());
+ } else if (has_interface<PPB_IMEInputEvent_Dev_0_1>()) {
+ return get_interface<PPB_IMEInputEvent_Dev_0_1>()->GetSegmentNumber(
+ pp_resource());
+ }
+ return 0;
}
uint32_t IMEInputEvent_Dev::GetSegmentOffset(uint32_t index) const {
- if (!has_interface<PPB_IMEInputEvent_Dev>())
- return 0;
- return get_interface<PPB_IMEInputEvent_Dev>()->GetSegmentOffset(pp_resource(),
- index);
+ if (has_interface<PPB_IMEInputEvent_Dev_0_2>()) {
+ return get_interface<PPB_IMEInputEvent_Dev_0_2>()->GetSegmentOffset(
+ pp_resource(), index);
+ } else if (has_interface<PPB_IMEInputEvent_Dev_0_1>()) {
+ return get_interface<PPB_IMEInputEvent_Dev_0_1>()->GetSegmentOffset(
+ pp_resource(), index);
+ }
+ return 0;
}
int32_t IMEInputEvent_Dev::GetTargetSegment() const {
- if (!has_interface<PPB_IMEInputEvent_Dev>())
- return 0;
- return get_interface<PPB_IMEInputEvent_Dev>()->GetTargetSegment(
- pp_resource());
+ if (has_interface<PPB_IMEInputEvent_Dev_0_2>()) {
+ return get_interface<PPB_IMEInputEvent_Dev_0_2>()->GetTargetSegment(
+ pp_resource());
+ } else if (has_interface<PPB_IMEInputEvent_Dev_0_1>()) {
+ return get_interface<PPB_IMEInputEvent_Dev_0_1>()->GetTargetSegment(
+ pp_resource());
+ }
+ return 0;
}
std::pair<uint32_t, uint32_t> IMEInputEvent_Dev::GetSelection() const {
std::pair<uint32_t, uint32_t> range(0, 0);
- if (!has_interface<PPB_IMEInputEvent_Dev>())
- return range;
- get_interface<PPB_IMEInputEvent_Dev>()->GetSelection(pp_resource(),
- &range.first,
- &range.second);
+ if (has_interface<PPB_IMEInputEvent_Dev_0_2>()) {
+ get_interface<PPB_IMEInputEvent_Dev_0_2>()->GetSelection(pp_resource(),
+ &range.first,
+ &range.second);
+ } else if (has_interface<PPB_IMEInputEvent_Dev_0_1>()) {
+ get_interface<PPB_IMEInputEvent_Dev_0_1>()->GetSelection(pp_resource(),
+ &range.first,
+ &range.second);
+ }
return range;
}
diff --git a/ppapi/cpp/dev/ime_input_event_dev.h b/ppapi/cpp/dev/ime_input_event_dev.h
index 17216a8..b9cb750 100644
--- a/ppapi/cpp/dev/ime_input_event_dev.h
+++ b/ppapi/cpp/dev/ime_input_event_dev.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.
@@ -6,6 +6,7 @@
#define PPAPI_CPP_DEV_IME_INPUT_EVENT_DEV_H_
#include <utility>
+#include <vector>
#include "ppapi/c/dev/ppb_ime_input_event_dev.h"
#include "ppapi/cpp/input_event.h"
@@ -29,6 +30,34 @@ class IMEInputEvent_Dev : public InputEvent {
/// @param[in] event A generic input event.
explicit IMEInputEvent_Dev(const InputEvent& event);
+ /// This constructor manually constructs an IME event from the provided
+ /// parameters.
+ ///
+ /// @param[in] instance The instance for which this event occurred.
+ ///
+ /// @param[in] type A <code>PP_InputEvent_Type</code> identifying the type of
+ /// input event. The type must be one of the ime event types.
+ ///
+ /// @param[in] time_stamp A <code>PP_TimeTicks</code> indicating the time
+ /// when the event occurred.
+ ///
+ /// @param[in] text The string returned by <code>GetText</code>.
+ ///
+ /// @param[in] segment_offsets The array of numbers returned by
+ /// <code>GetSegmentOffset</code>.
+ ///
+ /// @param[in] target_segment The number returned by
+ /// <code>GetTargetSegment</code>.
+ ///
+ /// @param[in] selection The range returned by <code>GetSelection</code>.
+ IMEInputEvent_Dev(const InstanceHandle& instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ Var text,
+ const std::vector<uint32_t>& segment_offsets,
+ int32_t target_segment,
+ const std::pair<uint32_t, uint32_t>& selection);
+
/// Returns the composition text as a UTF-8 string for the given IME event.
///
/// @return A string var representing the composition text. For non-IME
diff --git a/ppapi/ppapi_sources.gypi b/ppapi/ppapi_sources.gypi
index 05cf661..6e6d617 100644
--- a/ppapi/ppapi_sources.gypi
+++ b/ppapi/ppapi_sources.gypi
@@ -335,6 +335,8 @@
'tests/test_host_resolver_private.h',
'tests/test_image_data.cc',
'tests/test_image_data.h',
+ 'tests/test_ime_input_event.cc',
+ 'tests/test_ime_input_event.h',
'tests/test_input_event.cc',
'tests/test_input_event.h',
'tests/test_memory.cc',
diff --git a/ppapi/proxy/resource_creation_proxy.cc b/ppapi/proxy/resource_creation_proxy.cc
index 7a4cc01..b5c254c 100644
--- a/ppapi/proxy/resource_creation_proxy.cc
+++ b/ppapi/proxy/resource_creation_proxy.cc
@@ -76,6 +76,21 @@ PP_Resource ResourceCreationProxy::CreateFileSystem(
return PPB_FileSystem_Proxy::CreateProxyResource(instance, type);
}
+PP_Resource ResourceCreationProxy::CreateIMEInputEvent(
+ PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ struct PP_Var text,
+ uint32_t segment_number,
+ const uint32_t* segment_offsets,
+ int32_t target_segment,
+ uint32_t selection_start,
+ uint32_t selection_end) {
+ return PPB_InputEvent_Shared::CreateIMEInputEvent(
+ OBJECT_IS_PROXY, instance, type, time_stamp, text, segment_number,
+ segment_offsets, target_segment, selection_start, selection_end);
+}
+
PP_Resource ResourceCreationProxy::CreateKeyboardInputEvent(
PP_Instance instance,
PP_InputEvent_Type type,
@@ -83,25 +98,9 @@ PP_Resource ResourceCreationProxy::CreateKeyboardInputEvent(
uint32_t modifiers,
uint32_t key_code,
struct PP_Var character_text) {
- if (type != PP_INPUTEVENT_TYPE_RAWKEYDOWN &&
- type != PP_INPUTEVENT_TYPE_KEYDOWN &&
- type != PP_INPUTEVENT_TYPE_KEYUP &&
- type != PP_INPUTEVENT_TYPE_CHAR)
- return 0;
- InputEventData data;
- data.event_type = type;
- data.event_time_stamp = time_stamp;
- data.event_modifiers = modifiers;
- data.key_code = key_code;
- if (character_text.type == PP_VARTYPE_STRING) {
- StringVar* text_str = StringVar::FromPPVar(character_text);
- if (!text_str)
- return 0;
- data.character_text = text_str->value();
- }
-
- return (new PPB_InputEvent_Shared(OBJECT_IS_PROXY,
- instance, data))->GetReference();
+ return PPB_InputEvent_Shared::CreateKeyboardInputEvent(
+ OBJECT_IS_PROXY, instance, type, time_stamp, modifiers, key_code,
+ character_text);
}
PP_Resource ResourceCreationProxy::CreateMouseInputEvent(
@@ -113,24 +112,9 @@ PP_Resource ResourceCreationProxy::CreateMouseInputEvent(
const PP_Point* mouse_position,
int32_t click_count,
const PP_Point* mouse_movement) {
- if (type != PP_INPUTEVENT_TYPE_MOUSEDOWN &&
- type != PP_INPUTEVENT_TYPE_MOUSEUP &&
- type != PP_INPUTEVENT_TYPE_MOUSEMOVE &&
- type != PP_INPUTEVENT_TYPE_MOUSEENTER &&
- type != PP_INPUTEVENT_TYPE_MOUSELEAVE)
- return 0;
-
- InputEventData data;
- data.event_type = type;
- data.event_time_stamp = time_stamp;
- data.event_modifiers = modifiers;
- data.mouse_button = mouse_button;
- data.mouse_position = *mouse_position;
- data.mouse_click_count = click_count;
- data.mouse_movement = *mouse_movement;
-
- return (new PPB_InputEvent_Shared(OBJECT_IS_PROXY,
- instance, data))->GetReference();
+ return PPB_InputEvent_Shared::CreateMouseInputEvent(
+ OBJECT_IS_PROXY, instance, type, time_stamp, modifiers,
+ mouse_button, mouse_position, click_count, mouse_movement);
}
PP_Resource ResourceCreationProxy::CreateResourceArray(
@@ -160,16 +144,9 @@ PP_Resource ResourceCreationProxy::CreateWheelInputEvent(
const PP_FloatPoint* wheel_delta,
const PP_FloatPoint* wheel_ticks,
PP_Bool scroll_by_page) {
- InputEventData data;
- data.event_type = PP_INPUTEVENT_TYPE_WHEEL;
- data.event_time_stamp = time_stamp;
- data.event_modifiers = modifiers;
- data.wheel_delta = *wheel_delta;
- data.wheel_ticks = *wheel_ticks;
- data.wheel_scroll_by_page = PP_ToBool(scroll_by_page);
-
- return (new PPB_InputEvent_Shared(OBJECT_IS_PROXY,
- instance, data))->GetReference();
+ return PPB_InputEvent_Shared::CreateWheelInputEvent(
+ OBJECT_IS_PROXY, instance, time_stamp, modifiers,
+ wheel_delta, wheel_ticks, scroll_by_page);
}
PP_Resource ResourceCreationProxy::CreateAudio(
diff --git a/ppapi/proxy/resource_creation_proxy.h b/ppapi/proxy/resource_creation_proxy.h
index 2db304d..57af6f8 100644
--- a/ppapi/proxy/resource_creation_proxy.h
+++ b/ppapi/proxy/resource_creation_proxy.h
@@ -41,6 +41,15 @@ class ResourceCreationProxy : public InterfaceProxy,
const char* path) OVERRIDE;
virtual PP_Resource CreateFileSystem(PP_Instance instance,
PP_FileSystemType type) OVERRIDE;
+ virtual PP_Resource CreateIMEInputEvent(PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ struct PP_Var text,
+ uint32_t segment_number,
+ const uint32_t* segment_offsets,
+ int32_t target_segment,
+ uint32_t selection_start,
+ uint32_t selection_end) OVERRIDE;
virtual PP_Resource CreateKeyboardInputEvent(
PP_Instance instance,
PP_InputEvent_Type type,
diff --git a/ppapi/shared_impl/ppb_input_event_shared.cc b/ppapi/shared_impl/ppb_input_event_shared.cc
index cdb0565..7b07de9 100644
--- a/ppapi/shared_impl/ppb_input_event_shared.cc
+++ b/ppapi/shared_impl/ppb_input_event_shared.cc
@@ -127,4 +127,122 @@ void PPB_InputEvent_Shared::GetIMESelection(uint32_t* start, uint32_t* end) {
*end = data_.composition_selection_end;
}
+//static
+PP_Resource PPB_InputEvent_Shared::CreateIMEInputEvent(
+ ResourceObjectType type,
+ PP_Instance instance,
+ PP_InputEvent_Type event_type,
+ PP_TimeTicks time_stamp,
+ struct PP_Var text,
+ uint32_t segment_number,
+ const uint32_t* segment_offsets,
+ int32_t target_segment,
+ uint32_t selection_start,
+ uint32_t selection_end) {
+ if (event_type != PP_INPUTEVENT_TYPE_IME_COMPOSITION_START &&
+ event_type != PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE &&
+ event_type != PP_INPUTEVENT_TYPE_IME_COMPOSITION_END &&
+ event_type != PP_INPUTEVENT_TYPE_IME_TEXT)
+ return 0;
+
+ InputEventData data;
+ data.event_type = event_type;
+ data.event_time_stamp = time_stamp;
+ if (text.type == PP_VARTYPE_STRING) {
+ StringVar* text_str = StringVar::FromPPVar(text);
+ if (!text_str)
+ return 0;
+ data.character_text = text_str->value();
+ }
+ data.composition_target_segment = target_segment;
+ if (segment_number != 0) {
+ data.composition_segment_offsets.assign(
+ &segment_offsets[0], &segment_offsets[segment_number + 1]);
+ }
+ data.composition_selection_start = selection_start;
+ data.composition_selection_end = selection_end;
+
+ return (new PPB_InputEvent_Shared(type, instance, data))->GetReference();
+}
+
+//static
+PP_Resource PPB_InputEvent_Shared::CreateKeyboardInputEvent(
+ ResourceObjectType type,
+ PP_Instance instance,
+ PP_InputEvent_Type event_type,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers,
+ uint32_t key_code,
+ struct PP_Var character_text) {
+ if (event_type != PP_INPUTEVENT_TYPE_RAWKEYDOWN &&
+ event_type != PP_INPUTEVENT_TYPE_KEYDOWN &&
+ event_type != PP_INPUTEVENT_TYPE_KEYUP &&
+ event_type != PP_INPUTEVENT_TYPE_CHAR)
+ return 0;
+
+ InputEventData data;
+ data.event_type = event_type;
+ data.event_time_stamp = time_stamp;
+ data.event_modifiers = modifiers;
+ data.key_code = key_code;
+ if (character_text.type == PP_VARTYPE_STRING) {
+ StringVar* text_str = StringVar::FromPPVar(character_text);
+ if (!text_str)
+ return 0;
+ data.character_text = text_str->value();
+ }
+
+ return (new PPB_InputEvent_Shared(type, instance, data))->GetReference();
+}
+
+//static
+PP_Resource PPB_InputEvent_Shared::CreateMouseInputEvent(
+ ResourceObjectType type,
+ PP_Instance instance,
+ PP_InputEvent_Type event_type,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers,
+ PP_InputEvent_MouseButton mouse_button,
+ const PP_Point* mouse_position,
+ int32_t click_count,
+ const PP_Point* mouse_movement) {
+ if (event_type != PP_INPUTEVENT_TYPE_MOUSEDOWN &&
+ event_type != PP_INPUTEVENT_TYPE_MOUSEUP &&
+ event_type != PP_INPUTEVENT_TYPE_MOUSEMOVE &&
+ event_type != PP_INPUTEVENT_TYPE_MOUSEENTER &&
+ event_type != PP_INPUTEVENT_TYPE_MOUSELEAVE)
+ return 0;
+
+ InputEventData data;
+ data.event_type = event_type;
+ data.event_time_stamp = time_stamp;
+ data.event_modifiers = modifiers;
+ data.mouse_button = mouse_button;
+ data.mouse_position = *mouse_position;
+ data.mouse_click_count = click_count;
+ data.mouse_movement = *mouse_movement;
+
+ return (new PPB_InputEvent_Shared(type, instance, data))->GetReference();
+}
+
+//static
+PP_Resource PPB_InputEvent_Shared::CreateWheelInputEvent(
+ ResourceObjectType type,
+ PP_Instance instance,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers,
+ const PP_FloatPoint* wheel_delta,
+ const PP_FloatPoint* wheel_ticks,
+ PP_Bool scroll_by_page) {
+ InputEventData data;
+ data.event_type = PP_INPUTEVENT_TYPE_WHEEL;
+ data.event_time_stamp = time_stamp;
+ data.event_modifiers = modifiers;
+ data.wheel_delta = *wheel_delta;
+ data.wheel_ticks = *wheel_ticks;
+ data.wheel_scroll_by_page = PP_ToBool(scroll_by_page);
+
+ return (new PPB_InputEvent_Shared(type, instance, data))->GetReference();
+}
+
} // namespace ppapi
diff --git a/ppapi/shared_impl/ppb_input_event_shared.h b/ppapi/shared_impl/ppb_input_event_shared.h
index c62befa..74108b3 100644
--- a/ppapi/shared_impl/ppb_input_event_shared.h
+++ b/ppapi/shared_impl/ppb_input_event_shared.h
@@ -84,6 +84,42 @@ class PPAPI_SHARED_EXPORT PPB_InputEvent_Shared
virtual int32_t GetIMETargetSegment() OVERRIDE;
virtual void GetIMESelection(uint32_t* start, uint32_t* end) OVERRIDE;
+ // Implementations for event creation.
+ static PP_Resource CreateIMEInputEvent(ResourceObjectType type,
+ PP_Instance instance,
+ PP_InputEvent_Type event_type,
+ PP_TimeTicks time_stamp,
+ struct PP_Var text,
+ uint32_t segment_number,
+ const uint32_t* segment_offsets,
+ int32_t target_segment,
+ uint32_t selection_start,
+ uint32_t selection_end);
+ static PP_Resource CreateKeyboardInputEvent(ResourceObjectType type,
+ PP_Instance instance,
+ PP_InputEvent_Type event_type,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers,
+ uint32_t key_code,
+ struct PP_Var character_text);
+ static PP_Resource CreateMouseInputEvent(
+ ResourceObjectType type,
+ PP_Instance instance,
+ PP_InputEvent_Type event_type,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers,
+ PP_InputEvent_MouseButton mouse_button,
+ const PP_Point* mouse_position,
+ int32_t click_count,
+ const PP_Point* mouse_movement);
+ static PP_Resource CreateWheelInputEvent(ResourceObjectType type,
+ PP_Instance instance,
+ PP_TimeTicks time_stamp,
+ uint32_t modifiers,
+ const PP_FloatPoint* wheel_delta,
+ const PP_FloatPoint* wheel_ticks,
+ PP_Bool scroll_by_page);
+
private:
InputEventData data_;
diff --git a/ppapi/tests/test_ime_input_event.cc b/ppapi/tests/test_ime_input_event.cc
new file mode 100644
index 0000000..804e17d7a
--- /dev/null
+++ b/ppapi/tests/test_ime_input_event.cc
@@ -0,0 +1,425 @@
+// 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/tests/test_ime_input_event.h"
+
+#include "ppapi/c/dev/ppb_ime_input_event_dev.h"
+#include "ppapi/c/dev/ppb_testing_dev.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/ppb_input_event.h"
+#include "ppapi/cpp/dev/ime_input_event_dev.h"
+#include "ppapi/cpp/input_event.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/tests/test_utils.h"
+#include "ppapi/tests/testing_instance.h"
+
+REGISTER_TEST_CASE(ImeInputEvent);
+
+namespace {
+
+// Japanese Kanji letters meaning "a string" ('mo' 'ji' 'retsu' in Kanji)
+const char* kCompositionChar[] = {
+ "\xE6\x96\x87", "\xE5\xAD\x97", "\xE5\x88\x97"
+};
+
+const char kCompositionText[] = "\xE6\x96\x87\xE5\xAD\x97\xE5\x88\x97";
+
+#define FINISHED_WAITING_MESSAGE "TEST_IME_INPUT_EVENT_FINISHED_WAITING"
+
+} // namespace
+
+TestImeInputEvent::TestImeInputEvent(TestingInstance* instance)
+ : TestCase(instance),
+ input_event_interface_(NULL),
+ keyboard_input_event_interface_(NULL),
+ ime_input_event_interface_(NULL),
+ received_unexpected_event_(true),
+ received_finish_message_(false) {
+}
+
+TestImeInputEvent::~TestImeInputEvent() {
+ // Remove the special listener that only responds to a
+ // FINISHED_WAITING_MESSAGE string. See Init for where it gets added.
+ std::string js_code;
+ js_code = "var plugin = document.getElementById('plugin');"
+ "plugin.removeEventListener('message',"
+ " plugin.wait_for_messages_handler);"
+ "delete plugin.wait_for_messages_handler;";
+ instance_->EvalScript(js_code);
+}
+
+void TestImeInputEvent::RunTests(const std::string& filter) {
+ RUN_TEST(ImeCommit, filter);
+ RUN_TEST(ImeCancel, filter);
+ RUN_TEST(ImeUnawareCommit, filter);
+ RUN_TEST(ImeUnawareCancel, filter);
+}
+
+bool TestImeInputEvent::Init() {
+ input_event_interface_ = static_cast<const PPB_InputEvent*>(
+ pp::Module::Get()->GetBrowserInterface(PPB_INPUT_EVENT_INTERFACE));
+ keyboard_input_event_interface_ =
+ static_cast<const PPB_KeyboardInputEvent*>(
+ pp::Module::Get()->GetBrowserInterface(
+ PPB_KEYBOARD_INPUT_EVENT_INTERFACE));
+ ime_input_event_interface_ = static_cast<const PPB_IMEInputEvent_Dev*>(
+ pp::Module::Get()->GetBrowserInterface(
+ PPB_IME_INPUT_EVENT_DEV_INTERFACE));
+
+ bool success =
+ input_event_interface_ &&
+ keyboard_input_event_interface_ &&
+ ime_input_event_interface_ &&
+ CheckTestingInterface();
+
+ // Set up a listener for our message that signals that all input events have
+ // been received.
+ // Note the following code is dependent on some features of test_case.html.
+ // E.g., it is assumed that the DOM element where the plugin is embedded has
+ // an id of 'plugin', and there is a function 'IsTestingMessage' that allows
+ // us to ignore the messages that are intended for use by the testing
+ // framework itself.
+ std::string js_code =
+ "var plugin = document.getElementById('plugin');"
+ "var wait_for_messages_handler = function(message_event) {"
+ " if (!IsTestingMessage(message_event.data) &&"
+ " message_event.data === '" FINISHED_WAITING_MESSAGE "') {"
+ " plugin.postMessage('" FINISHED_WAITING_MESSAGE "');"
+ " }"
+ "};"
+ "plugin.addEventListener('message', wait_for_messages_handler);"
+ // Stash it on the plugin so we can remove it in the destructor.
+ "plugin.wait_for_messages_handler = wait_for_messages_handler;";
+ instance_->EvalScript(js_code);
+
+ return success;
+}
+
+bool TestImeInputEvent::HandleInputEvent(const pp::InputEvent& input_event) {
+ // Check whether the IME related events comes in the expected order.
+ switch (input_event.GetType()) {
+ case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START:
+ case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE:
+ case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END:
+ case PP_INPUTEVENT_TYPE_IME_TEXT:
+ case PP_INPUTEVENT_TYPE_CHAR:
+ if (expected_events_.empty()) {
+ received_unexpected_event_ = true;
+ } else {
+ received_unexpected_event_ =
+ !AreEquivalentEvents(input_event.pp_resource(),
+ expected_events_.front().pp_resource());
+ expected_events_.erase(expected_events_.begin());
+ }
+ break;
+
+ default:
+ // Don't care for any other input event types for this test.
+ break;
+ }
+
+ // Handle all input events.
+ return true;
+}
+
+void TestImeInputEvent::HandleMessage(const pp::Var& message_data) {
+ if (message_data.is_string() &&
+ (message_data.AsString() == FINISHED_WAITING_MESSAGE)) {
+ testing_interface_->QuitMessageLoop(instance_->pp_instance());
+ received_finish_message_ = true;
+ }
+}
+
+void TestImeInputEvent::DidChangeView(const pp::View& view) {
+ view_rect_ = view.GetRect();
+}
+
+pp::InputEvent TestImeInputEvent::CreateImeCompositionStartEvent() {
+ return pp::IMEInputEvent_Dev(
+ instance_,
+ PP_INPUTEVENT_TYPE_IME_COMPOSITION_START,
+ 100, // time_stamp
+ pp::Var(""),
+ std::vector<uint32_t>(),
+ -1, // target_segment
+ std::make_pair(0U, 0U) // selection
+ );
+}
+
+pp::InputEvent TestImeInputEvent::CreateImeCompositionUpdateEvent(
+ const std::string& text,
+ const std::vector<uint32_t>& segments,
+ int32_t target_segment,
+ const std::pair<uint32_t, uint32_t>& selection) {
+ return pp::IMEInputEvent_Dev(
+ instance_,
+ PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE,
+ 100, // time_stamp
+ text,
+ segments,
+ target_segment,
+ selection
+ );
+}
+
+pp::InputEvent TestImeInputEvent::CreateImeCompositionEndEvent(
+ const std::string& text) {
+ return pp::IMEInputEvent_Dev(
+ instance_,
+ PP_INPUTEVENT_TYPE_IME_COMPOSITION_END,
+ 100, // time_stamp
+ pp::Var(text),
+ std::vector<uint32_t>(),
+ -1, // target_segment
+ std::make_pair(0U, 0U) // selection
+ );
+}
+
+pp::InputEvent TestImeInputEvent::CreateImeTextEvent(const std::string& text) {
+ return pp::IMEInputEvent_Dev(
+ instance_,
+ PP_INPUTEVENT_TYPE_IME_TEXT,
+ 100, // time_stamp
+ pp::Var(text),
+ std::vector<uint32_t>(),
+ -1, // target_segment
+ std::make_pair(0U, 0U) // selection
+ );
+}
+
+pp::InputEvent TestImeInputEvent::CreateCharEvent(const std::string& text) {
+ return pp::KeyboardInputEvent(
+ instance_,
+ PP_INPUTEVENT_TYPE_CHAR,
+ 100, // time_stamp
+ 0, // modifiers
+ 0, // keycode
+ pp::Var(text));
+}
+
+void TestImeInputEvent::GetFocusBySimulatingMouseClick() {
+ // For receiving IME events, the plugin DOM node needs to be focused.
+ // The following code is for achieving that by simulating a mouse click event.
+ input_event_interface_->RequestInputEvents(instance_->pp_instance(),
+ PP_INPUTEVENT_CLASS_MOUSE);
+ SimulateInputEvent(pp::MouseInputEvent(
+ instance_,
+ PP_INPUTEVENT_TYPE_MOUSEDOWN,
+ 100, // time_stamp
+ 0, // modifiers
+ PP_INPUTEVENT_MOUSEBUTTON_LEFT,
+ pp::Point(
+ view_rect_.x() + view_rect_.width() / 2,
+ view_rect_.y() + view_rect_.height() / 2),
+ 1, // click count
+ pp::Point())); // movement
+}
+
+// Simulates the input event and calls PostMessage to let us know when
+// we have received all resulting events from the browser.
+bool TestImeInputEvent::SimulateInputEvent(const pp::InputEvent& input_event) {
+ received_unexpected_event_ = false;
+ received_finish_message_ = false;
+ testing_interface_->SimulateInputEvent(instance_->pp_instance(),
+ input_event.pp_resource());
+ instance_->PostMessage(pp::Var(FINISHED_WAITING_MESSAGE));
+ testing_interface_->RunMessageLoop(instance_->pp_instance());
+ return received_finish_message_ && !received_unexpected_event_;
+}
+
+bool TestImeInputEvent::AreEquivalentEvents(PP_Resource received,
+ PP_Resource expected) {
+ if (!input_event_interface_->IsInputEvent(received) ||
+ !input_event_interface_->IsInputEvent(expected)) {
+ return false;
+ }
+
+ // Test common fields, except modifiers and time stamp, which may be changed
+ // by the browser.
+ int32_t received_type = input_event_interface_->GetType(received);
+ int32_t expected_type = input_event_interface_->GetType(expected);
+ if (received_type != expected_type)
+ return false;
+
+ // Test event type-specific fields.
+ switch (received_type) {
+ case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START:
+ // COMPOSITION_START does not convey further information.
+ break;
+
+ case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END:
+ case PP_INPUTEVENT_TYPE_IME_TEXT:
+ // For COMPOSITION_END and TEXT, GetText() has meaning.
+ return pp::Var(pp::PASS_REF,
+ ime_input_event_interface_->GetText(received)) ==
+ pp::Var(pp::PASS_REF,
+ ime_input_event_interface_->GetText(expected));
+
+ case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE:
+ // For COMPOSITION_UPDATE, all fields must be checked.
+ {
+ uint32_t received_segment_number =
+ ime_input_event_interface_->GetSegmentNumber(received);
+ uint32_t expected_segment_number =
+ ime_input_event_interface_->GetSegmentNumber(expected);
+ if (received_segment_number != expected_segment_number)
+ return false;
+
+ // The "<=" is not a bug. i-th segment is represented as the pair of
+ // i-th and (i+1)-th offsets in Pepper IME API.
+ for (uint32_t i = 0; i <= received_segment_number; ++i) {
+ if (ime_input_event_interface_->GetSegmentOffset(received, i) !=
+ ime_input_event_interface_->GetSegmentOffset(expected, i))
+ return false;
+ }
+
+ uint32_t received_selection_start = 0;
+ uint32_t received_selection_end = 0;
+ uint32_t expected_selection_start = 0;
+ uint32_t expected_selection_end = 0;
+ ime_input_event_interface_->GetSelection(
+ received, &received_selection_start, &received_selection_end);
+ ime_input_event_interface_->GetSelection(
+ expected, &expected_selection_start, &expected_selection_end);
+ if (received_selection_start != expected_selection_start ||
+ received_selection_end != expected_selection_end) {
+ return true;
+ }
+
+ return pp::Var(pp::PASS_REF,
+ ime_input_event_interface_->GetText(received)) ==
+ pp::Var(pp::PASS_REF,
+ ime_input_event_interface_->GetText(expected)) &&
+ ime_input_event_interface_->GetTargetSegment(received) ==
+ ime_input_event_interface_->GetTargetSegment(expected);
+ }
+
+ case PP_INPUTEVENT_TYPE_CHAR:
+ return
+ keyboard_input_event_interface_->GetKeyCode(received) ==
+ keyboard_input_event_interface_->GetKeyCode(expected) &&
+ pp::Var(pp::PASS_REF,
+ keyboard_input_event_interface_->GetCharacterText(received)) ==
+ pp::Var(pp::PASS_REF,
+ keyboard_input_event_interface_->GetCharacterText(expected));
+
+ default:
+ break;
+ }
+ return true;
+}
+
+std::string TestImeInputEvent::TestImeCommit() {
+ GetFocusBySimulatingMouseClick();
+
+ input_event_interface_->RequestInputEvents(instance_->pp_instance(),
+ PP_INPUTEVENT_CLASS_KEYBOARD |
+ PP_INPUTEVENT_CLASS_IME);
+
+ std::vector<uint32_t> segments;
+ segments.push_back(0U);
+ segments.push_back(3U);
+ segments.push_back(6U);
+ segments.push_back(9U);
+ pp::InputEvent update_event = CreateImeCompositionUpdateEvent(
+ kCompositionText, segments, 1, std::make_pair(3U, 6U));
+
+ expected_events_.clear();
+ expected_events_.push_back(CreateImeCompositionStartEvent());
+ expected_events_.push_back(update_event);
+ expected_events_.push_back(CreateImeCompositionEndEvent(kCompositionText));
+ expected_events_.push_back(CreateImeTextEvent(kCompositionText));
+
+ // Simulate the case when IME successfully committed some text.
+ ASSERT_TRUE(SimulateInputEvent(update_event));
+ ASSERT_TRUE(SimulateInputEvent(CreateImeTextEvent(kCompositionText)));
+
+ ASSERT_TRUE(expected_events_.empty());
+ PASS();
+}
+
+std::string TestImeInputEvent::TestImeCancel() {
+ GetFocusBySimulatingMouseClick();
+
+ input_event_interface_->RequestInputEvents(instance_->pp_instance(),
+ PP_INPUTEVENT_CLASS_KEYBOARD |
+ PP_INPUTEVENT_CLASS_IME);
+
+ std::vector<uint32_t> segments;
+ segments.push_back(0U);
+ segments.push_back(3U);
+ segments.push_back(6U);
+ segments.push_back(9U);
+ pp::InputEvent update_event = CreateImeCompositionUpdateEvent(
+ kCompositionText, segments, 1, std::make_pair(3U, 6U));
+
+ expected_events_.clear();
+ expected_events_.push_back(CreateImeCompositionStartEvent());
+ expected_events_.push_back(update_event);
+ expected_events_.push_back(CreateImeCompositionEndEvent(""));
+
+ // Simulate the case when IME canceled composition.
+ ASSERT_TRUE(SimulateInputEvent(update_event));
+ ASSERT_TRUE(SimulateInputEvent(CreateImeCompositionEndEvent("")));
+
+ ASSERT_TRUE(expected_events_.empty());
+ PASS();
+}
+
+std::string TestImeInputEvent::TestImeUnawareCommit() {
+ GetFocusBySimulatingMouseClick();
+
+ input_event_interface_->ClearInputEventRequest(instance_->pp_instance(),
+ PP_INPUTEVENT_CLASS_IME);
+ input_event_interface_->RequestInputEvents(instance_->pp_instance(),
+ PP_INPUTEVENT_CLASS_KEYBOARD);
+
+ std::vector<uint32_t> segments;
+ segments.push_back(0U);
+ segments.push_back(3U);
+ segments.push_back(6U);
+ segments.push_back(9U);
+ pp::InputEvent update_event = CreateImeCompositionUpdateEvent(
+ kCompositionText, segments, 1, std::make_pair(3U, 6U));
+
+ expected_events_.clear();
+ expected_events_.push_back(CreateCharEvent(kCompositionChar[0]));
+ expected_events_.push_back(CreateCharEvent(kCompositionChar[1]));
+ expected_events_.push_back(CreateCharEvent(kCompositionChar[2]));
+
+ // Test for IME-unaware plugins. Commit event is translated to char events.
+ ASSERT_TRUE(SimulateInputEvent(update_event));
+ ASSERT_TRUE(SimulateInputEvent(CreateImeTextEvent(kCompositionText)));
+
+ ASSERT_TRUE(expected_events_.empty());
+ PASS();
+}
+
+
+std::string TestImeInputEvent::TestImeUnawareCancel() {
+ GetFocusBySimulatingMouseClick();
+
+ input_event_interface_->ClearInputEventRequest(instance_->pp_instance(),
+ PP_INPUTEVENT_CLASS_IME);
+ input_event_interface_->RequestInputEvents(instance_->pp_instance(),
+ PP_INPUTEVENT_CLASS_KEYBOARD);
+
+ std::vector<uint32_t> segments;
+ segments.push_back(0U);
+ segments.push_back(3U);
+ segments.push_back(6U);
+ segments.push_back(9U);
+ pp::InputEvent update_event = CreateImeCompositionUpdateEvent(
+ kCompositionText, segments, 1, std::make_pair(3U, 6U));
+
+ expected_events_.clear();
+
+ // Test for IME-unaware plugins. Cancel won't issue any events.
+ ASSERT_TRUE(SimulateInputEvent(update_event));
+ ASSERT_TRUE(SimulateInputEvent(CreateImeCompositionEndEvent("")));
+
+ ASSERT_TRUE(expected_events_.empty());
+ PASS();
+}
+
diff --git a/ppapi/tests/test_ime_input_event.h b/ppapi/tests/test_ime_input_event.h
new file mode 100644
index 0000000..483167c
--- /dev/null
+++ b/ppapi/tests/test_ime_input_event.h
@@ -0,0 +1,60 @@
+// 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_TESTS_TEST_IME_INPUT_EVENT_H_
+#define PPAPI_TESTS_TEST_IME_INPUT_EVENT_H_
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "ppapi/c/dev/ppb_ime_input_event_dev.h"
+#include "ppapi/c/ppb_input_event.h"
+#include "ppapi/cpp/input_event.h"
+#include "ppapi/tests/test_case.h"
+
+class TestImeInputEvent : public TestCase {
+ public:
+ explicit TestImeInputEvent(TestingInstance* instance);
+ ~TestImeInputEvent();
+
+ // TestCase implementation.
+ virtual void RunTests(const std::string& test_filter);
+ virtual bool Init();
+ virtual bool HandleInputEvent(const pp::InputEvent& input_event);
+ virtual void HandleMessage(const pp::Var& message_data);
+ virtual void DidChangeView(const pp::View& view);
+
+ private:
+ pp::InputEvent CreateImeCompositionStartEvent();
+ pp::InputEvent CreateImeCompositionUpdateEvent(
+ const std::string& text,
+ const std::vector<uint32_t>& segments,
+ int32_t target_segment,
+ const std::pair<uint32_t, uint32_t>& selection);
+ pp::InputEvent CreateImeCompositionEndEvent(const std::string& text);
+ pp::InputEvent CreateImeTextEvent(const std::string& text);
+ pp::InputEvent CreateCharEvent(const std::string& text);
+
+ void GetFocusBySimulatingMouseClick();
+ bool SimulateInputEvent(const pp::InputEvent& input_event);
+ bool AreEquivalentEvents(PP_Resource first, PP_Resource second);
+
+ // The test cases.
+ std::string TestImeCommit();
+ std::string TestImeCancel();
+ std::string TestImeUnawareCommit();
+ std::string TestImeUnawareCancel();
+
+ const PPB_InputEvent* input_event_interface_;
+ const PPB_KeyboardInputEvent* keyboard_input_event_interface_;
+ const PPB_IMEInputEvent_Dev* ime_input_event_interface_;
+
+ pp::Rect view_rect_;
+ bool received_unexpected_event_;
+ bool received_finish_message_;
+ std::vector<pp::InputEvent> expected_events_;
+};
+
+#endif // PPAPI_TESTS_TEST_IME_INPUT_EVENT_H_
diff --git a/ppapi/thunk/interfaces_ppb_public_dev.h b/ppapi/thunk/interfaces_ppb_public_dev.h
index 3b79fe4..692b4f3 100644
--- a/ppapi/thunk/interfaces_ppb_public_dev.h
+++ b/ppapi/thunk/interfaces_ppb_public_dev.h
@@ -26,6 +26,8 @@ PROXIED_IFACE(PPB_AudioInput, PPB_AUDIO_INPUT_DEV_INTERFACE_0_2,
PPB_AudioInput_Dev_0_2)
PROXIED_IFACE(NoAPIName, PPB_IME_INPUT_EVENT_DEV_INTERFACE_0_1,
PPB_IMEInputEvent_Dev_0_1)
+PROXIED_IFACE(NoAPIName, PPB_IME_INPUT_EVENT_DEV_INTERFACE_0_2,
+ PPB_IMEInputEvent_Dev_0_2)
PROXIED_IFACE(PPB_Buffer, PPB_BUFFER_DEV_INTERFACE_0_4, PPB_Buffer_Dev_0_4)
PROXIED_IFACE(PPB_Graphics3D,
PPB_GLES_CHROMIUM_TEXTURE_MAPPING_DEV_INTERFACE_0_1,
diff --git a/ppapi/thunk/ppb_input_event_thunk.cc b/ppapi/thunk/ppb_input_event_thunk.cc
index 8f3f65c..47f9e51 100644
--- a/ppapi/thunk/ppb_input_event_thunk.cc
+++ b/ppapi/thunk/ppb_input_event_thunk.cc
@@ -293,6 +293,26 @@ const PPB_KeyboardInputEvent_Dev g_ppb_keyboard_input_event_dev_thunk = {
// Composition -----------------------------------------------------------------
+PP_Resource CreateIMEInputEvent(PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ PP_Var text,
+ uint32_t segment_number,
+ const uint32_t segment_offsets[],
+ int32_t target_segment,
+ uint32_t selection_start,
+ uint32_t selection_end) {
+ EnterResourceCreation enter(instance);
+ if (enter.failed())
+ return 0;
+ return enter.functions()->CreateIMEInputEvent(instance, type, time_stamp,
+ text, segment_number,
+ segment_offsets,
+ target_segment,
+ selection_start,
+ selection_end);
+}
+
PP_Bool IsIMEInputEvent(PP_Resource resource) {
if (!IsInputEvent(resource))
return PP_FALSE; // Prevent warning log in GetType.
@@ -340,7 +360,17 @@ void GetIMESelection(PP_Resource ime_event, uint32_t* start, uint32_t* end) {
enter.object()->GetIMESelection(start, end);
}
-const PPB_IMEInputEvent_Dev g_ppb_ime_input_event_thunk = {
+const PPB_IMEInputEvent_Dev_0_1 g_ppb_ime_input_event_0_1_thunk = {
+ &IsIMEInputEvent,
+ &GetIMEText,
+ &GetIMESegmentNumber,
+ &GetIMESegmentOffset,
+ &GetIMETargetSegment,
+ &GetIMESelection
+};
+
+const PPB_IMEInputEvent_Dev_0_2 g_ppb_ime_input_event_0_2_thunk = {
+ &CreateIMEInputEvent,
&IsIMEInputEvent,
&GetIMEText,
&GetIMESegmentNumber,
@@ -377,7 +407,11 @@ const PPB_WheelInputEvent_1_0* GetPPB_WheelInputEvent_1_0_Thunk() {
}
const PPB_IMEInputEvent_Dev_0_1* GetPPB_IMEInputEvent_Dev_0_1_Thunk() {
- return &g_ppb_ime_input_event_thunk;
+ return &g_ppb_ime_input_event_0_1_thunk;
+}
+
+const PPB_IMEInputEvent_Dev_0_2* GetPPB_IMEInputEvent_Dev_0_2_Thunk() {
+ return &g_ppb_ime_input_event_0_2_thunk;
}
} // namespace thunk
diff --git a/ppapi/thunk/resource_creation_api.h b/ppapi/thunk/resource_creation_api.h
index ee7c5c2..2fd9d02 100644
--- a/ppapi/thunk/resource_creation_api.h
+++ b/ppapi/thunk/resource_creation_api.h
@@ -47,6 +47,15 @@ class ResourceCreationAPI {
const char* path) = 0;
virtual PP_Resource CreateFileSystem(PP_Instance instance,
PP_FileSystemType type) = 0;
+ virtual PP_Resource CreateIMEInputEvent(PP_Instance instance,
+ PP_InputEvent_Type type,
+ PP_TimeTicks time_stamp,
+ struct PP_Var text,
+ uint32_t segment_number,
+ const uint32_t* segment_offsets,
+ int32_t target_segment,
+ uint32_t selection_start,
+ uint32_t selection_end) = 0;
virtual PP_Resource CreateKeyboardInputEvent(
PP_Instance instance,
PP_InputEvent_Type type,