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 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 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 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 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 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 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 175 JSObjectRef makeTextInputController(JSContextRef context) 176 { 177 return JSObjectMake(context, getClass(context), 0); 178 } 179