diff --git a/index.d.ts b/index.d.ts index 037f5e08..9e2b23fd 100644 --- a/index.d.ts +++ b/index.d.ts @@ -15,6 +15,7 @@ export interface Screen { export function setKeyboardDelay(ms: number) : void export function keyTap(key: string, modifier?: string | string[]) : void export function keyToggle(key: string, down: string, modifier?: string | string[]) : void +export function unicodeTap(value: number) : void export function typeString(string: string) : void export function typeStringDelayed(string: string, cpm: number) : void export function setMouseDelay(delay: number) : void diff --git a/package-lock.json b/package-lock.json index 688d4d89..8ad9b618 100644 --- a/package-lock.json +++ b/package-lock.json @@ -151,7 +151,6 @@ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", "dev": true, - "optional": true, "requires": { "tweetnacl": "^0.14.3" } @@ -593,12 +592,57 @@ "mimic-response": "^2.0.0" } }, + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, "deep-extend": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", "dev": true }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -615,6 +659,15 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" }, + "dotignore": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dotignore/-/dotignore-0.1.2.tgz", + "integrity": "sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", @@ -667,7 +720,6 @@ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", "dev": true, - "optional": true, "requires": { "jsbn": "~0.1.0" } @@ -717,6 +769,44 @@ "is-arrayish": "^0.2.1" } }, + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, "es5-ext": { "version": "0.10.53", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", @@ -793,9 +883,9 @@ } }, "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, "extract-zip": { @@ -847,6 +937,15 @@ "pinkie-promise": "^2.0.0" } }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -909,6 +1008,12 @@ "rimraf": "2" } }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", @@ -1027,6 +1132,21 @@ "har-schema": "^2.0.0" } }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -1160,6 +1280,12 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -1175,6 +1301,18 @@ "builtin-modules": "^1.0.0" } }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, "is-finite": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", @@ -1198,6 +1336,24 @@ "integrity": "sha1-TBEDO11dlNbqs3dd7cm+fQCDJfE=", "dev": true }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -1248,17 +1404,16 @@ } }, "jquery": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", - "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz", + "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==", "dev": true }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true + "dev": true }, "json-schema": { "version": "0.2.3", @@ -1589,12 +1744,6 @@ "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", "dev": true }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", @@ -1900,12 +2049,44 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true + }, + "object-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz", + "integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==", + "dev": true + }, "object-keys": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", "dev": true }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + } + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1978,6 +2159,12 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, "path-type": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", @@ -2230,6 +2417,16 @@ "strip-indent": "^1.0.1" } }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, "repeating": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", @@ -2269,6 +2466,24 @@ "uuid": "^3.1.0" } }, + "resolve": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.2.tgz", + "integrity": "sha512-EjlOBLBO1kxsUxsKjLt7TAECyKW6fOh1VRkykQkKGzcBbjjPIxBqGh0jf7GJ3k/f5mxMqW3htMD3WdTUVtW8HQ==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true, + "requires": { + "through": "~2.3.4" + } + }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", @@ -2301,6 +2516,12 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, "semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", @@ -2413,9 +2634,9 @@ "dev": true }, "sshpk": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", "dev": true, "requires": { "asn1": "~0.2.3", @@ -2425,6 +2646,7 @@ "ecc-jsbn": "~0.1.1", "getpass": "^0.1.1", "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" } }, @@ -2438,6 +2660,37 @@ "strip-ansi": "^3.0.0" } }, + "string.prototype.trim": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz", + "integrity": "sha512-MjGFEeqixw47dAMFMtgUro/I0+wNqZB5GKXGt1fFr24u3TzDXCPu7J9Buppzoe3r/LqkSDLDDJzE15RGWDGAVw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimleft": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -2445,9 +2698,9 @@ "dev": true }, "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", "dev": true }, "strip-ansi": { @@ -2491,6 +2744,51 @@ "es6-promise": "^4.0.5" } }, + "tape": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.13.0.tgz", + "integrity": "sha512-J/hvA+GJnuWJ0Sj8Z0dmu3JgMNU+MmusvkCT7+SN4/2TklW18FNCp/UuHIEhPZwHfy4sXfKYgC7kypKg4umbOw==", + "dev": true, + "requires": { + "deep-equal": "~1.1.1", + "defined": "~1.0.0", + "dotignore": "~0.1.2", + "for-each": "~0.3.3", + "function-bind": "~1.1.1", + "glob": "~7.1.6", + "has": "~1.0.3", + "inherits": "~2.0.4", + "is-regex": "~1.0.5", + "minimist": "~1.2.0", + "object-inspect": "~1.7.0", + "resolve": "~1.14.2", + "resumer": "~0.0.0", + "string.prototype.trim": "~1.2.1", + "through": "~2.3.8" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + } + } + }, "tar": { "version": "4.4.13", "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", @@ -2640,6 +2938,12 @@ "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=", "dev": true }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, "through2": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", @@ -2717,8 +3021,7 @@ "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true + "dev": true }, "type": { "version": "1.2.0", diff --git a/package.json b/package.json index c7da7658..7b6a3949 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,10 @@ "scripts": { "test": "run-script-os", "test:darwin:linux": "jasmine 'test/**/*.js'", + "test-keyboard": "node test/keyboard.js", "test:win32": "jasmine test/**/*.js", "install": "prebuild-install || node-gyp rebuild", + "install-debug": "prebuild-install || node-gyp rebuild --debug", "prebuild": "prebuild --all" }, "repository": { @@ -44,6 +46,7 @@ "prebuild-install": "^5.3.3" }, "devDependencies": { + "tape": "^4.8.0", "jasmine": "^2.99.0", "prebuild": "^9.1.1", "run-script-os": "^1.0.3", diff --git a/src/keypress.c b/src/keypress.c index 0192609d..af095aaf 100644 --- a/src/keypress.c +++ b/src/keypress.c @@ -221,12 +221,12 @@ void tapKey(char c, MMKeyFlags flags) } #if defined(IS_MACOSX) -void toggleUnicodeKey(unsigned long ch, const bool down) +void toggleUnicode(UniChar ch, const bool down) { /* This function relies on the convenient * CGEventKeyboardSetUnicodeString(), which allows us to not have to * convert characters to a keycode, but does not support adding modifier - * flags. It is therefore only used in typeString() and typeStringDelayed() + * flags. It is therefore only used in typeStringDelayed() * -- if you need modifier keys, use the above functions instead. */ CGEventRef keyEvent = CGEventCreateKeyboardEvent(NULL, 0, down); if (keyEvent == NULL) { @@ -249,28 +249,43 @@ void toggleUnicodeKey(unsigned long ch, const bool down) CGEventPost(kCGSessionEventTap, keyEvent); CFRelease(keyEvent); } - -void toggleUniKey(char c, const bool down) -{ - toggleUnicodeKey(c, down); -} -#else - #define toggleUniKey(c, down) toggleKey(c, down, MOD_NONE) #endif -static void tapUniKey(char c) +void unicodeTap(const unsigned value) { - toggleUniKey(c, true); - toggleUniKey(c, false); + #if defined(IS_MACOSX) + UniChar ch = (UniChar)value; // Convert to unsigned char + + toggleUnicode(ch, true); + toggleUnicode(ch, false); + #elif defined(IS_WINDOWS) + INPUT ip; + + // Set up a generic keyboard event. + ip.type = INPUT_KEYBOARD; + ip.ki.wVk = 0; // Virtual-key code + ip.ki.wScan = value; // Hardware scan code for key + ip.ki.time = 0; // System will provide its own time stamp. + ip.ki.dwExtraInfo = 0; // No extra info. Use the GetMessageExtraInfo function to obtain this information if needed. + ip.ki.dwFlags = KEYEVENTF_UNICODE; // KEYEVENTF_KEYUP for key release. + + SendInput(1, &ip, sizeof(INPUT)); + #endif } -void typeString(const char *str) +void typeStringDelayed(const char *str, const unsigned cpm) { + unsigned long n; unsigned short c; unsigned short c1; unsigned short c2; unsigned short c3; - unsigned long n; + + /* Characters per second */ + const double cps = (double)cpm / 60.0; + + /* Average milli-seconds per character */ + const double mspc = (cps == 0.0) ? 0.0 : 1000.0 / cps; while (*str != '\0') { c = *str++; @@ -297,27 +312,10 @@ void typeString(const char *str) n = ((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; } - #if defined(IS_MACOSX) - toggleUnicodeKey(n, true); - toggleUnicodeKey(n, false); - #else - toggleUniKey(n, true); - toggleUniKey(n, false); - #endif - - } -} - -void typeStringDelayed(const char *str, const unsigned cpm) -{ - /* Characters per second */ - const double cps = (double)cpm / 60.0; - - /* Average milli-seconds per character */ - const double mspc = (cps == 0.0) ? 0.0 : 1000.0 / cps; - - while (*str != '\0') { - tapUniKey(*str++); - microsleep(mspc); + unicodeTap(n); + + if (mspc > 0) { + microsleep(mspc); + } } -} +} \ No newline at end of file diff --git a/src/keypress.h b/src/keypress.h index ed7fff69..1e8a265a 100644 --- a/src/keypress.h +++ b/src/keypress.h @@ -66,15 +66,15 @@ void tapKeyCode(MMKeyCode code, MMKeyFlags flags); void toggleKey(char c, const bool down, MMKeyFlags flags); void tapKey(char c, MMKeyFlags flags); -/* Sends a UTF-8 string without modifiers. */ -void typeString(const char *str); +/* Sends a Unicode character without modifiers. */ +void unicodeTap(const unsigned value); /* Macro to convert WPM to CPM integers. * (the average English word length is 5.1 characters.) */ #define WPM_TO_CPM(WPM) (unsigned)(5.1 * WPM) -/* Sends a string with partially random delays between each letter. Note that - * deadbeef_srand() must be called before this function if you actually want +/* Sends a UTF-8 string without modifiers and with partially random delays between each letter. + * Note that deadbeef_srand() must be called before this function if you actually want * randomness. */ void typeStringDelayed(const char *str, const unsigned cpm); diff --git a/src/mouse.c b/src/mouse.c index e61e8b7c..f7bb11d6 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -325,24 +325,25 @@ void scrollMouse(int x, int y) #elif defined(IS_WINDOWS) + // Must send y first, otherwise we get stuck when scrolling on y axis mouseScrollInputs[0].type = INPUT_MOUSE; mouseScrollInputs[0].mi.dx = 0; mouseScrollInputs[0].mi.dy = 0; - mouseScrollInputs[0].mi.dwFlags = MOUSEEVENTF_HWHEEL; + mouseScrollInputs[0].mi.dwFlags = MOUSEEVENTF_WHEEL; mouseScrollInputs[0].mi.time = 0; mouseScrollInputs[0].mi.dwExtraInfo = 0; - // Flip x to match other platforms. - mouseScrollInputs[0].mi.mouseData = -x; + mouseScrollInputs[0].mi.mouseData = y; mouseScrollInputs[1].type = INPUT_MOUSE; mouseScrollInputs[1].mi.dx = 0; mouseScrollInputs[1].mi.dy = 0; - mouseScrollInputs[1].mi.dwFlags = MOUSEEVENTF_WHEEL; + mouseScrollInputs[1].mi.dwFlags = MOUSEEVENTF_HWHEEL; mouseScrollInputs[1].mi.time = 0; mouseScrollInputs[1].mi.dwExtraInfo = 0; - mouseScrollInputs[1].mi.mouseData = y; + // Flip x to match other platforms. + mouseScrollInputs[1].mi.mouseData = -x; - SendInput(2, mouseScrollInputs, sizeof(mouseScrollInputs)); + SendInput(2, mouseScrollInputs, sizeof(INPUT)); #endif } diff --git a/src/robotjs.cc b/src/robotjs.cc index 091a975c..f96d98fc 100644 --- a/src/robotjs.cc +++ b/src/robotjs.cc @@ -582,7 +582,7 @@ NAN_METHOD(keyToggle) } } - //Get the acutal key. + //Get the actual key. switch(CheckKeyCodes(k, &key)) { case -1: @@ -593,36 +593,57 @@ NAN_METHOD(keyToggle) break; default: toggleKeyCode(key, down, flags); - microsleep(keyboardDelay); + microsleep(keyboardDelay); } info.GetReturnValue().Set(Nan::New(1)); } +NAN_METHOD(unicodeTap) +{ + size_t value = info[0]->Int32Value(Nan::GetCurrentContext()).FromJust(); + + if (value != 0) { + unicodeTap(value); + + info.GetReturnValue().Set(Nan::New(1)); + } else { + return Nan::ThrowError("Invalid character typed."); + } +} + NAN_METHOD(typeString) { - char *str; - Nan::Utf8String string(info[0]); + if (info.Length() > 0) { + char *str; + Nan::Utf8String string(info[0]); - str = *string; + str = *string; - typeString(str); + typeStringDelayed(str, 0); - info.GetReturnValue().Set(Nan::New(1)); + info.GetReturnValue().Set(Nan::New(1)); + } else { + return Nan::ThrowError("Invalid number of arguments."); + } } NAN_METHOD(typeStringDelayed) { - char *str; - Nan::Utf8String string(info[0]); + if (info.Length() > 0) { + char *str; + Nan::Utf8String string(info[0]); - str = *string; + str = *string; size_t cpm = Nan::To(info[1]).FromJust(); - typeStringDelayed(str, cpm); + typeStringDelayed(str, cpm); - info.GetReturnValue().Set(Nan::New(1)); + info.GetReturnValue().Set(Nan::New(1)); + } else { + return Nan::ThrowError("Invalid number of arguments."); + } } NAN_METHOD(setKeyboardDelay) @@ -879,6 +900,9 @@ NAN_MODULE_INIT(InitAll) Nan::Set(target, Nan::New("keyToggle").ToLocalChecked(), Nan::GetFunction(Nan::New(keyToggle)).ToLocalChecked()); + Nan::Set(target, Nan::New("unicodeTap").ToLocalChecked(), + Nan::GetFunction(Nan::New(unicodeTap)).ToLocalChecked()); + Nan::Set(target, Nan::New("typeString").ToLocalChecked(), Nan::GetFunction(Nan::New(typeString)).ToLocalChecked()); diff --git a/test/keyboard.js b/test/keyboard.js index cc1140eb..85f7ca17 100644 --- a/test/keyboard.js +++ b/test/keyboard.js @@ -39,3 +39,75 @@ describe('Keyboard', () => { } }); }); + +test('Tap a Unicode character.', function(t) +{ + t.plan(7); + t.ok(robot.unicodeTap("r".charCodeAt(0)) === 1, 'successfully tapped "r".'); + t.ok(robot.unicodeTap("ά".charCodeAt(0)) === 1, 'successfully tapped "ά".'); + t.ok(robot.unicodeTap("ö".charCodeAt(0)) === 1, 'successfully tapped "ö".'); + t.ok(robot.unicodeTap("ち".charCodeAt(0)) === 1, 'successfully tapped "ち".'); + t.ok(robot.unicodeTap("嗨".charCodeAt(0)) === 1, 'successfully tapped "嗨".'); + t.ok(robot.unicodeTap("ఝ".charCodeAt(0)) === 1, 'successfully tapped "ఝ".'); + + t.throws(function() + { + robot.unicodeTap(); + }, /Invalid character typed./, 'tap nothing.'); +}); + +test('Test Key Toggle.', function(t) +{ + t.plan(4); + + t.ok(robot.keyToggle("a", "down") === 1, 'Successfully pressed a.'); + t.ok(robot.keyToggle("a", "up") === 1, 'Successfully released a.'); + + t.throws(function() + { + t.ok(robot.keyToggle("ά", "down") === 1, 'Successfully pressed ά.'); + t.ok(robot.keyToggle("ά", "up") === 1, 'Successfully released ά.'); + }, /Invalid key code specified./, 'exception tapping ά.'); + + t.throws(function() + { + t.ok(robot.keyToggle("嗨", "down") === 1, 'Successfully pressed 嗨.'); + t.ok(robot.keyToggle("嗨", "up") === 1, 'Successfully released 嗨.'); + }, /Invalid key code specified./, 'exception tapping 嗨.'); +}); + +test('Type Ctrl+Shift+RightArrow.', function(t) +{ + t.plan(2); + + var modifiers = [] + modifiers.push('shift') + modifiers.push('control') + + t.ok(robot.keyToggle("right", "down", modifiers) === 1, 'Successfully pressed Ctrl+Shift+RightArrow.'); + t.ok(robot.keyToggle("right", "up", modifiers) === 1, 'Successfully released Ctrl+Shift+RightArrow.'); +}); + +test('Type a string.', function(t) +{ + t.plan(2); + t.ok(robot.typeString("Typed rάöち嗨ఝ 1") === 1, 'successfully typed "Typed rάöち嗨ఝ 1".'); + + t.throws(function() + { + t.ok(robot.typeString() === 1, 'Successfully typed nothing.'); + }, /Invalid number of arguments./, 'exception tapping nothing.'); +}); + +test('Type a string with delay.', function(t) +{ + t.plan(2); + + // 10 characters per minute -> 3 seconds to write the whole sentence here. + t.ok(robot.typeStringDelayed("Typed rάöち嗨ఝ with delay 1", 600) === 1, 'successfully typed with delay "Typed rάöち嗨ఝ with delay 1".'); + + t.throws(function() + { + t.ok(robot.typeStringDelayed() === 1, 'Successfully typed nothing.'); + }, /Invalid number of arguments./, 'exception tapping nothing.'); +});