Fix multi-touch to work in SkyShell. Before this patch it crashed. Also updated the touch-demo to support multi-touch. R=abarth@chromium.org BUG= Review URL: https://codereview.chromium.org/961483004
diff --git a/sky/engine/core/dom/ParentNode.idl b/sky/engine/core/dom/ParentNode.idl index 1e031c4..a1f0c75 100644 --- a/sky/engine/core/dom/ParentNode.idl +++ b/sky/engine/core/dom/ParentNode.idl
@@ -14,9 +14,9 @@ sequence<Element> getChildElements(); [CustomElementCallbacks, RaisesException] void append(sequence<Node> nodes); - [CustomElementCallbacks, RaisesException] Node appendChild(Node nodes); + [CustomElementCallbacks, RaisesException] Node appendChild(Node node); [CustomElementCallbacks, RaisesException] void prepend(sequence<Node> nodes); - [CustomElementCallbacks, RaisesException] Node prependChild(Node nodes); + [CustomElementCallbacks, RaisesException] Node prependChild(Node node); [CustomElementCallbacks] void removeChildren(); [CustomElementCallbacks, RaisesException] Node setChild(Node node);
diff --git a/sky/engine/core/frame/NewEventHandler.cpp b/sky/engine/core/frame/NewEventHandler.cpp index 9154289..a7e6c26 100644 --- a/sky/engine/core/frame/NewEventHandler.cpp +++ b/sky/engine/core/frame/NewEventHandler.cpp
@@ -121,7 +121,7 @@ void NewEventHandler::updateSelectionForPointerDown(const HitTestResult& hitTestResult, const WebPointerEvent& event) { Node* innerNode = hitTestResult.innerNode(); - if (!innerNode->renderer()) + if (!innerNode || !innerNode->renderer()) return; if (Position::nodeIsUserSelectNone(innerNode)) return; @@ -191,14 +191,14 @@ // pointer ID, but for mice, we don't get a pointer cancel when you // drag outside the window frame on Linux. For now, send the pointer // cancel at this point. - if (event.kind == WebPointerEvent::Mouse - && m_stateForPointer.find(event.pointer) != m_stateForPointer.end()) { + bool alreadyDown = m_stateForPointer.find(event.pointer) != m_stateForPointer.end(); + if (event.kind == WebPointerEvent::Mouse && alreadyDown) { WebPointerEvent fakeCancel = event; fakeCancel.type = WebInputEvent::PointerCancel; handlePointerCancelEvent(fakeCancel); } - ASSERT(m_stateForPointer.find(event.pointer) == m_stateForPointer.end()); + DCHECK(!alreadyDown) << "Pointer id " << event.pointer << "already down!"; HitTestResult hitTestResult = performHitTest(positionForEvent(event)); RefPtr<Node> target = targetForHitTestResult(hitTestResult); if (!target)
diff --git a/sky/examples/touch-demo.sky b/sky/examples/touch-demo.sky index e9482ab..57a8e41 100644 --- a/sky/examples/touch-demo.sky +++ b/sky/examples/touch-demo.sky
@@ -6,27 +6,54 @@ height: 100px; width: 100px; background-color: #00FF00; + border-radius: 50px; } </style> -<dot /> <log>Ready</log> <script> import "dart:sky"; -final Element dot = document.querySelector("dot"); +// Material design colors. :p +List<String> colors = [ + "#009688", + "#FFC107", + "#9C27B0", + "#03A9F4", + "#673AB7", + "#CDDC39", +]; -void moveDot(event) { - double x = event.x; - double y = event.y; +Element whichDot(event) { + return document.querySelector('dot[id="${event.pointer}"]'); +} - dot.style["transform"] = "translate(${x-50}px,${y-50}px)"; +void moreDots(event) { + Element dot = document.createElement('dot'); + dot.setAttribute('id', "${event.pointer}"); + dot.style['background-color'] = colors[event.pointer.remainder(colors.length)]; + document.querySelector('sky').appendChild(dot); + runToTheCenter(event); +} + +void goAway(event) { + whichDot(event).remove(); +} + +void stopDots(event) { + for (Element e in document.querySelectorAll('dot')) + e.remove(); +} + +void runToTheCenter(event) { + whichDot(event).style["transform"] = + "translate(${event.x-50}px,${event.y-50}px)"; } void main() { - document.addEventListener("pointerdown", moveDot); - document.addEventListener("pointermove", moveDot); - document.addEventListener("pointerup", moveDot); - document.addEventListener("pointercancel", moveDot); + document.addEventListener("pointerdown", moreDots); + document.addEventListener("pointermove", runToTheCenter); + document.addEventListener("pointerup", goAway); + document.addEventListener("pointercancel", stopDots); } </script> </sky>
diff --git a/sky/shell/org/domokit/sky/shell/PlatformView.java b/sky/shell/org/domokit/sky/shell/PlatformView.java index 2f646c9..e24cbdf 100644 --- a/sky/shell/org/domokit/sky/shell/PlatformView.java +++ b/sky/shell/org/domokit/sky/shell/PlatformView.java
@@ -81,10 +81,17 @@ } private int getTypeForAction(int maskedAction) { + // Primary pointer: if (maskedAction == MotionEvent.ACTION_DOWN) return EventType.POINTER_DOWN; if (maskedAction == MotionEvent.ACTION_UP) return EventType.POINTER_UP; + // Secondary pointer: + if (maskedAction == MotionEvent.ACTION_POINTER_DOWN) + return EventType.POINTER_DOWN; + if (maskedAction == MotionEvent.ACTION_POINTER_UP) + return EventType.POINTER_UP; + // All pointers: if (maskedAction == MotionEvent.ACTION_MOVE) return EventType.POINTER_MOVE; if (maskedAction == MotionEvent.ACTION_CANCEL) @@ -92,13 +99,12 @@ return EventType.UNKNOWN; } - @Override - public boolean onTouchEvent(MotionEvent event) { + private void sendInputEventForIndex(MotionEvent event, int pointerIndex) { PointerData pointerData = new PointerData(); - pointerData.pointer = event.getPointerId(0); + pointerData.pointer = event.getPointerId(pointerIndex); pointerData.kind = PointerKind.TOUCH; - pointerData.x = event.getX(); - pointerData.y = event.getY(); + pointerData.x = event.getX(pointerIndex); + pointerData.y = event.getY(pointerIndex); InputEvent inputEvent = new InputEvent(); inputEvent.type = getTypeForAction(event.getActionMasked()); @@ -106,6 +112,26 @@ inputEvent.pointerData = pointerData; mViewportObserver.onInputEvent(inputEvent); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + int maskedAction = event.getActionMasked(); + // ACTION_UP, ACTION_POINTER_UP, ACTION_DOWN, and ACTION_POINTER_DOWN + // only apply to a single pointer, other events apply to all pointers. + if (maskedAction == MotionEvent.ACTION_UP + || maskedAction == MotionEvent.ACTION_POINTER_UP + || maskedAction == MotionEvent.ACTION_DOWN + || maskedAction == MotionEvent.ACTION_POINTER_DOWN) { + sendInputEventForIndex(event, event.getActionIndex()); + } else { + // ACTION_MOVE may not actually mean all pointers have moved + // but it's the responsibility of a later part of the system to + // ignore 0-deltas if desired. + for (int p = 0; p < event.getPointerCount(); p++) { + sendInputEventForIndex(event, p); + } + } return true; }