From c33f0eab0956b9b1a3742e3752fb443d1b36fa2f Mon Sep 17 00:00:00 2001 From: Simo Kinnunen Date: Thu, 3 Apr 2014 17:13:17 +0900 Subject: [PATCH] Make sure touch events arrive in correct order. --- lib/roles/app.js | 3 +- lib/roles/device/plugins/touch.js | 36 ++++++++++++------- lib/wire/seqqueue.js | 26 ++++++++++++++ lib/wire/wire.proto | 15 ++++---- .../components/stf/control/control-service.js | 5 +-- .../components/stf/screen/screen-directive.js | 5 ++- 6 files changed, 68 insertions(+), 22 deletions(-) create mode 100644 lib/wire/seqqueue.js diff --git a/lib/roles/app.js b/lib/roles/app.js index 0db1c246..d3695691 100644 --- a/lib/roles/app.js +++ b/lib/roles/app.js @@ -248,7 +248,8 @@ module.exports = function(options) { push.send([ channel , wireutil.envelope(new Klass( - data.x + data.seq + , data.x , data.y )) ]) diff --git a/lib/roles/device/plugins/touch.js b/lib/roles/device/plugins/touch.js index 16d4447c..5ceffe48 100644 --- a/lib/roles/device/plugins/touch.js +++ b/lib/roles/device/plugins/touch.js @@ -7,6 +7,7 @@ var devutil = require('../../../util/devutil') var logger = require('../../../util/logger') var lifecycle = require('../../../util/lifecycle') var streamutil = require('../../../util/streamutil') +var SeqQueue = require('../../../wire/seqqueue') module.exports = syrup.serial() .dependency(require('../support/adb')) @@ -49,24 +50,35 @@ module.exports = syrup.serial() return openService() .then(function(monkey) { + var queue = new SeqQueue() + router .on(wire.TouchDownMessage, function(channel, message) { - monkey.touchDownAsync(message.x, message.y) - .catch(function(err) { - log.error('touchDown failed', err.stack) - }) + queue.push(message.seq, function() { + monkey.touchDownAsync(message.x, message.y) + .catch(function(err) { + log.error('touchDown failed', err.stack) + }) + }) }) .on(wire.TouchMoveMessage, function(channel, message) { - monkey.touchMoveAsync(message.x, message.y) - .catch(function(err) { - log.error('touchMove failed', err.stack) - }) + queue.push(message.seq, function() { + monkey.touchMoveAsync(message.x, message.y) + .catch(function(err) { + log.error('touchMove failed', err.stack) + }) + }) }) .on(wire.TouchUpMessage, function(channel, message) { - monkey.touchUpAsync(message.x, message.y) - .catch(function(err) { - log.error('touchUp failed', err.stack) - }) + queue.push(message.seq, function() { + monkey.touchUpAsync(message.x, message.y) + .catch(function(err) { + log.error('touchUp failed', err.stack) + }) + }) + + // Reset queue + queue = new SeqQueue() }) .on(wire.TapMessage, function(channel, message) { monkey.tapAsync(message.x, message.y) diff --git a/lib/wire/seqqueue.js b/lib/wire/seqqueue.js new file mode 100644 index 00000000..4e5fc499 --- /dev/null +++ b/lib/wire/seqqueue.js @@ -0,0 +1,26 @@ +function SeqQueue() { + this.queue = [] + this.seq = 0 +} + +SeqQueue.prototype.push = function(seq, handler) { + this.queue[seq] = handler + this.maybeDequeue() +} + +SeqQueue.prototype.done = function(seq, handler) { + this.queue[seq] = handler + this.maybeDequeue() +} + +SeqQueue.prototype.maybeDequeue = function() { + var handler + + while ((handler = this.queue[this.seq])) { + this.queue[this.seq] = void 0 + handler() + this.seq += 1 + } +} + +module.exports = SeqQueue diff --git a/lib/wire/wire.proto b/lib/wire/wire.proto index fa1952e2..65d74466 100644 --- a/lib/wire/wire.proto +++ b/lib/wire/wire.proto @@ -214,18 +214,21 @@ message PhysicalIdentifyMessage { } message TouchDownMessage { - required uint32 x = 1; - required uint32 y = 2; + required uint32 seq = 1; + required uint32 x = 2; + required uint32 y = 3; } message TouchMoveMessage { - required uint32 x = 1; - required uint32 y = 2; + required uint32 seq = 1; + required uint32 x = 2; + required uint32 y = 3; } message TouchUpMessage { - required uint32 x = 1; - required uint32 y = 2; + required uint32 seq = 1; + required uint32 x = 2; + required uint32 y = 3; } message TapMessage { diff --git a/res/app/components/stf/control/control-service.js b/res/app/components/stf/control/control-service.js index bb357ca8..1bf1ac43 100644 --- a/res/app/components/stf/control/control-service.js +++ b/res/app/components/stf/control/control-service.js @@ -40,9 +40,10 @@ module.exports = function ControlServiceFactory( } function touchSender(type) { - return function(x, y) { + return function(seq, x, y) { socket.emit(type, channel, { - x: x + seq: seq + , x: x , y: y }) } diff --git a/res/app/components/stf/screen/screen-directive.js b/res/app/components/stf/screen/screen-directive.js index 02a8692c..d5fa5bea 100644 --- a/res/app/components/stf/screen/screen-directive.js +++ b/res/app/components/stf/screen/screen-directive.js @@ -15,6 +15,7 @@ module.exports = function DeviceScreenDirective($document, ScalingService) { , cachedDisplayHeight = 0 , loading = false , scaler + , seq = 0 function sendTouch(type, e) { var scaled = scaler.coords( @@ -28,7 +29,8 @@ module.exports = function DeviceScreenDirective($document, ScalingService) { 'translate3d(' + e.offsetX + 'px,' + e.offsetY + 'px,0)' scope.control[type]( - scaled.xP * scope.device.display.width + seq++ + , scaled.xP * scope.device.display.width , scaled.yP * scope.device.display.height ) } @@ -38,6 +40,7 @@ module.exports = function DeviceScreenDirective($document, ScalingService) { element.unbind('mousemove', moveListener) $document.unbind('mouseup', upListener) $document.unbind('mouseleave', upListener) + seq = 0 } function updateDisplaySize() {