[Gtk] Implement textInputController.doCommand
[WebKit-https.git] / Tools / DumpRenderTree / gtk / TextInputController.cpp
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
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     ASSERT(view);
45     if (argumentCount < 3)
46         return JSValueMakeUndefined(context);
47
48     JSStringRef string = JSValueToStringCopy(context, arguments[0], exception);
49     ASSERT(!exception || !*exception);
50
51     size_t bufferSize = JSStringGetMaximumUTF8CStringSize(string);
52     GOwnPtr<gchar> stringBuffer(static_cast<gchar*>(g_malloc(bufferSize)));
53     JSStringGetUTF8CString(string, stringBuffer.get(), bufferSize);
54     JSStringRelease(string);
55
56     int start = static_cast<int>(JSValueToNumber(context, arguments[1], exception));
57     ASSERT(!exception || !*exception);
58
59     int length = static_cast<int>(JSValueToNumber(context, arguments[2], exception));
60     ASSERT(!exception || !*exception);
61
62     DumpRenderTreeSupportGtk::setComposition(view, stringBuffer.get(), start, length);
63     return JSValueMakeUndefined(context);
64 }
65
66 static JSValueRef hasMarkedTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
67 {
68     WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
69     ASSERT(view);
70     return JSValueMakeBoolean(context, DumpRenderTreeSupportGtk::hasComposition(view));
71 }
72
73 static JSValueRef markedRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
74 {
75     WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
76     ASSERT(view);
77
78     int start, length;
79     if (!DumpRenderTreeSupportGtk::compositionRange(view, &start, &length))
80         return JSValueMakeUndefined(context);
81
82     JSValueRef arrayValues[2];
83     arrayValues[0] = JSValueMakeNumber(context, start);
84     arrayValues[1] = JSValueMakeNumber(context, length);
85     JSObjectRef arrayObject = JSObjectMakeArray(context, 2, arrayValues, exception);
86     ASSERT(!exception || !*exception);
87     return arrayObject;
88 }
89
90 static JSValueRef insertTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
91 {
92     WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
93     ASSERT(view);
94
95     if (argumentCount < 1)
96         return JSValueMakeUndefined(context);
97
98     JSStringRef string = JSValueToStringCopy(context, arguments[0], exception);
99     ASSERT(!exception || !*exception);
100
101     size_t bufferSize = JSStringGetMaximumUTF8CStringSize(string);
102     GOwnPtr<gchar> stringBuffer(static_cast<gchar*>(g_malloc(bufferSize)));
103     JSStringGetUTF8CString(string, stringBuffer.get(), bufferSize);
104     JSStringRelease(string);
105
106     DumpRenderTreeSupportGtk::confirmComposition(view, stringBuffer.get());
107     return JSValueMakeUndefined(context);
108 }
109
110 static JSValueRef unmarkTextCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
111 {
112     WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
113     ASSERT(view);
114
115     DumpRenderTreeSupportGtk::confirmComposition(view, 0);
116     return JSValueMakeUndefined(context);
117 }
118
119 static JSValueRef firstRectForCharacterRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
120 {
121     WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
122     ASSERT(view);
123     if (argumentCount < 2)
124         return JSValueMakeUndefined(context);
125
126     int location = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
127     ASSERT(!exception || !*exception);
128
129     int length = static_cast<int>(JSValueToNumber(context, arguments[1], exception));
130     ASSERT(!exception || !*exception);
131
132     cairo_rectangle_int_t rect;
133     if (!DumpRenderTreeSupportGtk::firstRectForCharacterRange(view, location, length, &rect))
134         return JSValueMakeUndefined(context);
135
136     JSValueRef arrayValues[4];
137     arrayValues[0] = JSValueMakeNumber(context, rect.x);
138     arrayValues[1] = JSValueMakeNumber(context, rect.y);
139     arrayValues[2] = JSValueMakeNumber(context, rect.width);
140     arrayValues[3] = JSValueMakeNumber(context, rect.height);
141     JSObjectRef arrayObject = JSObjectMakeArray(context, 4, arrayValues, exception);
142     ASSERT(!exception || !*exception);
143
144     return arrayObject;
145 }
146
147 static JSValueRef selectedRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
148 {
149     WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
150     ASSERT(view);
151
152     int start, length;
153     if (!DumpRenderTreeSupportGtk::selectedRange(view, &start, &length))
154         return JSValueMakeUndefined(context);
155
156     JSValueRef arrayValues[2];
157     arrayValues[0] = JSValueMakeNumber(context, start);
158     arrayValues[1] = JSValueMakeNumber(context, length);
159     JSObjectRef arrayObject = JSObjectMakeArray(context, 2, arrayValues, exception);
160     ASSERT(!exception || !*exception);
161
162     return arrayObject;
163 }
164
165 static JSValueRef doCommandCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
166 {
167     WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame);
168     ASSERT(view);
169     if (argumentCount < 1)
170         return JSValueMakeUndefined(context);
171
172     JSStringRef string = JSValueToStringCopy(context, arguments[0], exception);
173     ASSERT(!exception || !*exception);
174
175     size_t bufferSize = JSStringGetMaximumUTF8CStringSize(string);
176     GOwnPtr<gchar> stringBuffer(static_cast<gchar*>(g_malloc(bufferSize)));
177     JSStringGetUTF8CString(string, stringBuffer.get(), bufferSize);
178     JSStringRelease(string);
179
180     DumpRenderTreeSupportGtk::doCommand(view, stringBuffer.get());
181     return JSValueMakeUndefined(context);
182 }
183
184 static JSStaticFunction staticFunctions[] = {
185     { "setMarkedText", setMarkedTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
186     { "hasMarkedText", hasMarkedTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
187     { "markedRange", markedRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
188     { "insertText", insertTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
189     { "unmarkText", unmarkTextCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
190     { "firstRectForCharacterRange", firstRectForCharacterRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
191     { "selectedRange", selectedRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
192     { "doCommand", doCommandCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
193     { 0, 0, 0 }
194 };
195
196 static JSClassRef getClass(JSContextRef context)
197 {
198     static JSClassRef textInputControllerClass = 0;
199
200     if (!textInputControllerClass) {
201         JSClassDefinition classDefinition = {
202                 0, 0, 0, 0, 0, 0,
203                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
204         classDefinition.staticFunctions = staticFunctions;
205
206         textInputControllerClass = JSClassCreate(&classDefinition);
207     }
208
209     return textInputControllerClass;
210 }
211
212 JSObjectRef makeTextInputController(JSContextRef context)
213 {
214     return JSObjectMake(context, getClass(context), 0);
215 }