diff -r 4f2f89ce4247 -r 303757a437d3 WebKitTools/DumpRenderTree/gtk/EventSender.cpp --- a/WebKitTools/DumpRenderTree/gtk/EventSender.cpp Fri Sep 17 09:02:29 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,637 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2009 Zan Dobersek - * Copyright (C) 2009 Holger Hans Peter Freyther - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "EventSender.h" - -#include "DumpRenderTree.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -// FIXME: Implement support for synthesizing drop events. - -extern "C" { - extern void webkit_web_frame_layout(WebKitWebFrame* frame); -} - -static bool dragMode; -static int timeOffset = 0; - -static int lastMousePositionX; -static int lastMousePositionY; -static int lastClickPositionX; -static int lastClickPositionY; -static int lastClickTimeOffset; -static int lastClickButton; -static int buttonCurrentlyDown; -static int clickCount; - -struct DelayedMessage { - GdkEvent event; - gulong delay; -}; - -static DelayedMessage msgQueue[1024]; - -static unsigned endOfQueue; -static unsigned startOfQueue; - -static const float zoomMultiplierRatio = 1.2f; - -// Key event location code defined in DOM Level 3. -enum KeyLocationCode { - DOM_KEY_LOCATION_STANDARD = 0x00, - DOM_KEY_LOCATION_LEFT = 0x01, - DOM_KEY_LOCATION_RIGHT = 0x02, - DOM_KEY_LOCATION_NUMPAD = 0x03 -}; - -static void sendOrQueueEvent(GdkEvent, bool = true); -static void dispatchEvent(GdkEvent event); -static guint getStateFlags(); - -#if !GTK_CHECK_VERSION(2, 17, 3) -static void gdk_window_get_root_coords(GdkWindow* window, gint x, gint y, gint* rootX, gint* rootY) -{ - gdk_window_get_root_origin(window, rootX, rootY); - *rootX = *rootX + x; - *rootY = *rootY + y; -} -#endif - -#if !GTK_CHECK_VERSION(2, 14, 0) -static GdkWindow* gtk_widget_get_window(GtkWidget* widget) -{ - g_return_val_if_fail(GTK_IS_WIDGET(widget), 0); - return widget->window; -} -#endif - -static JSValueRef getDragModeCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) -{ - return JSValueMakeBoolean(context, dragMode); -} - -static bool setDragModeCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception) -{ - dragMode = JSValueToBoolean(context, value); - return true; -} - -static JSValueRef leapForwardCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - if (argumentCount > 0) { - msgQueue[endOfQueue].delay = JSValueToNumber(context, arguments[0], exception); - timeOffset += msgQueue[endOfQueue].delay; - ASSERT(!exception || !*exception); - } - - return JSValueMakeUndefined(context); -} - -bool prepareMouseButtonEvent(GdkEvent* event, int eventSenderButtonNumber) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - if (!view) - return false; - - // The logic for mapping EventSender button numbers to GDK button - // numbers originates from the Windows EventSender. - int gdkButtonNumber = 3; - if (eventSenderButtonNumber >= 0 && eventSenderButtonNumber <= 2) - gdkButtonNumber = eventSenderButtonNumber + 1; - - // fast/events/mouse-click-events expects the 4th button - // to be event.button = 1, so send a middle-button event. - else if (eventSenderButtonNumber == 3) - gdkButtonNumber = 2; - - memset(event, 0, sizeof(event)); - event->button.button = gdkButtonNumber; - event->button.x = lastMousePositionX; - event->button.y = lastMousePositionY; - event->button.window = gtk_widget_get_window(GTK_WIDGET(view)); - event->button.device = gdk_device_get_core_pointer(); - event->button.state = getStateFlags(); - event->button.time = GDK_CURRENT_TIME; - - int xRoot, yRoot; - gdk_window_get_root_coords(gtk_widget_get_window(GTK_WIDGET(view)), lastMousePositionX, lastMousePositionY, &xRoot, &yRoot); - event->button.x_root = xRoot; - event->button.y_root = yRoot; - - return true; -} - -static JSValueRef contextClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - GdkEvent event; - if (!prepareMouseButtonEvent(&event, 2)) - return JSValueMakeUndefined(context); - - event.type = GDK_BUTTON_PRESS; - sendOrQueueEvent(event); - event.type = GDK_BUTTON_RELEASE; - sendOrQueueEvent(event); - - return JSValueMakeUndefined(context); -} - -static void updateClickCount(int button) -{ - if (lastClickPositionX != lastMousePositionX - || lastClickPositionY != lastMousePositionY - || lastClickButton != button - || timeOffset - lastClickTimeOffset >= 1) - clickCount = 1; - else - clickCount++; -} - -static JSValueRef mouseDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - int button = 0; - if (argumentCount == 1) { - button = static_cast(JSValueToNumber(context, arguments[0], exception)); - g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context)); - } - - GdkEvent event; - if (!prepareMouseButtonEvent(&event, button)) - return JSValueMakeUndefined(context); - - buttonCurrentlyDown = event.button.button; - - // Normally GDK will send both GDK_BUTTON_PRESS and GDK_2BUTTON_PRESS for - // the second button press during double-clicks. WebKit GTK+ selectively - // ignores the first GDK_BUTTON_PRESS of that pair using gdk_event_peek. - // Since our events aren't ever going onto the GDK event queue, WebKit won't - // be able to filter out the first GDK_BUTTON_PRESS, so we just don't send - // it here. Eventually this code should probably figure out a way to get all - // appropriate events onto the event queue and this work-around should be - // removed. - updateClickCount(event.button.button); - if (clickCount == 2) - event.type = GDK_2BUTTON_PRESS; - else if (clickCount == 3) - event.type = GDK_3BUTTON_PRESS; - else - event.type = GDK_BUTTON_PRESS; - - sendOrQueueEvent(event); - return JSValueMakeUndefined(context); -} - -static guint getStateFlags() -{ - if (buttonCurrentlyDown == 1) - return GDK_BUTTON1_MASK; - if (buttonCurrentlyDown == 2) - return GDK_BUTTON2_MASK; - if (buttonCurrentlyDown == 3) - return GDK_BUTTON3_MASK; - return 0; -} - -static JSValueRef mouseUpCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - int button = 0; - if (argumentCount == 1) { - button = static_cast(JSValueToNumber(context, arguments[0], exception)); - g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context)); - } - - GdkEvent event; - if (!prepareMouseButtonEvent(&event, button)) - return JSValueMakeUndefined(context); - - lastClickPositionX = lastMousePositionX; - lastClickPositionY = lastMousePositionY; - lastClickButton = buttonCurrentlyDown; - lastClickTimeOffset = timeOffset; - buttonCurrentlyDown = 0; - - event.type = GDK_BUTTON_RELEASE; - sendOrQueueEvent(event); - return JSValueMakeUndefined(context); -} - -static JSValueRef mouseMoveToCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - if (!view) - return JSValueMakeUndefined(context); - - if (argumentCount < 2) - return JSValueMakeUndefined(context); - - lastMousePositionX = (int)JSValueToNumber(context, arguments[0], exception); - g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context)); - lastMousePositionY = (int)JSValueToNumber(context, arguments[1], exception); - g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context)); - - GdkEvent event; - memset(&event, 0, sizeof(event)); - event.type = GDK_MOTION_NOTIFY; - event.motion.x = lastMousePositionX; - event.motion.y = lastMousePositionY; - - event.motion.time = GDK_CURRENT_TIME; - event.motion.window = gtk_widget_get_window(GTK_WIDGET(view)); - event.motion.device = gdk_device_get_core_pointer(); - event.motion.state = getStateFlags(); - - int xRoot, yRoot; - gdk_window_get_root_coords(gtk_widget_get_window(GTK_WIDGET(view)), lastMousePositionX, lastMousePositionY, &xRoot, &yRoot); - event.motion.x_root = xRoot; - event.motion.y_root = yRoot; - - sendOrQueueEvent(event, false); - return JSValueMakeUndefined(context); -} - -static JSValueRef mouseWheelToCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - if (!view) - return JSValueMakeUndefined(context); - - if (argumentCount < 2) - return JSValueMakeUndefined(context); - - int horizontal = (int)JSValueToNumber(context, arguments[0], exception); - g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context)); - int vertical = (int)JSValueToNumber(context, arguments[1], exception); - g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context)); - - // GTK+ doesn't support multiple direction scrolls in the same event! - g_return_val_if_fail((!vertical || !horizontal), JSValueMakeUndefined(context)); - - GdkEvent event; - event.type = GDK_SCROLL; - event.scroll.x = lastMousePositionX; - event.scroll.y = lastMousePositionY; - event.scroll.time = GDK_CURRENT_TIME; - event.scroll.window = gtk_widget_get_window(GTK_WIDGET(view)); - - if (horizontal < 0) - event.scroll.direction = GDK_SCROLL_LEFT; - else if (horizontal > 0) - event.scroll.direction = GDK_SCROLL_RIGHT; - else if (vertical < 0) - event.scroll.direction = GDK_SCROLL_UP; - else if (vertical > 0) - event.scroll.direction = GDK_SCROLL_DOWN; - else - g_assert_not_reached(); - - sendOrQueueEvent(event); - return JSValueMakeUndefined(context); -} - -static JSValueRef beginDragWithFilesCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - if (argumentCount < 1) - return JSValueMakeUndefined(context); - - // FIXME: Implement this completely once WebCore has complete drag and drop support - return JSValueMakeUndefined(context); -} - -static void sendOrQueueEvent(GdkEvent event, bool shouldReplaySavedEvents) -{ - // Mouse move events are queued if the previous event was queued or if a - // delay was set up by leapForward(). - if ((dragMode && buttonCurrentlyDown) || endOfQueue != startOfQueue || msgQueue[endOfQueue].delay) { - msgQueue[endOfQueue++].event = event; - - if (shouldReplaySavedEvents) - replaySavedEvents(); - - return; - } - - dispatchEvent(event); -} - -static void dispatchEvent(GdkEvent event) -{ - webkit_web_frame_layout(mainFrame); - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - if (!view) - return; - - gtk_main_do_event(&event); -} - -void replaySavedEvents() -{ - // FIXME: Eventually we may need to have more sophisticated logic to - // track drag-and-drop operations. - - // First send all the events that are ready to be sent - while (startOfQueue < endOfQueue) { - if (msgQueue[startOfQueue].delay) { - g_usleep(msgQueue[startOfQueue].delay * 1000); - msgQueue[startOfQueue].delay = 0; - } - - dispatchEvent(msgQueue[startOfQueue++].event); - } - - startOfQueue = 0; - endOfQueue = 0; -} - -static JSValueRef keyDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - if (argumentCount < 1) - return JSValueMakeUndefined(context); - - static const JSStringRef lengthProperty = JSStringCreateWithUTF8CString("length"); - - webkit_web_frame_layout(mainFrame); - - // handle modifier keys. - int state = 0; - if (argumentCount > 1) { - JSObjectRef modifiersArray = JSValueToObject(context, arguments[1], exception); - if (modifiersArray) { - for (int i = 0; i < JSValueToNumber(context, JSObjectGetProperty(context, modifiersArray, lengthProperty, 0), 0); ++i) { - JSValueRef value = JSObjectGetPropertyAtIndex(context, modifiersArray, i, 0); - JSStringRef string = JSValueToStringCopy(context, value, 0); - if (JSStringIsEqualToUTF8CString(string, "ctrlKey")) - state |= GDK_CONTROL_MASK; - else if (JSStringIsEqualToUTF8CString(string, "shiftKey")) - state |= GDK_SHIFT_MASK; - else if (JSStringIsEqualToUTF8CString(string, "altKey")) - state |= GDK_MOD1_MASK; - - JSStringRelease(string); - } - } - } - - // handle location argument. - int location = DOM_KEY_LOCATION_STANDARD; - if (argumentCount > 2) - location = (int)JSValueToNumber(context, arguments[2], exception); - - JSStringRef character = JSValueToStringCopy(context, arguments[0], exception); - g_return_val_if_fail((!exception || !*exception), JSValueMakeUndefined(context)); - int gdkKeySym = GDK_VoidSymbol; - if (location == DOM_KEY_LOCATION_NUMPAD) { - if (JSStringIsEqualToUTF8CString(character, "leftArrow")) - gdkKeySym = GDK_KP_Left; - else if (JSStringIsEqualToUTF8CString(character, "rightArrow")) - gdkKeySym = GDK_KP_Right; - else if (JSStringIsEqualToUTF8CString(character, "upArrow")) - gdkKeySym = GDK_KP_Up; - else if (JSStringIsEqualToUTF8CString(character, "downArrow")) - gdkKeySym = GDK_KP_Down; - else if (JSStringIsEqualToUTF8CString(character, "pageUp")) - gdkKeySym = GDK_KP_Page_Up; - else if (JSStringIsEqualToUTF8CString(character, "pageDown")) - gdkKeySym = GDK_KP_Page_Down; - else if (JSStringIsEqualToUTF8CString(character, "home")) - gdkKeySym = GDK_KP_Home; - else if (JSStringIsEqualToUTF8CString(character, "end")) - gdkKeySym = GDK_KP_End; - else - // Assume we only get arrow/pgUp/pgDn/home/end keys with - // location=NUMPAD for now. - g_assert_not_reached(); - } else { - if (JSStringIsEqualToUTF8CString(character, "leftArrow")) - gdkKeySym = GDK_Left; - else if (JSStringIsEqualToUTF8CString(character, "rightArrow")) - gdkKeySym = GDK_Right; - else if (JSStringIsEqualToUTF8CString(character, "upArrow")) - gdkKeySym = GDK_Up; - else if (JSStringIsEqualToUTF8CString(character, "downArrow")) - gdkKeySym = GDK_Down; - else if (JSStringIsEqualToUTF8CString(character, "pageUp")) - gdkKeySym = GDK_Page_Up; - else if (JSStringIsEqualToUTF8CString(character, "pageDown")) - gdkKeySym = GDK_Page_Down; - else if (JSStringIsEqualToUTF8CString(character, "home")) - gdkKeySym = GDK_Home; - else if (JSStringIsEqualToUTF8CString(character, "end")) - gdkKeySym = GDK_End; - else if (JSStringIsEqualToUTF8CString(character, "delete")) - gdkKeySym = GDK_Delete; - else if (JSStringIsEqualToUTF8CString(character, "F1")) - gdkKeySym = GDK_F1; - else if (JSStringIsEqualToUTF8CString(character, "F2")) - gdkKeySym = GDK_F2; - else if (JSStringIsEqualToUTF8CString(character, "F3")) - gdkKeySym = GDK_F3; - else if (JSStringIsEqualToUTF8CString(character, "F4")) - gdkKeySym = GDK_F4; - else if (JSStringIsEqualToUTF8CString(character, "F5")) - gdkKeySym = GDK_F5; - else if (JSStringIsEqualToUTF8CString(character, "F6")) - gdkKeySym = GDK_F6; - else if (JSStringIsEqualToUTF8CString(character, "F7")) - gdkKeySym = GDK_F7; - else if (JSStringIsEqualToUTF8CString(character, "F8")) - gdkKeySym = GDK_F8; - else if (JSStringIsEqualToUTF8CString(character, "F9")) - gdkKeySym = GDK_F9; - else if (JSStringIsEqualToUTF8CString(character, "F10")) - gdkKeySym = GDK_F10; - else if (JSStringIsEqualToUTF8CString(character, "F11")) - gdkKeySym = GDK_F11; - else if (JSStringIsEqualToUTF8CString(character, "F12")) - gdkKeySym = GDK_F12; - else { - int charCode = JSStringGetCharactersPtr(character)[0]; - if (charCode == '\n' || charCode == '\r') - gdkKeySym = GDK_Return; - else if (charCode == '\t') - gdkKeySym = GDK_Tab; - else if (charCode == '\x8') - gdkKeySym = GDK_BackSpace; - else { - gdkKeySym = gdk_unicode_to_keyval(charCode); - if (WTF::isASCIIUpper(charCode)) - state |= GDK_SHIFT_MASK; - } - } - } - JSStringRelease(character); - - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - if (!view) - return JSValueMakeUndefined(context); - - // create and send the event - GdkEvent event; - memset(&event, 0, sizeof(event)); - event.key.keyval = gdkKeySym; - event.key.state = state; - event.key.window = gtk_widget_get_window(GTK_WIDGET(view)); - - // When synthesizing an event, an invalid hardware_keycode value - // can cause it to be badly processed by Gtk+. - GdkKeymapKey* keys; - gint n_keys; - if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), gdkKeySym, &keys, &n_keys)) { - event.key.hardware_keycode = keys[0].keycode; - g_free(keys); - } - - event.key.type = GDK_KEY_PRESS; - dispatchEvent(event); - - event.key.type = GDK_KEY_RELEASE; - dispatchEvent(event); - - return JSValueMakeUndefined(context); -} - -static void zoomIn(gboolean fullContentsZoom) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - if (!view) - return; - - webkit_web_view_set_full_content_zoom(view, fullContentsZoom); - gfloat currentZoom = webkit_web_view_get_zoom_level(view); - webkit_web_view_set_zoom_level(view, currentZoom * zoomMultiplierRatio); -} - -static void zoomOut(gboolean fullContentsZoom) -{ - WebKitWebView* view = webkit_web_frame_get_web_view(mainFrame); - if (!view) - return; - - webkit_web_view_set_full_content_zoom(view, fullContentsZoom); - gfloat currentZoom = webkit_web_view_get_zoom_level(view); - webkit_web_view_set_zoom_level(view, currentZoom / zoomMultiplierRatio); -} - -static JSValueRef textZoomInCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - zoomIn(FALSE); - return JSValueMakeUndefined(context); -} - -static JSValueRef textZoomOutCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - zoomOut(FALSE); - return JSValueMakeUndefined(context); -} - -static JSValueRef zoomPageInCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - zoomIn(TRUE); - return JSValueMakeUndefined(context); -} - -static JSValueRef zoomPageOutCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) -{ - zoomOut(TRUE); - return JSValueMakeUndefined(context); -} - -static JSStaticFunction staticFunctions[] = { - { "mouseWheelTo", mouseWheelToCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "contextClick", contextClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "mouseDown", mouseDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "mouseUp", mouseUpCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "mouseMoveTo", mouseMoveToCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "beginDragWithFiles", beginDragWithFilesCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "leapForward", leapForwardCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "keyDown", keyDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "textZoomIn", textZoomInCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "textZoomOut", textZoomOutCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "zoomPageIn", zoomPageInCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { "zoomPageOut", zoomPageOutCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, - { 0, 0, 0 } -}; - -static JSStaticValue staticValues[] = { - { "dragMode", getDragModeCallback, setDragModeCallback, kJSPropertyAttributeNone }, - { 0, 0, 0, 0 } -}; - -static JSClassRef getClass(JSContextRef context) -{ - static JSClassRef eventSenderClass = 0; - - if (!eventSenderClass) { - JSClassDefinition classDefinition = { - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - classDefinition.staticFunctions = staticFunctions; - classDefinition.staticValues = staticValues; - - eventSenderClass = JSClassCreate(&classDefinition); - } - - return eventSenderClass; -} - -JSObjectRef makeEventSender(JSContextRef context, bool isTopFrame) -{ - if (isTopFrame) { - dragMode = true; - - // Fly forward in time one second when the main frame loads. This will - // ensure that when a test begins clicking in the same location as - // a previous test, those clicks won't be interpreted as continuations - // of the previous test's click sequences. - timeOffset += 1000; - - lastMousePositionX = lastMousePositionY = 0; - lastClickPositionX = lastClickPositionY = 0; - lastClickTimeOffset = 0; - lastClickButton = 0; - buttonCurrentlyDown = 0; - clickCount = 0; - - endOfQueue = 0; - startOfQueue = 0; - } - - return JSObjectMake(context, getClass(context), 0); -}