1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036 |
- /*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2009 Zan Dobersek <zandobersek@gmail.com>
- * Copyright (C) 2009 Holger Hans Peter Freyther
- * Copyright (C) 2010 Igalia S.L.
- * Copyright (C) 2011 ProFUSION Embedded Systems
- * Copyright (C) 2011, 2012 Samsung Electronics
- *
- * 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 "DumpRenderTreeChrome.h"
- #include "IntPoint.h"
- #include "JSStringUtils.h"
- #include "NotImplemented.h"
- #include "PlatformEvent.h"
- #include "WebCoreSupport/DumpRenderTreeSupportEfl.h"
- #include "ewk_private.h"
- #include <EWebKit.h>
- #include <Ecore_Input.h>
- #include <JavaScriptCore/JSObjectRef.h>
- #include <JavaScriptCore/JSRetainPtr.h>
- #include <JavaScriptCore/JSStringRef.h>
- #include <JavaScriptCore/OpaqueJSString.h>
- #include <wtf/ASCIICType.h>
- #include <wtf/Platform.h>
- #include <wtf/text/CString.h>
- static bool gDragMode;
- static int gTimeOffset = 0;
- static int gLastMousePositionX;
- static int gLastMousePositionY;
- static int gLastClickPositionX;
- static int gLastClickPositionY;
- static int gLastClickTimeOffset;
- static int gLastClickButton;
- static int gButtonCurrentlyDown;
- static int gClickCount;
- static const float zoomMultiplierRatio = 1.2f;
- // Key event location code defined in DOM Level 3.
- enum KeyLocationCode {
- DomKeyLocationStandard,
- DomKeyLocationLeft,
- DomKeyLocationRight,
- DomKeyLocationNumpad
- };
- enum EvasKeyModifier {
- EvasKeyModifierNone = 0,
- EvasKeyModifierControl = 1 << 0,
- EvasKeyModifierShift = 1 << 1,
- EvasKeyModifierAlt = 1 << 2,
- EvasKeyModifierMeta = 1 << 3
- };
- enum EvasMouseButton {
- EvasMouseButtonNone,
- EvasMouseButtonLeft,
- EvasMouseButtonMiddle,
- EvasMouseButtonRight
- };
- enum EvasMouseEvent {
- EvasMouseEventNone = 0,
- EvasMouseEventDown = 1 << 0,
- EvasMouseEventUp = 1 << 1,
- EvasMouseEventMove = 1 << 2,
- EvasMouseEventScrollUp = 1 << 3,
- EvasMouseEventScrollDown = 1 << 4,
- EvasMouseEventScrollLeft = 1 << 5,
- EvasMouseEventScrollRight = 1 << 6,
- EvasMouseEventClick = EvasMouseEventMove | EvasMouseEventDown | EvasMouseEventUp,
- };
- enum ZoomEvent {
- ZoomIn,
- ZoomOut
- };
- enum EventQueueStrategy {
- FeedQueuedEvents,
- DoNotFeedQueuedEvents
- };
- struct KeyEventInfo {
- KeyEventInfo(const CString& keyName, unsigned modifiers, const CString& keyString = CString())
- : keyName(keyName)
- , keyString(keyString)
- , modifiers(modifiers)
- {
- }
- const CString keyName;
- const CString keyString;
- unsigned modifiers;
- };
- struct MouseEventInfo {
- MouseEventInfo(EvasMouseEvent event, unsigned modifiers = EvasKeyModifierNone, EvasMouseButton button = EvasMouseButtonNone, int horizontalDelta = 0, int verticalDelta = 0)
- : event(event)
- , modifiers(modifiers)
- , button(button)
- , horizontalDelta(horizontalDelta)
- , verticalDelta(verticalDelta)
- {
- }
- EvasMouseEvent event;
- unsigned modifiers;
- EvasMouseButton button;
- int horizontalDelta;
- int verticalDelta;
- };
- struct DelayedEvent {
- DelayedEvent(MouseEventInfo* eventInfo, unsigned long delay = 0)
- : eventInfo(eventInfo)
- , delay(delay)
- {
- }
- MouseEventInfo* eventInfo;
- unsigned long delay;
- };
- struct TouchEventInfo {
- TouchEventInfo(unsigned id, Ewk_Touch_Point_Type state, const WebCore::IntPoint& point)
- : state(state)
- , point(point)
- , id(id)
- {
- }
- unsigned id;
- Ewk_Touch_Point_Type state;
- WebCore::IntPoint point;
- };
- static unsigned touchModifiers;
- WTF::Vector<TouchEventInfo>& touchPointList()
- {
- DEFINE_STATIC_LOCAL(WTF::Vector<TouchEventInfo>, staticTouchPointList, ());
- return staticTouchPointList;
- }
- WTF::Vector<DelayedEvent>& delayedEventQueue()
- {
- DEFINE_STATIC_LOCAL(WTF::Vector<DelayedEvent>, staticDelayedEventQueue, ());
- return staticDelayedEventQueue;
- }
- static void feedOrQueueMouseEvent(MouseEventInfo*, EventQueueStrategy);
- static void feedMouseEvent(MouseEventInfo*);
- static void feedQueuedMouseEvents();
- static void setEvasModifiers(Evas* evas, unsigned modifiers)
- {
- static const char* modifierNames[] = { "Control", "Shift", "Alt", "Super" };
- for (unsigned modifier = 0; modifier < 4; ++modifier) {
- if (modifiers & (1 << modifier))
- evas_key_modifier_on(evas, modifierNames[modifier]);
- else
- evas_key_modifier_off(evas, modifierNames[modifier]);
- }
- }
- static EvasMouseButton translateMouseButtonNumber(int eventSenderButtonNumber)
- {
- static const EvasMouseButton translationTable[] = {
- EvasMouseButtonLeft,
- EvasMouseButtonMiddle,
- EvasMouseButtonRight,
- EvasMouseButtonMiddle // fast/events/mouse-click-events expects the 4th button to be treated as the middle button
- };
- static const unsigned translationTableSize = sizeof(translationTable) / sizeof(translationTable[0]);
- if (eventSenderButtonNumber < translationTableSize)
- return translationTable[eventSenderButtonNumber];
- return EvasMouseButtonLeft;
- }
- static Eina_Bool sendClick(void*)
- {
- MouseEventInfo* eventInfo = new MouseEventInfo(EvasMouseEventClick, EvasKeyModifierNone, EvasMouseButtonLeft);
- feedOrQueueMouseEvent(eventInfo, FeedQueuedEvents);
- return ECORE_CALLBACK_CANCEL;
- }
- static JSValueRef scheduleAsynchronousClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- ecore_idler_add(sendClick, 0);
- return JSValueMakeUndefined(context);
- }
- static void updateClickCount(int button)
- {
- if (gLastClickPositionX != gLastMousePositionX
- || gLastClickPositionY != gLastMousePositionY
- || gLastClickButton != button
- || gTimeOffset - gLastClickTimeOffset >= 1)
- gClickCount = 1;
- else
- gClickCount++;
- }
- static EvasKeyModifier modifierFromJSValue(JSContextRef context, const JSValueRef value)
- {
- JSRetainPtr<JSStringRef> jsKeyValue(Adopt, JSValueToStringCopy(context, value, 0));
- if (equals(jsKeyValue, "ctrlKey") || equals(jsKeyValue, "addSelectionKey"))
- return EvasKeyModifierControl;
- if (equals(jsKeyValue, "shiftKey") || equals(jsKeyValue, "rangeSelectionKey"))
- return EvasKeyModifierShift;
- if (equals(jsKeyValue, "altKey"))
- return EvasKeyModifierAlt;
- if (equals(jsKeyValue, "metaKey"))
- return EvasKeyModifierMeta;
- return EvasKeyModifierNone;
- }
- static unsigned modifiersFromJSValue(JSContextRef context, const JSValueRef modifiers)
- {
- // The value may either be a string with a single modifier or an array of modifiers.
- if (JSValueIsString(context, modifiers))
- return modifierFromJSValue(context, modifiers);
- JSObjectRef modifiersArray = JSValueToObject(context, modifiers, 0);
- if (!modifiersArray)
- return EvasKeyModifierNone;
- unsigned modifier = EvasKeyModifierNone;
- JSRetainPtr<JSStringRef> lengthProperty(Adopt, JSStringCreateWithUTF8CString("length"));
- int modifiersCount = JSValueToNumber(context, JSObjectGetProperty(context, modifiersArray, lengthProperty.get(), 0), 0);
- for (int i = 0; i < modifiersCount; ++i)
- modifier |= modifierFromJSValue(context, JSObjectGetPropertyAtIndex(context, modifiersArray, i, 0));
- return modifier;
- }
- static JSValueRef getMenuItemTitleCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
- {
- Ewk_Context_Menu_Item* item = static_cast<Ewk_Context_Menu_Item*>(JSObjectGetPrivate(object));
- CString label;
- if (ewk_context_menu_item_type_get(item) == EWK_SEPARATOR_TYPE)
- label = "<separator>";
- else
- label = ewk_context_menu_item_title_get(item);
- return JSValueMakeString(context, JSStringCreateWithUTF8CString(label.data()));
- }
- static bool setMenuItemTitleCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
- {
- return true;
- }
- static JSValueRef menuItemClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- Ewk_Context_Menu_Item* item = static_cast<Ewk_Context_Menu_Item*>(JSObjectGetPrivate(thisObject));
- ewk_context_menu_item_select(ewk_context_menu_item_parent_get(item), item);
- return JSValueMakeUndefined(context);
- }
- static JSStaticFunction staticMenuItemFunctions[] = {
- { "click", menuItemClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { 0, 0, 0 }
- };
- static JSStaticValue staticMenuItemValues[] = {
- { "title", getMenuItemTitleCallback, setMenuItemTitleCallback, kJSPropertyAttributeNone },
- { 0, 0, 0, 0 }
- };
- static JSClassRef getMenuItemClass()
- {
- static JSClassRef menuItemClass = 0;
- if (!menuItemClass) {
- JSClassDefinition classDefinition = {
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- classDefinition.staticFunctions = staticMenuItemFunctions;
- classDefinition.staticValues = staticMenuItemValues;
- menuItemClass = JSClassCreate(&classDefinition);
- }
- return menuItemClass;
- }
- static JSValueRef contextClickCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- Evas_Object* view = ewk_frame_view_get(browser->mainFrame());
- if (!view)
- return JSValueMakeUndefined(context);
- Evas* evas = evas_object_evas_get(view);
- if (!evas)
- return JSValueMakeUndefined(context);
- Evas_Event_Mouse_Down mouseDown;
- mouseDown.button = 3;
- mouseDown.output.x = gLastMousePositionX;
- mouseDown.output.y = gLastMousePositionY;
- mouseDown.canvas.x = gLastMousePositionX;
- mouseDown.canvas.y = gLastMousePositionY;
- mouseDown.data = 0;
- mouseDown.modifiers = const_cast<Evas_Modifier*>(evas_key_modifier_get(evas));
- mouseDown.locks = const_cast<Evas_Lock*>(evas_key_lock_get(evas));
- mouseDown.flags = EVAS_BUTTON_NONE;
- mouseDown.timestamp = ecore_loop_time_get();
- mouseDown.event_flags = EVAS_EVENT_FLAG_NONE;
- mouseDown.dev = 0;
- ewk_view_context_menu_forward_event(view, &mouseDown);
- Ewk_Context_Menu* ewkMenu = ewk_view_context_menu_get(view);
- JSValueRef valueRef = JSObjectMakeArray(context, 0, 0, 0);
- if (ewkMenu) {
- const Eina_List* ewkMenuItems = ewk_context_menu_item_list_get(ewkMenu);
- JSValueRef arrayValues[eina_list_count(ewkMenuItems)];
- const Eina_List* listIterator;
- void* data;
- int index = 0;
- EINA_LIST_FOREACH(ewkMenuItems, listIterator, data)
- arrayValues[index++] = JSObjectMake(context, getMenuItemClass(), data);
- if (index)
- valueRef = JSObjectMakeArray(context, index - 1, arrayValues, 0);
- }
- return valueRef;
- }
- 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<int>(JSValueToNumber(context, arguments[0], exception));
- if (exception && *exception)
- return JSValueMakeUndefined(context);
- }
- button = translateMouseButtonNumber(button);
- // If the same mouse button is already in the down position don't send another event as it may confuse Xvfb.
- if (gButtonCurrentlyDown == button)
- return JSValueMakeUndefined(context);
- updateClickCount(button);
- unsigned modifiers = argumentCount >= 2 ? modifiersFromJSValue(context, arguments[1]) : EvasKeyModifierNone;
- MouseEventInfo* eventInfo = new MouseEventInfo(EvasMouseEventDown, modifiers, static_cast<EvasMouseButton>(button));
- feedOrQueueMouseEvent(eventInfo, FeedQueuedEvents);
- gButtonCurrentlyDown = button;
- return JSValueMakeUndefined(context);
- }
- 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<int>(JSValueToNumber(context, arguments[0], exception));
- if (exception && *exception)
- return JSValueMakeUndefined(context);
- }
- gLastClickPositionX = gLastMousePositionX;
- gLastClickPositionY = gLastMousePositionY;
- gLastClickButton = gButtonCurrentlyDown;
- gLastClickTimeOffset = gTimeOffset;
- gButtonCurrentlyDown = 0;
- unsigned modifiers = argumentCount >= 2 ? modifiersFromJSValue(context, arguments[1]) : EvasKeyModifierNone;
- MouseEventInfo* eventInfo = new MouseEventInfo(EvasMouseEventUp, modifiers, translateMouseButtonNumber(button));
- feedOrQueueMouseEvent(eventInfo, FeedQueuedEvents);
- return JSValueMakeUndefined(context);
- }
- static JSValueRef mouseMoveToCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- if (argumentCount < 2)
- return JSValueMakeUndefined(context);
- gLastMousePositionX = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
- if (exception && *exception)
- return JSValueMakeUndefined(context);
- gLastMousePositionY = static_cast<int>(JSValueToNumber(context, arguments[1], exception));
- if (exception && *exception)
- return JSValueMakeUndefined(context);
- MouseEventInfo* eventInfo = new MouseEventInfo(EvasMouseEventMove);
- feedOrQueueMouseEvent(eventInfo, DoNotFeedQueuedEvents);
- return JSValueMakeUndefined(context);
- }
- static JSValueRef leapForwardCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- if (argumentCount > 0) {
- const unsigned long leapForwardDelay = JSValueToNumber(context, arguments[0], exception);
- if (delayedEventQueue().isEmpty())
- delayedEventQueue().append(DelayedEvent(0, leapForwardDelay));
- else
- delayedEventQueue().last().delay = leapForwardDelay;
- gTimeOffset += leapForwardDelay;
- }
- return JSValueMakeUndefined(context);
- }
- static EvasMouseEvent evasMouseEventFromHorizontalAndVerticalOffsets(int horizontalOffset, int verticalOffset)
- {
- unsigned mouseEvent = 0;
- if (verticalOffset > 0)
- mouseEvent |= EvasMouseEventScrollUp;
- else if (verticalOffset < 0)
- mouseEvent |= EvasMouseEventScrollDown;
- if (horizontalOffset > 0)
- mouseEvent |= EvasMouseEventScrollRight;
- else if (horizontalOffset < 0)
- mouseEvent |= EvasMouseEventScrollLeft;
- return static_cast<EvasMouseEvent>(mouseEvent);
- }
- static JSValueRef mouseScrollByCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- if (argumentCount < 2)
- return JSValueMakeUndefined(context);
- // We need to invert scrolling values since in EFL negative z value means that
- // canvas is scrolling down
- const int horizontal = -(static_cast<int>(JSValueToNumber(context, arguments[0], exception)));
- if (exception && *exception)
- return JSValueMakeUndefined(context);
- const int vertical = -(static_cast<int>(JSValueToNumber(context, arguments[1], exception)));
- if (exception && *exception)
- return JSValueMakeUndefined(context);
- MouseEventInfo* eventInfo = new MouseEventInfo(evasMouseEventFromHorizontalAndVerticalOffsets(horizontal, vertical), EvasKeyModifierNone, EvasMouseButtonNone, horizontal, vertical);
- feedOrQueueMouseEvent(eventInfo, FeedQueuedEvents);
- return JSValueMakeUndefined(context);
- }
- static JSValueRef continuousMouseScrollByCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- return JSValueMakeUndefined(context);
- }
- static KeyEventInfo* keyPadNameFromJSValue(JSStringRef character, unsigned modifiers)
- {
- if (equals(character, "leftArrow"))
- return new KeyEventInfo("KP_Left", modifiers);
- if (equals(character, "rightArrow"))
- return new KeyEventInfo("KP_Right", modifiers);
- if (equals(character, "upArrow"))
- return new KeyEventInfo("KP_Up", modifiers);
- if (equals(character, "downArrow"))
- return new KeyEventInfo("KP_Down", modifiers);
- if (equals(character, "pageUp"))
- return new KeyEventInfo("KP_Prior", modifiers);
- if (equals(character, "pageDown"))
- return new KeyEventInfo("KP_Next", modifiers);
- if (equals(character, "home"))
- return new KeyEventInfo("KP_Home", modifiers);
- if (equals(character, "end"))
- return new KeyEventInfo("KP_End", modifiers);
- if (equals(character, "insert"))
- return new KeyEventInfo("KP_Insert", modifiers);
- if (equals(character, "delete"))
- return new KeyEventInfo("KP_Delete", modifiers);
- return new KeyEventInfo(character->string().utf8(), modifiers, character->string().utf8());
- }
- static KeyEventInfo* keyNameFromJSValue(JSStringRef character, unsigned modifiers)
- {
- if (equals(character, "leftArrow"))
- return new KeyEventInfo("Left", modifiers);
- if (equals(character, "rightArrow"))
- return new KeyEventInfo("Right", modifiers);
- if (equals(character, "upArrow"))
- return new KeyEventInfo("Up", modifiers);
- if (equals(character, "downArrow"))
- return new KeyEventInfo("Down", modifiers);
- if (equals(character, "pageUp"))
- return new KeyEventInfo("Prior", modifiers);
- if (equals(character, "pageDown"))
- return new KeyEventInfo("Next", modifiers);
- if (equals(character, "home"))
- return new KeyEventInfo("Home", modifiers);
- if (equals(character, "end"))
- return new KeyEventInfo("End", modifiers);
- if (equals(character, "insert"))
- return new KeyEventInfo("Insert", modifiers);
- if (equals(character, "delete"))
- return new KeyEventInfo("Delete", modifiers);
- if (equals(character, "printScreen"))
- return new KeyEventInfo("Print", modifiers);
- if (equals(character, "menu"))
- return new KeyEventInfo("Menu", modifiers);
- if (equals(character, "leftControl"))
- return new KeyEventInfo("Control_L", modifiers);
- if (equals(character, "rightControl"))
- return new KeyEventInfo("Control_R", modifiers);
- if (equals(character, "leftShift"))
- return new KeyEventInfo("Shift_L", modifiers);
- if (equals(character, "rightShift"))
- return new KeyEventInfo("Shift_R", modifiers);
- if (equals(character, "leftAlt"))
- return new KeyEventInfo("Alt_L", modifiers);
- if (equals(character, "rightAlt"))
- return new KeyEventInfo("Alt_R", modifiers);
- if (equals(character, "F1"))
- return new KeyEventInfo("F1", modifiers);
- if (equals(character, "F2"))
- return new KeyEventInfo("F2", modifiers);
- if (equals(character, "F3"))
- return new KeyEventInfo("F3", modifiers);
- if (equals(character, "F4"))
- return new KeyEventInfo("F4", modifiers);
- if (equals(character, "F5"))
- return new KeyEventInfo("F5", modifiers);
- if (equals(character, "F6"))
- return new KeyEventInfo("F6", modifiers);
- if (equals(character, "F7"))
- return new KeyEventInfo("F7", modifiers);
- if (equals(character, "F8"))
- return new KeyEventInfo("F8", modifiers);
- if (equals(character, "F9"))
- return new KeyEventInfo("F9", modifiers);
- if (equals(character, "F10"))
- return new KeyEventInfo("F10", modifiers);
- if (equals(character, "F11"))
- return new KeyEventInfo("F11", modifiers);
- if (equals(character, "F12"))
- return new KeyEventInfo("F12", modifiers);
- int charCode = JSStringGetCharactersPtr(character)[0];
- if (charCode == '\n' || charCode == '\r')
- return new KeyEventInfo("Return", modifiers, "\r");
- if (charCode == '\t')
- return new KeyEventInfo("Tab", modifiers, "\t");
- if (charCode == '\x8')
- return new KeyEventInfo("BackSpace", modifiers, "\x8");
- if (charCode == ' ')
- return new KeyEventInfo("space", modifiers, " ");
- if (charCode == '\x1B')
- return new KeyEventInfo("Escape", modifiers, "\x1B");
- if ((character->length() == 1) && (charCode >= 'A' && charCode <= 'Z'))
- modifiers |= EvasKeyModifierShift;
- return new KeyEventInfo(character->string().utf8(), modifiers, character->string().utf8());
- }
- static KeyEventInfo* createKeyEventInfo(JSContextRef context, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- if (!ewk_frame_view_get(browser->mainFrame()))
- return 0;
- if (argumentCount < 1)
- return 0;
- // handle location argument.
- int location = DomKeyLocationStandard;
- if (argumentCount > 2)
- location = static_cast<int>(JSValueToNumber(context, arguments[2], exception));
- JSRetainPtr<JSStringRef> character(Adopt, JSValueToStringCopy(context, arguments[0], exception));
- if (exception && *exception)
- return 0;
- unsigned modifiers = EvasKeyModifierNone;
- if (argumentCount >= 2)
- modifiers = modifiersFromJSValue(context, arguments[1]);
- return (location == DomKeyLocationNumpad) ? keyPadNameFromJSValue(character.get(), modifiers) : keyNameFromJSValue(character.get(), modifiers);
- }
- static void sendKeyDown(Evas* evas, KeyEventInfo* keyEventInfo)
- {
- if (!keyEventInfo)
- return;
- const char* keyName = keyEventInfo->keyName.data();
- const char* keyString = keyEventInfo->keyString.data();
- unsigned modifiers = keyEventInfo->modifiers;
- DumpRenderTreeSupportEfl::layoutFrame(browser->mainFrame());
- ASSERT(evas);
- int eventIndex = 0;
- // Mimic the emacs ctrl-o binding by inserting a paragraph
- // separator and then putting the cursor back to its original
- // position. Allows us to pass emacs-ctrl-o.html
- if ((modifiers & EvasKeyModifierControl) && !strcmp(keyName, "o")) {
- setEvasModifiers(evas, EvasKeyModifierNone);
- evas_event_feed_key_down(evas, "Return", "Return", "\r", 0, eventIndex++, 0);
- evas_event_feed_key_up(evas, "Return", "Return", "\r", 0, eventIndex++, 0);
- modifiers = EvasKeyModifierNone;
- keyName = "Left";
- keyString = 0;
- }
- setEvasModifiers(evas, modifiers);
- evas_event_feed_key_down(evas, keyName, keyName, keyString, 0, eventIndex++, 0);
- evas_event_feed_key_up(evas, keyName, keyName, keyString, 0, eventIndex++, 0);
- setEvasModifiers(evas, EvasKeyModifierNone);
- DumpRenderTreeSupportEfl::deliverAllMutationsIfNecessary();
- }
- static JSValueRef keyDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- OwnPtr<KeyEventInfo> keyEventInfo = adoptPtr(createKeyEventInfo(context, argumentCount, arguments, exception));
- sendKeyDown(evas_object_evas_get(browser->mainFrame()), keyEventInfo.get());
- return JSValueMakeUndefined(context);
- }
- static JSValueRef scalePageByCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- if (argumentCount < 3)
- return JSValueMakeUndefined(context);
- Evas_Object* view = ewk_frame_view_get(browser->mainFrame());
- if (!view)
- return JSValueMakeUndefined(context);
- float scaleFactor = JSValueToNumber(context, arguments[0], exception);
- float x = JSValueToNumber(context, arguments[1], exception);
- float y = JSValueToNumber(context, arguments[2], exception);
- ewk_view_scale_set(view, scaleFactor, x, y);
- return JSValueMakeUndefined(context);
- }
- static void textZoom(ZoomEvent zoomEvent)
- {
- Evas_Object* view = ewk_frame_view_get(browser->mainFrame());
- if (!view)
- return;
- float zoomFactor = ewk_view_text_zoom_get(view);
- if (zoomEvent == ZoomIn)
- zoomFactor *= zoomMultiplierRatio;
- else
- zoomFactor /= zoomMultiplierRatio;
- ewk_view_text_zoom_set(view, zoomFactor);
- }
- static void pageZoom(ZoomEvent zoomEvent)
- {
- Evas_Object* view = ewk_frame_view_get(browser->mainFrame());
- if (!view)
- return;
- float zoomFactor = ewk_view_page_zoom_get(view);
- if (zoomEvent == ZoomIn)
- zoomFactor *= zoomMultiplierRatio;
- else
- zoomFactor /= zoomMultiplierRatio;
- ewk_view_page_zoom_set(view, zoomFactor);
- }
- static JSValueRef textZoomInCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- textZoom(ZoomIn);
- return JSValueMakeUndefined(context);
- }
- static JSValueRef textZoomOutCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- textZoom(ZoomOut);
- return JSValueMakeUndefined(context);
- }
- static JSValueRef zoomPageInCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- pageZoom(ZoomIn);
- return JSValueMakeUndefined(context);
- }
- static JSValueRef zoomPageOutCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- pageZoom(ZoomOut);
- return JSValueMakeUndefined(context);
- }
- static Eina_Bool sendAsynchronousKeyDown(void* userData)
- {
- OwnPtr<KeyEventInfo> keyEventInfo = adoptPtr(static_cast<KeyEventInfo*>(userData));
- sendKeyDown(evas_object_evas_get(browser->mainFrame()), keyEventInfo.get());
- return ECORE_CALLBACK_CANCEL;
- }
- static JSValueRef scheduleAsynchronousKeyDownCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- KeyEventInfo* keyEventInfo = createKeyEventInfo(context, argumentCount, arguments, exception);
- ecore_idler_add(sendAsynchronousKeyDown, static_cast<void*>(keyEventInfo));
- return JSValueMakeUndefined(context);
- }
- static void sendTouchEvent(Ewk_Touch_Event_Type type)
- {
- Eina_List* eventList = 0;
- for (unsigned i = 0; i < touchPointList().size(); ++i) {
- Ewk_Touch_Point* event = new Ewk_Touch_Point;
- WebCore::IntPoint point = touchPointList().at(i).point;
- event->id = touchPointList().at(i).id;
- event->x = point.x();
- event->y = point.y();
- event->state = touchPointList().at(i).state;
- eventList = eina_list_append(eventList, event);
- }
- ewk_frame_feed_touch_event(browser->mainFrame(), type, eventList, touchModifiers);
- void* listData;
- EINA_LIST_FREE(eventList, listData) {
- Ewk_Touch_Point* event = static_cast<Ewk_Touch_Point*>(listData);
- delete event;
- }
- for (unsigned i = 0; i < touchPointList().size(); ) {
- if (touchPointList().at(i).state == EWK_TOUCH_POINT_RELEASED)
- touchPointList().remove(i);
- else {
- touchPointList().at(i).state = EWK_TOUCH_POINT_STATIONARY;
- ++i;
- }
- }
- }
- static JSValueRef addTouchPointCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- if (argumentCount != 2)
- return JSValueMakeUndefined(context);
- int x = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
- ASSERT(!exception || !*exception);
- int y = static_cast<int>(JSValueToNumber(context, arguments[1], exception));
- ASSERT(!exception || !*exception);
- const WebCore::IntPoint point(x, y);
- const unsigned id = touchPointList().isEmpty() ? 0 : touchPointList().last().id + 1;
- TouchEventInfo eventInfo(id, EWK_TOUCH_POINT_PRESSED, point);
- touchPointList().append(eventInfo);
- return JSValueMakeUndefined(context);
- }
- static JSValueRef touchStartCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- sendTouchEvent(EWK_TOUCH_START);
- return JSValueMakeUndefined(context);
- }
- static JSValueRef updateTouchPointCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- if (argumentCount != 3)
- return JSValueMakeUndefined(context);
- int index = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
- ASSERT(!exception || !*exception);
- int x = static_cast<int>(JSValueToNumber(context, arguments[1], exception));
- ASSERT(!exception || !*exception);
- int y = static_cast<int>(JSValueToNumber(context, arguments[2], exception));
- ASSERT(!exception || !*exception);
- if (index < 0 || index >= touchPointList().size())
- return JSValueMakeUndefined(context);
- WebCore::IntPoint& point = touchPointList().at(index).point;
- point.setX(x);
- point.setY(y);
- touchPointList().at(index).state = EWK_TOUCH_POINT_MOVED;
- return JSValueMakeUndefined(context);
- }
- static JSValueRef touchMoveCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- sendTouchEvent(EWK_TOUCH_MOVE);
- return JSValueMakeUndefined(context);
- }
- static JSValueRef cancelTouchPointCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- if (argumentCount != 1)
- return JSValueMakeUndefined(context);
- int index = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
- ASSERT(!exception || !*exception);
- if (index < 0 || index >= touchPointList().size())
- return JSValueMakeUndefined(context);
- touchPointList().at(index).state = EWK_TOUCH_POINT_CANCELLED;
- return JSValueMakeUndefined(context);
- }
- static JSValueRef touchCancelCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- sendTouchEvent(EWK_TOUCH_CANCEL);
- return JSValueMakeUndefined(context);
- }
- static JSValueRef releaseTouchPointCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- if (argumentCount != 1)
- return JSValueMakeUndefined(context);
- int index = static_cast<int>(JSValueToNumber(context, arguments[0], exception));
- ASSERT(!exception || !*exception);
- if (index < 0 || index >= touchPointList().size())
- return JSValueMakeUndefined(context);
- touchPointList().at(index).state = EWK_TOUCH_POINT_RELEASED;
- return JSValueMakeUndefined(context);
- }
- static JSValueRef touchEndCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- sendTouchEvent(EWK_TOUCH_END);
- touchModifiers = 0;
- return JSValueMakeUndefined(context);
- }
- static JSValueRef clearTouchPointsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- touchPointList().clear();
- return JSValueMakeUndefined(context);
- }
- static JSValueRef setTouchModifierCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
- {
- if (argumentCount != 2)
- return JSValueMakeUndefined(context);
- JSRetainPtr<JSStringRef> jsModifier(Adopt, JSValueToStringCopy(context, arguments[0], exception));
- unsigned mask = 0;
- if (equals(jsModifier, "alt"))
- mask |= ECORE_EVENT_MODIFIER_ALT;
- else if (equals(jsModifier, "ctrl"))
- mask |= ECORE_EVENT_MODIFIER_CTRL;
- else if (equals(jsModifier, "meta"))
- mask |= ECORE_EVENT_MODIFIER_WIN;
- else if (equals(jsModifier, "shift"))
- mask |= ECORE_EVENT_MODIFIER_SHIFT;
- if (JSValueToBoolean(context, arguments[1]))
- touchModifiers |= mask;
- else
- touchModifiers &= ~mask;
- return JSValueMakeUndefined(context);
- }
- static JSStaticFunction staticFunctions[] = {
- { "contextClick", contextClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "mouseScrollBy", mouseScrollByCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "continuousMouseScrollBy", continuousMouseScrollByCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "mouseDown", mouseDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "mouseUp", mouseUpCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "mouseMoveTo", mouseMoveToCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "leapForward", leapForwardCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "keyDown", keyDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "scheduleAsynchronousClick", scheduleAsynchronousClickCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "scheduleAsynchronousKeyDown", scheduleAsynchronousKeyDownCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "scalePageBy", scalePageByCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "textZoomIn", textZoomInCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "textZoomOut", textZoomOutCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "zoomPageIn", zoomPageInCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "zoomPageOut", zoomPageOutCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "addTouchPoint", addTouchPointCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "touchStart", touchStartCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "updateTouchPoint", updateTouchPointCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "touchMove", touchMoveCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "releaseTouchPoint", releaseTouchPointCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "touchEnd", touchEndCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "cancelTouchPoint", cancelTouchPointCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "touchCancel", touchCancelCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "clearTouchPoints", clearTouchPointsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { "setTouchModifier", setTouchModifierCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
- { 0, 0, 0 }
- };
- static JSStaticValue staticValues[] = {
- { 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) {
- gDragMode = 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.
- gTimeOffset += 1000;
- gLastMousePositionX = gLastMousePositionY = 0;
- gLastClickPositionX = gLastClickPositionY = 0;
- gLastClickTimeOffset = 0;
- gLastClickButton = 0;
- gButtonCurrentlyDown = 0;
- gClickCount = 0;
- }
- return JSObjectMake(context, getClass(context), 0);
- }
- static void feedOrQueueMouseEvent(MouseEventInfo* eventInfo, EventQueueStrategy strategy)
- {
- if (!delayedEventQueue().isEmpty()) {
- if (delayedEventQueue().last().eventInfo)
- delayedEventQueue().append(DelayedEvent(eventInfo));
- else
- delayedEventQueue().last().eventInfo = eventInfo;
- if (strategy == FeedQueuedEvents)
- feedQueuedMouseEvents();
- } else
- feedMouseEvent(eventInfo);
- }
- static void feedMouseEvent(MouseEventInfo* eventInfo)
- {
- if (!eventInfo)
- return;
- unsigned timeStamp = 0;
- Evas_Object* mainFrame = browser->mainFrame();
- Evas* evas = evas_object_evas_get(mainFrame);
- EvasMouseEvent event = eventInfo->event;
- setEvasModifiers(evas, eventInfo->modifiers);
- Evas_Button_Flags flags = EVAS_BUTTON_NONE;
- // FIXME: We need to pass additional information with our events, so that
- // we could construct correct PlatformWheelEvent. At the moment, max number
- // of clicks is 3
- if (gClickCount == 3)
- flags = EVAS_BUTTON_TRIPLE_CLICK;
- else if (gClickCount == 2)
- flags = EVAS_BUTTON_DOUBLE_CLICK;
- if (event & EvasMouseEventMove)
- evas_event_feed_mouse_move(evas, gLastMousePositionX, gLastMousePositionY, timeStamp++, 0);
- if (event & EvasMouseEventDown)
- evas_event_feed_mouse_down(evas, eventInfo->button, flags, timeStamp++, 0);
- if (event & EvasMouseEventUp)
- evas_event_feed_mouse_up(evas, eventInfo->button, flags, timeStamp++, 0);
- if (event & EvasMouseEventScrollLeft | event & EvasMouseEventScrollRight)
- evas_event_feed_mouse_wheel(evas, 1, eventInfo->horizontalDelta, timeStamp, 0);
- if (event & EvasMouseEventScrollUp | event & EvasMouseEventScrollDown)
- evas_event_feed_mouse_wheel(evas, 0, eventInfo->verticalDelta, timeStamp, 0);
- setEvasModifiers(evas, EvasKeyModifierNone);
- delete eventInfo;
- }
- static void feedQueuedMouseEvents()
- {
- WTF::Vector<DelayedEvent>::const_iterator it = delayedEventQueue().begin();
- for (; it != delayedEventQueue().end(); it++) {
- DelayedEvent delayedEvent = *it;
- if (delayedEvent.delay)
- usleep(delayedEvent.delay * 1000);
- feedMouseEvent(delayedEvent.eventInfo);
- }
- delayedEventQueue().clear();
- }
|