Bug 1133492 - Extract some of nsPresShell into a separate TouchManager class. r=smaug
This commit is contained in:
@@ -975,6 +975,8 @@ PresShell::Init(nsIDocument* aDocument,
|
||||
|
||||
// Setup our font inflation preferences.
|
||||
SetupFontInflation();
|
||||
|
||||
mTouchManager.Init(this, mDocument);
|
||||
}
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
@@ -1277,7 +1279,7 @@ PresShell::Destroy()
|
||||
|
||||
mHaveShutDown = true;
|
||||
|
||||
EvictTouches();
|
||||
mTouchManager.Destroy();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -6804,60 +6806,6 @@ PresShell::RecordMouseLocation(WidgetGUIEvent* aEvent)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
EvictTouchPoint(nsRefPtr<dom::Touch>& aTouch,
|
||||
nsIDocument* aLimitToDocument = nullptr)
|
||||
{
|
||||
nsCOMPtr<nsINode> node(do_QueryInterface(aTouch->mTarget));
|
||||
if (node) {
|
||||
nsIDocument* doc = node->GetCurrentDoc();
|
||||
if (doc && (!aLimitToDocument || aLimitToDocument == doc)) {
|
||||
nsIPresShell* presShell = doc->GetShell();
|
||||
if (presShell) {
|
||||
nsIFrame* frame = presShell->GetRootFrame();
|
||||
if (frame) {
|
||||
nsPoint pt(aTouch->mRefPoint.x, aTouch->mRefPoint.y);
|
||||
nsCOMPtr<nsIWidget> widget = frame->GetView()->GetNearestWidget(&pt);
|
||||
if (widget) {
|
||||
WidgetTouchEvent event(true, NS_TOUCH_END, widget);
|
||||
event.widget = widget;
|
||||
event.time = PR_IntervalNow();
|
||||
event.touches.AppendElement(aTouch);
|
||||
nsEventStatus status;
|
||||
widget->DispatchEvent(&event, status);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!node || !aLimitToDocument || node->OwnerDoc() == aLimitToDocument) {
|
||||
// We couldn't dispatch touchend. Remove the touch from gCaptureTouchList
|
||||
// explicitly.
|
||||
nsIPresShell::gCaptureTouchList->Remove(aTouch->Identifier());
|
||||
}
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
AppendToTouchList(const uint32_t& aKey, nsRefPtr<dom::Touch>& aData, void *aTouchList)
|
||||
{
|
||||
WidgetTouchEvent::TouchArray* touches =
|
||||
static_cast<WidgetTouchEvent::TouchArray*>(aTouchList);
|
||||
aData->mChanged = false;
|
||||
touches->AppendElement(aData);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
PresShell::EvictTouches()
|
||||
{
|
||||
WidgetTouchEvent::AutoTouchArray touches;
|
||||
gCaptureTouchList->Enumerate(&AppendToTouchList, &touches);
|
||||
for (uint32_t i = 0; i < touches.Length(); ++i) {
|
||||
EvictTouchPoint(touches[i], mDocument);
|
||||
}
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
FindAnyTarget(const uint32_t& aKey, nsRefPtr<dom::Touch>& aData,
|
||||
void* aAnyTarget)
|
||||
@@ -8068,125 +8016,7 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent, nsEventStatus* aStatus)
|
||||
case NS_MOUSE_BUTTON_UP:
|
||||
isHandlingUserInput = true;
|
||||
break;
|
||||
case NS_TOUCH_START: {
|
||||
isHandlingUserInput = true;
|
||||
WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
|
||||
// if there is only one touch in this touchstart event, assume that it is
|
||||
// the start of a new touch session and evict any old touches in the
|
||||
// queue
|
||||
if (touchEvent->touches.Length() == 1) {
|
||||
WidgetTouchEvent::AutoTouchArray touches;
|
||||
gCaptureTouchList->Enumerate(&AppendToTouchList, (void *)&touches);
|
||||
for (uint32_t i = 0; i < touches.Length(); ++i) {
|
||||
EvictTouchPoint(touches[i]);
|
||||
}
|
||||
}
|
||||
// Add any new touches to the queue
|
||||
for (uint32_t i = 0; i < touchEvent->touches.Length(); ++i) {
|
||||
dom::Touch* touch = touchEvent->touches[i];
|
||||
int32_t id = touch->Identifier();
|
||||
if (!gCaptureTouchList->Get(id, nullptr)) {
|
||||
// If it is not already in the queue, it is a new touch
|
||||
touch->mChanged = true;
|
||||
}
|
||||
touch->mMessage = aEvent->message;
|
||||
gCaptureTouchList->Put(id, touch);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NS_TOUCH_END:
|
||||
isHandlingUserInput = true;
|
||||
// Fall through to touchcancel code
|
||||
case NS_TOUCH_CANCEL: {
|
||||
// Remove the changed touches
|
||||
// need to make sure we only remove touches that are ending here
|
||||
WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
|
||||
WidgetTouchEvent::TouchArray& touches = touchEvent->touches;
|
||||
for (uint32_t i = 0; i < touches.Length(); ++i) {
|
||||
dom::Touch* touch = touches[i];
|
||||
if (!touch) {
|
||||
continue;
|
||||
}
|
||||
touch->mMessage = aEvent->message;
|
||||
touch->mChanged = true;
|
||||
|
||||
int32_t id = touch->Identifier();
|
||||
nsRefPtr<dom::Touch> oldTouch = gCaptureTouchList->GetWeak(id);
|
||||
if (!oldTouch) {
|
||||
continue;
|
||||
}
|
||||
nsCOMPtr<EventTarget> targetPtr = oldTouch->mTarget;
|
||||
|
||||
mCurrentEventContent = do_QueryInterface(targetPtr);
|
||||
touch->SetTarget(targetPtr);
|
||||
gCaptureTouchList->Remove(id);
|
||||
}
|
||||
// add any touches left in the touch list, but ensure changed=false
|
||||
gCaptureTouchList->Enumerate(&AppendToTouchList, (void *)&touches);
|
||||
break;
|
||||
}
|
||||
case NS_TOUCH_MOVE: {
|
||||
// Check for touches that changed. Mark them add to queue
|
||||
WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
|
||||
WidgetTouchEvent::TouchArray& touches = touchEvent->touches;
|
||||
bool haveChanged = false;
|
||||
for (int32_t i = touches.Length(); i; ) {
|
||||
--i;
|
||||
dom::Touch* touch = touches[i];
|
||||
if (!touch) {
|
||||
continue;
|
||||
}
|
||||
int32_t id = touch->Identifier();
|
||||
touch->mMessage = aEvent->message;
|
||||
|
||||
nsRefPtr<dom::Touch> oldTouch = gCaptureTouchList->GetWeak(id);
|
||||
if (!oldTouch) {
|
||||
touches.RemoveElementAt(i);
|
||||
continue;
|
||||
}
|
||||
if (!touch->Equals(oldTouch)) {
|
||||
touch->mChanged = true;
|
||||
haveChanged = true;
|
||||
}
|
||||
|
||||
nsCOMPtr<dom::EventTarget> targetPtr = oldTouch->mTarget;
|
||||
if (!targetPtr) {
|
||||
touches.RemoveElementAt(i);
|
||||
continue;
|
||||
}
|
||||
touch->SetTarget(targetPtr);
|
||||
|
||||
gCaptureTouchList->Put(id, touch);
|
||||
// if we're moving from touchstart to touchmove for this touch
|
||||
// we allow preventDefault to prevent mouse events
|
||||
if (oldTouch->mMessage != touch->mMessage) {
|
||||
touchIsNew = true;
|
||||
}
|
||||
}
|
||||
// is nothing has changed, we should just return
|
||||
if (!haveChanged) {
|
||||
if (touchIsNew) {
|
||||
// however, if this is the first touchmove after a touchstart,
|
||||
// it is special in that preventDefault is allowed on it, so
|
||||
// we must dispatch it to content even if nothing changed. we
|
||||
// arbitrarily pick the first touch point to be the "changed"
|
||||
// touch because firing an event with no changed events doesn't
|
||||
// work.
|
||||
for (uint32_t i = 0; i < touchEvent->touches.Length(); ++i) {
|
||||
if (touchEvent->touches[i]) {
|
||||
touchEvent->touches[i]->mChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (gPreventMouseEvents) {
|
||||
*aStatus = nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NS_DRAGDROP_DROP:
|
||||
nsCOMPtr<nsIDragSession> session = nsContentUtils::GetDragSession();
|
||||
if (session) {
|
||||
@@ -8198,6 +8028,12 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent, nsEventStatus* aStatus)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!mTouchManager.PreHandleEvent(aEvent, aStatus,
|
||||
touchIsNew, isHandlingUserInput,
|
||||
mCurrentEventContent)) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (aEvent->message == NS_CONTEXTMENU) {
|
||||
|
||||
Reference in New Issue
Block a user