1
0
Fork 0
mirror of https://github.com/openstf/stf synced 2025-10-06 03:50:04 +02:00

Implement device screen.

This commit is contained in:
Simo Kinnunen 2014-02-06 22:45:19 +09:00
parent a2dd5ad0c7
commit d17e86bc57
9 changed files with 317 additions and 1 deletions

View file

@ -79,6 +79,7 @@ module.exports = function(options) {
var whitelist = {
'devices/index': true
, 'devices/control': true
, 'devices/screen': true
}
if (whitelist.hasOwnProperty(req.params[0])) {

View file

@ -355,27 +355,51 @@ module.exports = function(options) {
})
.on(wire.TouchDownMessage, function(channel, message) {
services.input.touchDownAsync(message.x, message.y)
.catch(function(err) {
log.error('touchDown failed', err.stack)
})
})
.on(wire.TouchMoveMessage, function(channel, message) {
services.input.touchMoveAsync(message.x, message.y)
.catch(function(err) {
log.error('touchMove failed', err.stack)
})
})
.on(wire.TouchUpMessage, function(channel, message) {
services.input.touchUpAsync(message.x, message.y)
.catch(function(err) {
log.error('touchUp failed', err.stack)
})
})
.on(wire.TapMessage, function(channel, message) {
services.input.tapAsync(message.x, message.y)
.catch(function(err) {
log.error('tap failed', err.stack)
})
})
.on(wire.TypeMessage, function(channel, message) {
services.monkey.typeAsync(message.text)
.catch(function(err) {
log.error('type failed', err.stack)
})
})
.on(wire.KeyDownMessage, function(channel, message) {
services.monkey.keyDownAsync(message.key)
.catch(function(err) {
log.error('keyDown failed', err.stack)
})
})
.on(wire.KeyUpMessage, function(channel, message) {
services.monkey.keyUpAsync(message.key)
.catch(function(err) {
log.error('keyUp failed', err.stack)
})
})
.on(wire.KeyPressMessage, function(channel, message) {
services.monkey.pressAsync(message.key)
.catch(function(err) {
log.error('keyPress failed', err.stack)
})
})
.on(wire.ShellCommandMessage, function(channel, message) {
log.info('Running shell command "%s"', message.command.join(' '))

View file

@ -3,10 +3,11 @@ define(['./_module'], function(app) {
$scope.device = null
$scope.control = null
deviceService.get($routeParams.serial)
$scope.promiseOfDevice = deviceService.get($routeParams.serial)
.then(function(device) {
$scope.device = device
$scope.control = controlService.forChannel(device.channel)
return device
})
}

View file

@ -0,0 +1,140 @@
define(['./_module'], function(app) {
function DeviceScreenCtrl($scope, scalingService) {
$scope.ready = false
$scope.displayError = false
$scope.scalingService = scalingService
$scope.promiseOfDevice.then(function() {
$scope.ready = true
})
}
function DeviceScreenDirective($document, scalingService) {
return {
restrict: 'E'
, templateUrl: 'partials/devices/screen'
, link: function($scope, element, attrs) {
$scope.promiseOfDevice.then(function(device) {
var loader = new Image()
, canvas = element.find('canvas')[0]
, g = canvas.getContext('2d')
, displayWidth = 0
, displayHeight = 0
, scaler = scalingService.coordinator(
device.display.width
, device.display.height
)
function updateDisplaySize() {
displayWidth = element[0].offsetWidth
displayHeight = element[0].offsetHeight
// Developer error, let's try to reduce debug time
if (!displayWidth || !displayHeight) {
throw new Error(
'Unable to update display size; container must have dimensions'
)
}
}
function loadScreen() {
loader.src = device.display.url +
'?width=' + displayWidth +
'&height=' + displayHeight +
'&time=' + Date.now()
}
loader.onload = function() {
var size = scaler.projectedSize(displayWidth, displayHeight)
// Make sure we're rendering pixels 1 to 1
canvas.width = this.width
canvas.height = this.height
// Perhaps we have a massive screen but not enough pixels. Let's
// scale up
canvas.style.width = size.width + 'px'
canvas.style.height = size.height + 'px'
// Draw the image
g.drawImage(this, 0, 0)
// Reset error, if any
if ($scope.displayError) {
$scope.$apply(function() {
$scope.displayError = false
})
}
// Next please
loadScreen()
}
loader.onerror = function() {
$scope.$apply(function() {
$scope.displayError = true
})
}
function sendTouch(type, e) {
var scaled = scaler.coords(
displayWidth
, displayHeight
, e.offsetX
, e.offsetY
)
$scope.control[type](
scaled.xP * device.display.width
, scaled.yP * device.display.height
)
}
function downListener(e) {
e.preventDefault()
sendTouch('touchDown', e)
element.bind('mousemove', moveListener)
$document.bind('mouseup', upListener)
$document.bind('mouseleave', upListener)
}
function moveListener(e) {
sendTouch('touchMove', e)
}
function upListener(e) {
sendTouch('touchUp', e)
stop()
}
function stop() {
element.unbind('mousemove', moveListener)
$document.unbind('mouseup', upListener)
$document.unbind('mouseleave', upListener)
}
$scope.$on('$destroy', function() {
loader.onload = loader.onerror = null
$document.unbind('mouseup', upListener)
$document.unbind('mouseleave', upListener)
})
element.bind('mousedown', downListener)
updateDisplaySize()
loadScreen()
})
}
}
}
app.controller('DeviceScreenCtrl'
, [ '$scope'
, 'ScalingService'
, DeviceScreenCtrl
])
.directive('deviceScreen'
, [ '$document'
, 'ScalingService'
, DeviceScreenDirective
])
})

View file

@ -1,6 +1,7 @@
define([
'./DeviceListCtrl'
, './DeviceControlCtrl'
, './DeviceScreenCtrl'
]
, function() {
}

View file

@ -0,0 +1,128 @@
define(['./_module'], function(app) {
function ScalingServiceFactory() {
var scalingService = {
}
scalingService.coordinator = function(realWidth, realHeight) {
var realRatio = realWidth / realHeight
return {
coords: function(width, height, x, y) {
var ratio = width / height
, scaledValue
if (realRatio > ratio) {
// covers the area horizontally
scaledValue = width / realRatio;
// adjust y to start from the scaled top edge
y -= (height - scaledValue) / 2
// not touching the screen, but we want to trigger certain events
// (like touchup) anyway, so let's do it on the edges.
if (y < 0) {
y = 0
}
else if (y > scaledValue) {
y = scaledValue
}
// make sure x is within bounds too
if (x < 0) {
x = 0
}
else if (x > width) {
x = width
}
height = scaledValue
}
else {
// covers the area vertically
scaledValue = height * realRatio
// adjust x to start from the scaled left edge
x -= (width - scaledValue) / 2
// not touching the screen, but we want to trigger certain events
// (like touchup) anyway, so let's do it on the edges.
if (x < 0) {
x = 0
}
else if (x > scaledValue) {
x = scaledValue
}
// make sure y is within bounds too
if (y < 0) {
y = 0
}
else if (y > height) {
y = height
}
width = scaledValue
}
return {
xP: x / width
, yP: y / height
}
}
, size: function(width, height) {
var ratio = width / height
if (realRatio > ratio) {
// covers the area horizontally
if (width >= realWidth) {
// don't go over max size
width = realWidth
height = realHeight
}
else {
height = Math.floor(width / realRatio)
}
}
else {
// covers the area vertically
if (height >= realHeight) {
// don't go over max size
height = realHeight
width = realWidth
}
else {
width = Math.floor(height * realRatio)
}
}
return {
width: width
, height: height
}
}
, projectedSize: function(width, height) {
var ratio = width / height
if (realRatio > ratio) {
// covers the area horizontally
height = Math.floor(width / realRatio)
}
else {
width = Math.floor(height * realRatio)
}
return {
width: width
, height: height
}
}
}
}
return scalingService
}
app.factory('ScalingService', [ScalingServiceFactory])
})

View file

@ -4,6 +4,7 @@ define([
, './GroupService'
, './UserService'
, './ControlService'
, './ScalingService'
]
, function() {
}

View file

@ -1,5 +1,23 @@
h1 {{ device.serial }}
style.
device-screen {
position: relative;
display: block;
}
device-screen canvas {
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
pointer-events: none; /* MUST HAVE */
}
div(ng-controller='DeviceScreenCtrl')
device-screen(style='width: 400px; height: 600px; background: gray')
button(ng-click='control.menu()') Menu
button(ng-click='control.home()') Home
button(ng-click='control.back()') Back

View file

@ -0,0 +1,2 @@
canvas(ng-show='ready')
div(ng-if='displayError') Screen error