1 /*
2 * Copyright (C) 2011 Igalia S.L.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "config.h"
30 #include "TextInputController.h"
31
32 #include "DumpRenderTree.h"
33 #include "WebCoreSupport/DumpRenderTreeSupportGtk.h"
34 #include <GOwnPtrGtk.h>
35 #include <JavaScriptCore/JSObjectRef.h>
36 #include <JavaScriptCore/JSRetainPtr.h>
37 #include <JavaScriptCore/JSStringRef.h>
38 #include <cstring>
39 #include <webkit/webkit.h>
40
setMarkedTextCallback(JSContextRef context,JSObjectRef function,JSObjectRef thisObject,size_t argumentCount,const JSValueRef arguments[],JSValueRef * exception)41 static JSValueRef setMarkedTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
42 {
43 WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
44 if (!view)
45 return JSValueMakeUndefined(context);
46
47 if (argumentCount < 3)
48 return JSValueMakeUndefined(context);
49
50 JSStringRef string = JSValueToStringCopy(context, arguments[0], exception);
51 g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
52
53 size_t bufferSize = JSStringGetMaximumUTF8CStringSize(string);
54 GOwnPtr<gchar> stringBuffer(static_cast<gchar*>(g_malloc(bufferSize)));
55 JSStringGetUTF8CString(string, stringBuffer.get(), bufferSize);
56 JSStringRelease(string);
57
58 int start = static_cast<int>(JSValueToNumber(context, arguments[1], exception));
59 g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
60
61 int end = static_cast<int>(JSValueToNumber(context, arguments[2], exception));
62 g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
63
64 DumpRenderTreeSupportGtk::setComposition(view, stringBuffer.get(), start, end);
65
66 return JSValueMakeUndefined(context);
67 }
68
insertTextCallback(JSContextRef context,JSObjectRef function,JSObjectRef thisObject,size_t argumentCount,const JSValueRef arguments[],JSValueRef * exception)69 static JSValueRef insertTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
70 {
71 WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
72 if (!view)
73 return JSValueMakeUndefined(context);
74
75 if (argumentCount < 1)
76 return JSValueMakeUndefined(context);
77
78 JSStringRef string = JSValueToStringCopy(context, arguments[0], exception);
79 g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
80
81 size_t bufferSize = JSStringGetMaximumUTF8CStringSize(string);
82 GOwnPtr<gchar> stringBuffer(static_cast<gchar*>(g_malloc(bufferSize)));
83 JSStringGetUTF8CString(string, stringBuffer.get(), bufferSize);
84 JSStringRelease(string);
85
86 DumpRenderTreeSupportGtk::confirmComposition(view, stringBuffer.get());
87
88 return JSValueMakeUndefined(context);
89 }
90
unmarkTextCallback(JSContextRef context,JSObjectRef function,JSObjectRef thisObject,size_t argumentCount,const JSValueRef arguments[],JSValueRef * exception)91 static JSValueRef unmarkTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
92 {
93 WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
94 if (!view)
95 return JSValueMakeUndefined(context);
96
97 DumpRenderTreeSupportGtk::confirmComposition(view, 0);
98 return JSValueMakeUndefined(context);
99 }
100
firstRectForCharacterRangeCallback(JSContextRef context,JSObjectRef function,JSObjectRef thisObject,size_t argumentCount,const JSValueRef arguments[],JSValueRef * exception)101 static JSValueRef firstRectForCharacterRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
102 {
103 WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
104 if (!view)
105 return JSValueMakeUndefined(context);
106
107 if (argumentCount < 2)
108 return JSValueMakeUndefined(context);
109
110 int location = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
111 g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
112
113 int length = static_cast<int>(JSValueToNumber(context, arguments[1], exception));
114 g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
115
116 GdkRectangle rect;
117 if (!DumpRenderTreeSupportGtk::firstRectForCharacterRange(view, location, length, &rect))
118 return JSValueMakeUndefined(context);
119
120 JSValueRef arrayValues[4];
121 arrayValues[0] = JSValueMakeNumber(context, rect.x);
122 arrayValues[1] = JSValueMakeNumber(context, rect.y);
123 arrayValues[2] = JSValueMakeNumber(context, rect.width);
124 arrayValues[3] = JSValueMakeNumber(context, rect.height);
125 JSObjectRef arrayObject = JSObjectMakeArray(context, 4, arrayValues, exception);
126 g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
127
128 return arrayObject;
129 }
130
selectedRangeCallback(JSContextRef context,JSObjectRef function,JSObjectRef thisObject,size_t argumentCount,const JSValueRef arguments[],JSValueRef * exception)131 static JSValueRef selectedRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
132 {
133 WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
134 if (!view)
135 return JSValueMakeUndefined(context);
136
137 int start, end;
138 if (!DumpRenderTreeSupportGtk::selectedRange(view, &start, &end))
139 return JSValueMakeUndefined(context);
140
141 JSValueRef arrayValues[2];
142 arrayValues[0] = JSValueMakeNumber(context, start);
143 arrayValues[1] = JSValueMakeNumber(context, end);
144 JSObjectRef arrayObject = JSObjectMakeArray(context, 2, arrayValues, exception);
145 g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context));
146
147 return arrayObject;
148 }
149
150 static JSStaticFunction staticFunctions[] = {
151 { "setMarkedText", setMarkedTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
152 { "insertText", insertTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
153 { "unmarkText", unmarkTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
154 { "firstRectForCharacterRange", firstRectForCharacterRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
155 { "selectedRange", selectedRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
156 { 0, 0, 0 }
157 };
158
getClass(JSContextRef context)159 static JSClassRef getClass(JSContextRef context)
160 {
161 static JSClassRef textInputControllerClass = 0;
162
163 if (!textInputControllerClass) {
164 JSClassDefinition classDefinition = {
165 0, 0, 0, 0, 0, 0,
166 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
167 classDefinition.staticFunctions = staticFunctions;
168
169 textInputControllerClass = JSClassCreate(&classDefinition);
170 }
171
172 return textInputControllerClass;
173 }
174
makeTextInputController(JSContextRef context)175 JSObjectRef makeTextInputController(JSContextRef context)
176 {
177 return JSObjectMake(context, getClass(context), 0);
178 }
179