void MobileSimulator::MouseDownEvent(Vec2i screenCoordinates, MouseButtonInput button)
{
	_mouseDown = true;

	TouchList* tl = &TouchListener::GetTouchList();

	if (theInput.IsKeyDown(ANGEL_KEY_LEFTCONTROL) || theInput.IsKeyDown(ANGEL_KEY_RIGHTCONTROL))
	{
		// add the two touches
		Touch* t = new Touch();
		t->__platformTouch = NULL;
		t->StartingPoint = screenCoordinates;
		t->CurrentPoint = t->StartingPoint;
		tl->push_back(t);
		SendTouchNotifiers(t, TOUCH_START);

		t = new Touch();
		t->__platformTouch = NULL;
		Vector2 pos2 = MathUtil::WorldToScreen(_fingerGhost2->GetPosition());
		t->StartingPoint = Vec2i(pos2.X, pos2.Y);
		t->CurrentPoint = t->StartingPoint;
		tl->push_back(t);
		SendTouchNotifiers(t, TOUCH_START);
	}
	else
	{
		// just a single touch
		Touch* t = new Touch();
		t->__platformTouch = NULL;
		t->StartingPoint = screenCoordinates;
		t->CurrentPoint = t->StartingPoint;
		tl->push_back(t);
		SendTouchNotifiers(t, TOUCH_START);
	}
}
void PluginView::handleTouchEvent(TouchEvent* event)
{
    if (!m_window->isAcceptingEvent(kTouch_ANPEventFlag))
        return;

    if (!m_window->inFullScreen() && m_parentFrame->document()->focusedNode() != m_element)
        return;

    ANPEvent evt;
    SkANP::InitEvent(&evt, kMultiTouch_ANPEventType);

    const AtomicString& type = event->type();
    if (eventNames().touchstartEvent == type)
        evt.data.multiTouch.action = kDown_ANPTouchAction;
    else if (eventNames().touchendEvent == type)
        evt.data.multiTouch.action = kUp_ANPTouchAction;
    else if (eventNames().touchmoveEvent == type)
        evt.data.multiTouch.action = kMove_ANPTouchAction;
    else if (eventNames().touchcancelEvent == type)
        evt.data.multiTouch.action = kCancel_ANPTouchAction;
    else if (eventNames().touchlongpressEvent == type)
        evt.data.multiTouch.action = kLongPress_ANPTouchAction;
    else if (eventNames().touchdoubletapEvent == type)
        evt.data.multiTouch.action = kDoubleTap_ANPTouchAction;
    else
        return;

    // set the id and timestamp
    evt.data.multiTouch.id = 0; // TODO
    evt.data.multiTouch.timestamp = 0; // TODO

    // In the event of a touchend (up) or touchcancel event, we must ask the changedTouch for the
    // co-ordinates as there is no touch in touches anymore.
    TouchList* touches = (evt.data.multiTouch.action == kUp_ANPTouchAction
        || evt.data.multiTouch.action == kCancel_ANPTouchAction) ? event->changedTouches() : event->touches();

    // set each touchPoint
    int pointerCount = touches->length();
    evt.data.multiTouch.pointerCount = pointerCount;
    evt.data.multiTouch.touchPoint = new TouchPoint[pointerCount];

    for (int x = 0; x < evt.data.multiTouch.pointerCount; x++) {
        Touch* touch = touches->item(x);
        // Convert to coordinates that are relative to the plugin.
        IntPoint localPos = roundedIntPoint(m_element->renderer()->absoluteToLocal(IntPoint(touch->pageX(), touch->pageY())));

        evt.data.multiTouch.touchPoint[x].id = touch->identifier();
        evt.data.multiTouch.touchPoint[x].x = localPos.x();
        evt.data.multiTouch.touchPoint[x].y = localPos.y();
        evt.data.multiTouch.touchPoint[x].pressure = 1; // TODO
        evt.data.multiTouch.touchPoint[x].size = 1; // TODO
    }

    if (m_window->sendEvent(evt))
        event->preventDefault();

    // cleanup the touch points we allocated
    delete[] evt.data.multiTouch.touchPoint;
}
Exemplo n.º 3
0
JSValue jsTouchListLength(ExecState* exec, JSValue slotBase, const Identifier&)
{
    JSTouchList* castedThis = static_cast<JSTouchList*>(asObject(slotBase));
    UNUSED_PARAM(exec);
    TouchList* imp = static_cast<TouchList*>(castedThis->impl());
    JSValue result = jsNumber(imp->length());
    return result;
}
Exemplo n.º 4
0
void RangeInputType::handleTouchEvent(TouchEvent* event)
{
    if (element().isDisabledOrReadOnly())
        return;

    if (event->type() == EventTypeNames::touchend) {
        event->setDefaultHandled();
        return;
    }

    TouchList* touches = event->targetTouches();
    if (touches->length() == 1) {
        sliderThumbElement()->setPositionFromPoint(touches->item(0)->absoluteLocation());
        event->setDefaultHandled();
    }
}
Exemplo n.º 5
0
void SliderThumbElement::handleTouchStart(TouchEvent* touchEvent)
{
    TouchList* targetTouches = touchEvent->targetTouches();
    if (targetTouches->length() != 1)
        return;

    // Ignore the touch if it is not really inside the thumb.
    Touch* touch = targetTouches->item(0);
    IntRect boundingBox = renderer()->absoluteBoundingBoxRect();
    if (!boundingBox.contains(touch->pageX(), touch->pageY()))
        return;

    setExclusiveTouchIdentifier(touch->identifier());

    startDragging();
    touchEvent->setDefaultHandled();
}
Exemplo n.º 6
0
EncodedJSValue JSC_HOST_CALL jsTouchListPrototypeFunctionItem(ExecState* exec)
{
    JSValue thisValue = exec->hostThisValue();
    if (!thisValue.inherits(&JSTouchList::s_info))
        return throwVMTypeError(exec);
    JSTouchList* castedThis = static_cast<JSTouchList*>(asObject(thisValue));
    ASSERT_GC_OBJECT_INHERITS(castedThis, &JSTouchList::s_info);
    TouchList* imp = static_cast<TouchList*>(castedThis->impl());
    if (exec->argumentCount() < 1)
        return throwVMError(exec, createTypeError(exec, "Not enough arguments"));
    unsigned index(exec->argument(0).toUInt32(exec));
    if (exec->hadException())
        return JSValue::encode(jsUndefined());


    JSC::JSValue result = toJS(exec, castedThis->globalObject(), WTF::getPtr(imp->item(index)));
    return JSValue::encode(result);
}
Exemplo n.º 7
0
void RangeInputType::handleTouchEvent(TouchEvent* event)
{
#if PLATFORM(IOS)
    typedSliderThumbElement().handleTouchEvent(event);
#elif ENABLE(TOUCH_SLIDER)
    if (element().isDisabledOrReadOnly())
        return;

    if (event->type() == eventNames().touchendEvent) {
        event->setDefaultHandled();
        return;
    }

    TouchList* touches = event->targetTouches();
    if (touches->length() == 1) {
        typedSliderThumbElement().setPositionFromPoint(touches->item(0)->absoluteLocation());
        event->setDefaultHandled();
    }
#endif
}
Exemplo n.º 8
0
void PluginView::handleTouchEvent(TouchEvent* event)
{
    if (!m_private)
        return;

    if (!m_private->m_isFocused)
        focusPluginElement();

    NPTouchEvent npTouchEvent;

    if (event->isDoubleTap())
        npTouchEvent.type = TOUCH_EVENT_DOUBLETAP;
    else if (event->isTouchHold())
        npTouchEvent.type = TOUCH_EVENT_TOUCHHOLD;
    else if (event->type() == eventNames().touchcancelEvent)
        npTouchEvent.type = TOUCH_EVENT_CANCEL;
    else
        return;

    TouchList* touchList;
    // The touches list is empty if in a touch end event.
    // Since DoubleTap is ususally a TouchEnd Use changedTouches instead.
    if (npTouchEvent.type == TOUCH_EVENT_DOUBLETAP)
        touchList = event->changedTouches();
    else
        touchList = event->touches();

    npTouchEvent.points = 0;
    npTouchEvent.size = touchList->length();

    OwnArrayPtr<NPTouchPoint> touchPoints;
    if (touchList->length()) {
        touchPoints = adoptArrayPtr(new NPTouchPoint[touchList->length()]);
        npTouchEvent.points = touchPoints.get();
        for (unsigned i = 0; i < touchList->length(); i++) {
            Touch* touchItem = touchList->item(i);
            touchPoints[i].touchId = touchItem->identifier();
            touchPoints[i].clientX = touchItem->pageX() - frameRect().x();
            touchPoints[i].clientY = touchItem->pageY() - frameRect().y();
            touchPoints[i].screenX = touchItem->screenX();
            touchPoints[i].screenY = touchItem->screenY();
            touchPoints[i].pageX = touchItem->pageX();
            touchPoints[i].pageY = touchItem->pageY();

        }
    }

    NPEvent npEvent;
    npEvent.type = NP_TouchEvent;
    npEvent.data = &npTouchEvent;

    if (dispatchNPEvent(npEvent))
        event->setDefaultHandled();
}
Exemplo n.º 9
0
void SliderContainerElement::handleTouchEvent(TouchEvent* event) {
  HTMLInputElement* input = hostInput();
  if (input->isDisabledOrReadOnly())
    return;

  if (event->type() == EventTypeNames::touchend) {
    input->dispatchFormControlChangeEvent();
    event->setDefaultHandled();
    m_slidingDirection = NoMove;
    m_touchStarted = false;
    return;
  }

  // The direction of this series of touch actions has been determined, which is
  // perpendicular to the slider, so no need to adjust the value.
  if (!canSlide()) {
    return;
  }

  TouchList* touches = event->targetTouches();
  SliderThumbElement* thumb = toSliderThumbElement(
      treeScope().getElementById(ShadowElementNames::sliderThumb()));
  if (touches->length() == 1) {
    if (event->type() == EventTypeNames::touchstart) {
      m_startPoint = touches->item(0)->absoluteLocation();
      m_slidingDirection = NoMove;
      m_touchStarted = true;
      thumb->setPositionFromPoint(touches->item(0)->absoluteLocation());
    } else if (m_touchStarted) {
      LayoutPoint currentPoint = touches->item(0)->absoluteLocation();
      if (m_slidingDirection ==
          NoMove) {  // Still needs to update the direction.
        m_slidingDirection = getDirection(currentPoint, m_startPoint);
      }

      // m_slidingDirection has been updated, so check whether it's okay to
      // slide again.
      if (canSlide()) {
        thumb->setPositionFromPoint(touches->item(0)->absoluteLocation());
        event->setDefaultHandled();
      }
    }
  }
}
Exemplo n.º 10
0
void EventPath::checkReachability(TreeScope& treeScope, TouchList& touchList)
{
    for (size_t i = 0; i < touchList.length(); ++i)
        ASSERT(touchList.item(i)->target()->toNode()->treeScope().isInclusiveOlderSiblingShadowRootOrAncestorTreeScopeOf(treeScope));
}
Exemplo n.º 11
0
void MobileSimulator::MouseMotionEvent(Vec2i screenCoordinates)
{
	Vector2 pos = MathUtil::ScreenToWorld(screenCoordinates);
	_fingerGhost1->SetPosition(pos);
	_fingerGhost2->SetPosition(-pos);

	if (_mouseDown)
	{
		//move touch(es)
		TouchList *tl = &TouchListener::GetTouchList();
		if (tl->size() > 0)
		{
			(*tl)[0]->CurrentPoint = screenCoordinates;
			if ( (*tl)[0]->MotionStartTime < 0.0f )
			{
				(*tl)[0]->MotionStartTime = theWorld.GetCurrentTimeSeconds();
			}
		}
		if (tl->size() > 1)
		{
			Vector2 negCoordsVec = MathUtil::WorldToScreen(-pos);
			Vec2i negCoords(negCoordsVec.X, negCoordsVec.Y);
			(*tl)[1]->CurrentPoint = negCoords;
			if ( (*tl)[1]->MotionStartTime < 0.0f )
			{
				(*tl)[1]->MotionStartTime = theWorld.GetCurrentTimeSeconds();
			}

			Touch* t1 = (*tl)[0];
			Touch* t2 = (*tl)[1];

			Vector2 start1(t1->StartingPoint);
			Vector2 current1(t1->CurrentPoint);
			Vector2 start2(t2->StartingPoint);
			Vector2 current2(t2->CurrentPoint);

			Vector2 initialVector = start2 - start1;
			Vector2 currentVector = current2 - current1;

			Vector2 initNorm = Vector2::Normalize(initialVector);
			Vector2 currentNorm = Vector2::Normalize(currentVector);
			float radiansRotated = acos(Vector2::Dot(initNorm, currentNorm));

			if (!_multiGestureOngoing)
			{					
				Vector2 motion = current1 - start1;

				if (motion.LengthSquared() >= (MULTI_MIN_DISTANCE * MULTI_MIN_DISTANCE) )
				{
					_multiGestureOngoing = true;
					
					// figure out if it's a rotate or a pinch
					if (radiansRotated > MULTI_ROTATE_ANGLE)
					{
						_gestureType = ROTATE;
					}
					else
					{
						_gestureType = PINCH;
					}
				}
			}

			if (_multiGestureOngoing)
			{
				GestureData gd;
				gd.Velocity = 0.0f; // don't want to store all the extra datums
									//  needed to actually calculate this

				if      (_gestureType == ROTATE)
				{
					float cross = Vector2::Cross(initNorm, currentNorm);
					if (cross > 0.0f)
					{
						radiansRotated = -radiansRotated;
					}
					gd.GestureMagnitude = radiansRotated;
					theSwitchboard.Broadcast(new TypedMessage<GestureData>("MultiTouchRotate", gd));
				}
				else if (_gestureType == PINCH)
				{
					gd.GestureMagnitude = currentVector.Length() / initialVector.Length();
					theSwitchboard.Broadcast(new TypedMessage<GestureData>("MultiTouchPinch", gd));	
				}
			}
		}
	}
}
Exemplo n.º 12
0
void MobileSimulator::MouseUpEvent(Vec2i screenCoordinates, MouseButtonInput button)
{
	_multiGestureOngoing = false;
	_gestureType = NONE;
	_mouseDown = false;

	TouchList* tl = &TouchListener::GetTouchList();
	
	if (theInput.IsKeyDown(ANGEL_KEY_LEFTCONTROL) || theInput.IsKeyDown(ANGEL_KEY_RIGHTCONTROL))
	{
		TouchList::iterator it = tl->begin();
		while (it != tl->end())
		{
			SendTouchNotifiers((*it), TOUCH_END);
			delete (*it);
			it = tl->erase(it);
		}
	}
	else
	{
		// just a single touch, but we'll iterate anyway
		TouchList::iterator it = tl->begin();
		while (it != tl->end())
		{
			if ( (theWorld.GetCurrentTimeSeconds() - (*it)->MotionStartTime) < SWIPE_MAX_DURATION)
			{
				Vector2 start((*it)->StartingPoint.X, (*it)->StartingPoint.Y);
				Vector2 end((*it)->CurrentPoint.X, (*it)->CurrentPoint.Y);
				Vector2 motion = end - start;
				if (motion.LengthSquared() >= (SWIPE_MIN_DISTANCE * SWIPE_MIN_DISTANCE))
				{
					float angle = MathUtil::ToDegrees(acos(Vector2::Dot(Vector2::UnitX, Vector2::Normalize(motion))));
					if (motion.Y > 0.0f)
					{
						angle = 360.0f - angle;
					}

					if      ( (angle > 45.0f) && (angle <= 135.0f) )
					{
						// swipe up
						theSwitchboard.Broadcast(new Message("MultiTouchSwipeUp"));
					}
					else if ( (angle > 135.0f) && (angle <= 225.0f) )
					{
						// swipe left
						theSwitchboard.Broadcast(new Message("MultiTouchSwipeLeft"));
					}
					else if ( (angle > 225.0f) && (angle <= 315.0f) )
					{
						// swipe down
						theSwitchboard.Broadcast(new Message("MultiTouchSwipeDown"));
					}
					else
					{
						// swipe right
						theSwitchboard.Broadcast(new Message("MultiTouchSwipeRight"));
					}
				}
			}
			SendTouchNotifiers((*it), TOUCH_END);
			delete (*it);
			it = tl->erase(it);
		}
	}
}
Exemplo n.º 13
0
WebInputEventResult TouchEventManager::dispatchTouchEvents(
    const PlatformTouchEvent& event,
    const HeapVector<TouchInfo>& touchInfos,
    bool allTouchesReleased)
{
    bool touchStartOrFirstTouchMove = false;
    if (event.type() == PlatformEvent::TouchStart) {
        m_waitingForFirstTouchMove = true;
        touchStartOrFirstTouchMove = true;
    } else if (event.type() == PlatformEvent::TouchMove) {
        touchStartOrFirstTouchMove = m_waitingForFirstTouchMove;
        m_waitingForFirstTouchMove = false;
    }

    // Build up the lists to use for the |touches|, |targetTouches| and
    // |changedTouches| attributes in the JS event. See
    // http://www.w3.org/TR/touch-events/#touchevent-interface for how these
    // lists fit together.

    // Holds the complete set of touches on the screen.
    TouchList* touches = TouchList::create();

    // A different view on the 'touches' list above, filtered and grouped by
    // event target. Used for the |targetTouches| list in the JS event.
    using TargetTouchesHeapMap = HeapHashMap<EventTarget*, Member<TouchList>>;
    TargetTouchesHeapMap touchesByTarget;

    // Array of touches per state, used to assemble the |changedTouches| list.
    ChangedTouches changedTouches[PlatformTouchPoint::TouchStateEnd];

    for (unsigned i = 0; i < touchInfos.size(); ++i) {
        const TouchInfo& touchInfo = touchInfos[i];
        const PlatformTouchPoint& point = touchInfo.point;
        PlatformTouchPoint::TouchState pointState = point.state();

        if (touchInfo.consumed)
            continue;

        Touch* touch = Touch::create(
            touchInfo.targetFrame.get(),
            touchInfo.touchNode.get(),
            point.id(),
            point.screenPos(),
            touchInfo.contentPoint,
            touchInfo.adjustedRadius,
            point.rotationAngle(),
            point.force(),
            touchInfo.region);

        // Ensure this target's touch list exists, even if it ends up empty, so
        // it can always be passed to TouchEvent::Create below.
        TargetTouchesHeapMap::iterator targetTouchesIterator = touchesByTarget.find(touchInfo.touchNode.get());
        if (targetTouchesIterator == touchesByTarget.end()) {
            touchesByTarget.set(touchInfo.touchNode.get(), TouchList::create());
            targetTouchesIterator = touchesByTarget.find(touchInfo.touchNode.get());
        }

        // |touches| and |targetTouches| should only contain information about
        // touches still on the screen, so if this point is released or
        // cancelled it will only appear in the |changedTouches| list.
        if (pointState != PlatformTouchPoint::TouchReleased && pointState != PlatformTouchPoint::TouchCancelled) {
            touches->append(touch);
            targetTouchesIterator->value->append(touch);
        }

        // Now build up the correct list for |changedTouches|.
        // Note that  any touches that are in the TouchStationary state (e.g. if
        // the user had several points touched but did not move them all) should
        // never be in the |changedTouches| list so we do not handle them
        // explicitly here. See https://bugs.webkit.org/show_bug.cgi?id=37609
        // for further discussion about the TouchStationary state.
        if (pointState != PlatformTouchPoint::TouchStationary && touchInfo.knownTarget) {
            ASSERT(pointState < PlatformTouchPoint::TouchStateEnd);
            if (!changedTouches[pointState].m_touches)
                changedTouches[pointState].m_touches = TouchList::create();
            changedTouches[pointState].m_touches->append(touch);
            changedTouches[pointState].m_targets.add(touchInfo.touchNode);
        }
    }

    if (allTouchesReleased) {
        m_touchSequenceDocument.clear();
        m_touchSequenceUserGestureToken.clear();
    }

    WebInputEventResult eventResult = WebInputEventResult::NotHandled;

    // Now iterate through the |changedTouches| list and |m_targets| within it,
    // sending TouchEvents to the targets as required.
    for (unsigned state = 0; state != PlatformTouchPoint::TouchStateEnd; ++state) {
        if (!changedTouches[state].m_touches)
            continue;

        const AtomicString& eventName(touchEventNameForTouchPointState(static_cast<PlatformTouchPoint::TouchState>(state)));
        for (const auto& eventTarget : changedTouches[state].m_targets) {
            EventTarget* touchEventTarget = eventTarget;
            TouchEvent* touchEvent = TouchEvent::create(
                touches, touchesByTarget.get(touchEventTarget), changedTouches[state].m_touches.get(),
                eventName, touchEventTarget->toNode()->document().domWindow(),
                event.getModifiers(), event.cancelable(), event.causesScrollingIfUncanceled(), event.timestamp());

            DispatchEventResult domDispatchResult = touchEventTarget->dispatchEvent(touchEvent);

            // Only report for top level documents with a single touch on
            // touch-start or the first touch-move.
            if (touchStartOrFirstTouchMove && touchInfos.size() == 1 && event.cancelable() && m_frame->isMainFrame()) {
                DEFINE_STATIC_LOCAL(EnumerationHistogram, rootDocumentListenerHistogram, ("Event.Touch.TargetAndDispatchResult", TouchTargetAndDispatchResultTypeMax));
                rootDocumentListenerHistogram.count(toTouchTargetHistogramValue(eventTarget, domDispatchResult));

                // Count the handled touch starts and first touch moves before and after the page is fully loaded respectively.
                if (m_frame->document()->isLoadCompleted()) {
                    DEFINE_STATIC_LOCAL(EnumerationHistogram, touchDispositionsAfterPageLoadHistogram, ("Event.Touch.TouchDispositionsAfterPageLoad", TouchEventDispatchResultTypeMax));
                    touchDispositionsAfterPageLoadHistogram.count((domDispatchResult != DispatchEventResult::NotCanceled) ? HandledTouches : UnhandledTouches);
                } else {
                    DEFINE_STATIC_LOCAL(EnumerationHistogram, touchDispositionsBeforePageLoadHistogram, ("Event.Touch.TouchDispositionsBeforePageLoad", TouchEventDispatchResultTypeMax));
                    touchDispositionsBeforePageLoadHistogram.count((domDispatchResult != DispatchEventResult::NotCanceled) ? HandledTouches : UnhandledTouches);
                }
            }
            eventResult = EventHandler::mergeEventResult(eventResult,
                EventHandler::toWebInputEventResult(domDispatchResult));
        }
    }
    return eventResult;
}