Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
270cdca14f | |||
e9705db5ba | |||
10096b2709 | |||
e6f4653570 | |||
552cd50266 | |||
b0f9dfddf2 | |||
b0543d3f93 | |||
527ab97a04 | |||
d0e38d0e55 | |||
8ffe640c4b | |||
bcea441630 | |||
17a8f0c995 | |||
60a3f24c86 | |||
c420323cdf | |||
a454b2a2a1 | |||
877a35861a | |||
9317d31153 | |||
d785d341cb | |||
fa202be7da | |||
95833e3a33 | |||
b1bb55766d | |||
bd87beb211 | |||
965c446b51 | |||
4a816737c7 | |||
95f9c731e9 | |||
6c4e4392b4 | |||
432e35cb6a | |||
24786356c4 |
46
.ci/Jenkinsfile
vendored
Normal file
46
.ci/Jenkinsfile
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
properties(
|
||||
[
|
||||
disableConcurrentBuilds()
|
||||
]
|
||||
)
|
||||
|
||||
node('linux && docker') {
|
||||
try {
|
||||
stage('Checkout') {
|
||||
//branch name from Jenkins environment variables
|
||||
echo "My branch is: ${env.BRANCH_NAME}"
|
||||
|
||||
// this doesn't grab tags pointing to this branch
|
||||
//checkout scm
|
||||
// this hack does... https://issues.jenkins.io/browse/JENKINS-45164
|
||||
checkout([
|
||||
$class: 'GitSCM',
|
||||
branches: [[name: 'refs/heads/'+env.BRANCH_NAME]],
|
||||
extensions: [[$class: 'CloneOption', noTags: false, shallow: false, depth: 0, reference: '']],
|
||||
userRemoteConfigs: scm.userRemoteConfigs,
|
||||
])
|
||||
sh '''
|
||||
set -euxo pipefail
|
||||
git checkout "$BRANCH_NAME" --
|
||||
git reset --hard "origin/$BRANCH_NAME"
|
||||
'''
|
||||
}
|
||||
|
||||
stage('Build + Deploy') {
|
||||
sh '''
|
||||
mkdir -p release
|
||||
cp keymap.toml release
|
||||
curl --compressed -sL https://code.moparisthebest.com/moparisthebest/self-ci/raw/branch/master/build-ci.sh | bash
|
||||
'''
|
||||
}
|
||||
|
||||
currentBuild.result = 'SUCCESS'
|
||||
} catch (Exception err) {
|
||||
currentBuild.result = 'FAILURE'
|
||||
} finally {
|
||||
stage('Email') {
|
||||
step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: 'admin.jenkins@moparisthebest.com', sendToIndividuals: true])
|
||||
}
|
||||
deleteDir()
|
||||
}
|
||||
}
|
45
.ci/build.sh
Executable file
45
.ci/build.sh
Executable file
@ -0,0 +1,45 @@
|
||||
#!/bin/bash
|
||||
set -exo pipefail
|
||||
|
||||
echo "starting build for TARGET $TARGET"
|
||||
|
||||
export CRATE_NAME=rusty-keys
|
||||
|
||||
DISABLE_TESTS=${DISABLE_TESTS:-0}
|
||||
|
||||
SUFFIX=""
|
||||
|
||||
echo "$TARGET" | grep -E '^x86_64-pc-windows-gnu$' >/dev/null && SUFFIX=".exe"
|
||||
|
||||
[ "$TARGET" == 'riscv64gc-unknown-linux-gnu' ] && echo 'riscv64gc-unknown-linux-gnu is not yet supported by inotify, skipping build...' && exit 0
|
||||
|
||||
# no main impl for these platforms
|
||||
echo "$TARGET" | grep -E '(android|solaris$)' >/dev/null && DISABLE_TESTS=1
|
||||
|
||||
cross build --target $TARGET --release
|
||||
|
||||
# to check how they are built
|
||||
file "target/$TARGET/release/rusty-keys$SUFFIX"
|
||||
|
||||
if [ $DISABLE_TESTS -ne 1 ]
|
||||
then
|
||||
# only going to run --help I guess
|
||||
cross run --target $TARGET --release --bin rusty-keys -- -h
|
||||
fi
|
||||
|
||||
# if this commit has a tag, upload artifact to release
|
||||
strip "target/$TARGET/release/rusty-keys$SUFFIX" || true # if strip fails, it's fine
|
||||
mkdir -p release
|
||||
mv "target/$TARGET/release/rusty-keys$SUFFIX" "release/rusty-keys-$TARGET$SUFFIX"
|
||||
|
||||
if [ "$TARGET" == 'x86_64-unknown-linux-musl' ]
|
||||
then
|
||||
# for this arch only, we are going to build with each feature combo to test that the build succeeds, but not archive them
|
||||
# the default for now is all features, so that's already tested above
|
||||
cross build --target $TARGET --release --no-default-features
|
||||
cross build --target $TARGET --release --no-default-features --features epoll_inotify
|
||||
cross build --target $TARGET --release --no-default-features --features toml_serde
|
||||
fi
|
||||
|
||||
echo 'build success!'
|
||||
exit 0
|
232
Cargo.lock
generated
232
Cargo.lock
generated
@ -1,249 +1,265 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.0"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.45"
|
||||
version = "1.0.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.6.4"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62"
|
||||
dependencies = [
|
||||
"core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.6.2"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics"
|
||||
version = "0.17.3"
|
||||
version = "0.22.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "269f35f69b542b80e736a20a89a05215c0ce80c2c03c514abb2e318b78379d86"
|
||||
dependencies = [
|
||||
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
"core-graphics-types",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-graphics-types"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "epoll"
|
||||
version = "4.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20df693c700404f7e19d4d6fae6b15215d2913c27955d2b9d6f2c0f537511cd0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
dependencies = [
|
||||
"foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"foreign-types-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
|
||||
dependencies = [
|
||||
"unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inotify"
|
||||
version = "0.7.0"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e5fc8f41dbaa9c8492a96c8afffda4f76896ee041d6a57606e70581b80c901f"
|
||||
dependencies = [
|
||||
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags",
|
||||
"inotify-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inotify-sys"
|
||||
version = "0.1.3"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
|
||||
dependencies = [
|
||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ioctl-sys"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.62"
|
||||
version = "0.2.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.15.0"
|
||||
version = "0.22.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3bb9a13fa32bc5aeb64150cd3f32d6cf4c748f8f8a417cce5d2eb976a8370ba"
|
||||
dependencies = [
|
||||
"bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.4"
|
||||
version = "1.0.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
|
||||
dependencies = [
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.2"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusty-keys"
|
||||
version = "0.0.3"
|
||||
dependencies = [
|
||||
"core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"inotify 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uinput-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation-sys",
|
||||
"core-graphics",
|
||||
"epoll",
|
||||
"getopts",
|
||||
"inotify",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"nix",
|
||||
"serde",
|
||||
"toml",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.101"
|
||||
version = "1.0.130"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
|
||||
dependencies = [
|
||||
"serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.101"
|
||||
version = "1.0.130"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.5"
|
||||
version = "1.0.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.3"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
|
||||
dependencies = [
|
||||
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uinput-sys"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ioctl-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.6"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.8"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2"
|
||||
"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be"
|
||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
|
||||
"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
|
||||
"checksum core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)" = "56790968ab1c8a1202a102e6de05fc6e1ec87da99e4e93e9a7d13efbfc1e95a9"
|
||||
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
"checksum getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
|
||||
"checksum inotify 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24e40d6fd5d64e2082e0c796495c8ef5ad667a96d03e5aaa0becfd9d47bcbfb8"
|
||||
"checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0"
|
||||
"checksum ioctl-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5e2c4b26352496eaaa8ca7cfa9bd99e93419d3f7983dc6e99c2a35fe9e33504a"
|
||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
|
||||
"checksum nix 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229"
|
||||
"checksum proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afdc77cc74ec70ed262262942ebb7dac3d479e9e5cfa2da1841c0806f6cdabcc"
|
||||
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
|
||||
"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd"
|
||||
"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e"
|
||||
"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf"
|
||||
"checksum toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724"
|
||||
"checksum uinput-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9aabddd8174ccadd600afeab346bb276cb1db5fafcf6a7c5c5708b8cc4b2cac7"
|
||||
"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
|
||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
26
Cargo.toml
26
Cargo.toml
@ -22,22 +22,26 @@ include = [
|
||||
|
||||
[dependencies]
|
||||
getopts = "0.2.21"
|
||||
toml = "0.5.3"
|
||||
serde = { version = "1.0.101", features = ["derive"] }
|
||||
toml = { version = "0.5.8", optional = true }
|
||||
serde = { version = "1.0.130", features = ["derive"], optional = true }
|
||||
|
||||
#[target.'cfg(target_os="macos")'.dependencies]
|
||||
core-graphics = "0.17"
|
||||
core-foundation-sys = "0.6.2"
|
||||
[target.'cfg(target_os="macos")'.dependencies]
|
||||
core-graphics = "0.22"
|
||||
core-foundation-sys = "0.8"
|
||||
#rustkit = "0.0.1"
|
||||
lazy_static = "1.4.0"
|
||||
libc = "0.2"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["winuser", "wincon"] }
|
||||
winapi = { version = "0.3.9", features = ["winuser", "wincon"] }
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
[target.'cfg(target_os="linux")'.dependencies]
|
||||
libc = "0.2.62"
|
||||
nix = "0.15.0"
|
||||
uinput-sys = "0.1.7"
|
||||
inotify = { version = "0.7.0", default-features = false, features = [] }
|
||||
libc = "0.2.102"
|
||||
nix = "0.22.1"
|
||||
epoll = { version = "4.3.1", optional = true }
|
||||
inotify = { version = "0.9.3", default-features = false, features = [], optional = true }
|
||||
|
||||
[features]
|
||||
default = ["epoll_inotify", "toml_serde"]
|
||||
toml_serde = ["toml", "serde"]
|
||||
epoll_inotify = ["epoll", "inotify"]
|
||||
|
909
Events.h
909
Events.h
@ -1,909 +0,0 @@
|
||||
/*
|
||||
File: HIToolbox/Events.h
|
||||
|
||||
Contains: Event Manager Interfaces.
|
||||
|
||||
Copyright: © 1985-2008 by Apple Computer, Inc., all rights reserved
|
||||
|
||||
Bugs?: For bug reports, consult the following page on
|
||||
the World Wide Web:
|
||||
|
||||
http://developer.apple.com/bugreporter/
|
||||
|
||||
*/
|
||||
#ifndef __EVENTS__
|
||||
#define __EVENTS__
|
||||
|
||||
#ifndef __APPLICATIONSERVICES__
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <AvailabilityMacros.h>
|
||||
|
||||
#if PRAGMA_ONCE
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#pragma pack(push, 2)
|
||||
|
||||
typedef UInt16 EventKind;
|
||||
typedef UInt16 EventMask;
|
||||
enum {
|
||||
nullEvent = 0,
|
||||
mouseDown = 1,
|
||||
mouseUp = 2,
|
||||
keyDown = 3,
|
||||
keyUp = 4,
|
||||
autoKey = 5,
|
||||
updateEvt = 6,
|
||||
diskEvt = 7, /* Not sent in Carbon. See kEventClassVolume in CarbonEvents.h*/
|
||||
activateEvt = 8,
|
||||
osEvt = 15,
|
||||
kHighLevelEvent = 23
|
||||
};
|
||||
|
||||
enum {
|
||||
mDownMask = 1 << mouseDown, /* mouse button pressed*/
|
||||
mUpMask = 1 << mouseUp, /* mouse button released*/
|
||||
keyDownMask = 1 << keyDown, /* key pressed*/
|
||||
keyUpMask = 1 << keyUp, /* key released*/
|
||||
autoKeyMask = 1 << autoKey, /* key repeatedly held down*/
|
||||
updateMask = 1 << updateEvt, /* window needs updating*/
|
||||
diskMask = 1 << diskEvt, /* disk inserted*/
|
||||
activMask = 1 << activateEvt, /* activate/deactivate window*/
|
||||
highLevelEventMask = 0x0400, /* high-level events (includes AppleEvents)*/
|
||||
osMask = 1 << osEvt, /* operating system events (suspend, resume)*/
|
||||
everyEvent = 0xFFFF /* all of the above*/
|
||||
};
|
||||
|
||||
enum {
|
||||
charCodeMask = 0x000000FF,
|
||||
keyCodeMask = 0x0000FF00,
|
||||
adbAddrMask = 0x00FF0000,
|
||||
osEvtMessageMask = (UInt32)0xFF000000
|
||||
};
|
||||
|
||||
enum {
|
||||
/* OS event messages. Event (sub)code is in the high byte of the message field.*/
|
||||
mouseMovedMessage = 0x00FA,
|
||||
suspendResumeMessage = 0x0001
|
||||
};
|
||||
|
||||
enum {
|
||||
resumeFlag = 1 /* Bit 0 of message indicates resume vs suspend*/
|
||||
};
|
||||
|
||||
#if CALL_NOT_IN_CARBON
|
||||
/* convertClipboardFlag is not ever set under Carbon. This is because scrap conversion is */
|
||||
/* not tied to suspend/resume events any longer. Your application should instead use the */
|
||||
/* scrap promise mechanism and fulfill scrap requests only when your promise keeper proc */
|
||||
/* is called. If you need to know if the scrap has changed, you can cache the last */
|
||||
/* ScrapRef you received and compare it with the current ScrapRef */
|
||||
enum {
|
||||
convertClipboardFlag = 2 /* Bit 1 in resume message indicates clipboard change*/
|
||||
};
|
||||
|
||||
#endif /* CALL_NOT_IN_CARBON */
|
||||
|
||||
/*
|
||||
CARBON ALERT! BATTLESTATIONS!
|
||||
|
||||
The EventModifiers bits defined here are also used in the newer Carbon Event
|
||||
key modifiers parameters. There are two main differences:
|
||||
|
||||
1) The Carbon key modifiers parameter is a UInt32, not a UInt16. Never try to
|
||||
extract the key modifiers parameter from a Carbon Event into an EventModifiers
|
||||
type. You will probably get your stack trashed.
|
||||
2) The Carbon key modifiers is just that: key modifiers. That parameter will
|
||||
never contain the button state bit.
|
||||
*/
|
||||
typedef UInt16 EventModifiers;
|
||||
enum {
|
||||
/* modifiers */
|
||||
activeFlagBit = 0, /* activate? (activateEvt and mouseDown)*/
|
||||
btnStateBit = 7, /* state of button?*/
|
||||
cmdKeyBit = 8, /* command key down?*/
|
||||
shiftKeyBit = 9, /* shift key down?*/
|
||||
alphaLockBit = 10, /* alpha lock down?*/
|
||||
optionKeyBit = 11, /* option key down?*/
|
||||
controlKeyBit = 12, /* control key down?*/
|
||||
rightShiftKeyBit = 13, /* right shift key down? Not supported on Mac OS X.*/
|
||||
rightOptionKeyBit = 14, /* right Option key down? Not supported on Mac OS X.*/
|
||||
rightControlKeyBit = 15 /* right Control key down? Not supported on Mac OS X.*/
|
||||
};
|
||||
|
||||
enum {
|
||||
activeFlag = 1 << activeFlagBit,
|
||||
btnState = 1 << btnStateBit,
|
||||
cmdKey = 1 << cmdKeyBit,
|
||||
shiftKey = 1 << shiftKeyBit,
|
||||
alphaLock = 1 << alphaLockBit,
|
||||
optionKey = 1 << optionKeyBit,
|
||||
controlKey = 1 << controlKeyBit,
|
||||
rightShiftKey = 1 << rightShiftKeyBit, /* Not supported on Mac OS X.*/
|
||||
rightOptionKey = 1 << rightOptionKeyBit, /* Not supported on Mac OS X.*/
|
||||
rightControlKey = 1 << rightControlKeyBit /* Not supported on Mac OS X.*/
|
||||
};
|
||||
|
||||
/* MacRoman character codes*/
|
||||
enum {
|
||||
kNullCharCode = 0,
|
||||
kHomeCharCode = 1,
|
||||
kEnterCharCode = 3,
|
||||
kEndCharCode = 4,
|
||||
kHelpCharCode = 5,
|
||||
kBellCharCode = 7,
|
||||
kBackspaceCharCode = 8,
|
||||
kTabCharCode = 9,
|
||||
kLineFeedCharCode = 10,
|
||||
kVerticalTabCharCode = 11,
|
||||
kPageUpCharCode = 11,
|
||||
kFormFeedCharCode = 12,
|
||||
kPageDownCharCode = 12,
|
||||
kReturnCharCode = 13,
|
||||
kFunctionKeyCharCode = 16,
|
||||
kCommandCharCode = 17, /* glyph available only in system fonts*/
|
||||
kCheckCharCode = 18, /* glyph available only in system fonts*/
|
||||
kDiamondCharCode = 19, /* glyph available only in system fonts*/
|
||||
kAppleLogoCharCode = 20, /* glyph available only in system fonts*/
|
||||
kEscapeCharCode = 27,
|
||||
kClearCharCode = 27,
|
||||
kLeftArrowCharCode = 28,
|
||||
kRightArrowCharCode = 29,
|
||||
kUpArrowCharCode = 30,
|
||||
kDownArrowCharCode = 31,
|
||||
kSpaceCharCode = 32,
|
||||
kDeleteCharCode = 127,
|
||||
kBulletCharCode = 165,
|
||||
kNonBreakingSpaceCharCode = 202
|
||||
};
|
||||
|
||||
/* useful Unicode code points*/
|
||||
enum {
|
||||
kShiftUnicode = 0x21E7, /* Unicode UPWARDS WHITE ARROW*/
|
||||
kControlUnicode = 0x2303, /* Unicode UP ARROWHEAD*/
|
||||
kOptionUnicode = 0x2325, /* Unicode OPTION KEY*/
|
||||
kCommandUnicode = 0x2318, /* Unicode PLACE OF INTEREST SIGN*/
|
||||
kPencilUnicode = 0x270E, /* Unicode LOWER RIGHT PENCIL; actually pointed left until Mac OS X 10.3*/
|
||||
kPencilLeftUnicode = 0xF802, /* Unicode LOWER LEFT PENCIL; available in Mac OS X 10.3 and later*/
|
||||
kCheckUnicode = 0x2713, /* Unicode CHECK MARK*/
|
||||
kDiamondUnicode = 0x25C6, /* Unicode BLACK DIAMOND*/
|
||||
kBulletUnicode = 0x2022, /* Unicode BULLET*/
|
||||
kAppleLogoUnicode = 0xF8FF /* Unicode APPLE LOGO*/
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Summary:
|
||||
* Virtual keycodes
|
||||
*
|
||||
* Discussion:
|
||||
* These constants are the virtual keycodes defined originally in
|
||||
* Inside Mac Volume V, pg. V-191. They identify physical keys on a
|
||||
* keyboard. Those constants with "ANSI" in the name are labeled
|
||||
* according to the key position on an ANSI-standard US keyboard.
|
||||
* For example, kVK_ANSI_A indicates the virtual keycode for the key
|
||||
* with the letter 'A' in the US keyboard layout. Other keyboard
|
||||
* layouts may have the 'A' key label on a different physical key;
|
||||
* in this case, pressing 'A' will generate a different virtual
|
||||
* keycode.
|
||||
*/
|
||||
enum {
|
||||
kVK_ANSI_A = 0x00,
|
||||
kVK_ANSI_S = 0x01,
|
||||
kVK_ANSI_D = 0x02,
|
||||
kVK_ANSI_F = 0x03,
|
||||
kVK_ANSI_H = 0x04,
|
||||
kVK_ANSI_G = 0x05,
|
||||
kVK_ANSI_Z = 0x06,
|
||||
kVK_ANSI_X = 0x07,
|
||||
kVK_ANSI_C = 0x08,
|
||||
kVK_ANSI_V = 0x09,
|
||||
kVK_ANSI_B = 0x0B,
|
||||
kVK_ANSI_Q = 0x0C,
|
||||
kVK_ANSI_W = 0x0D,
|
||||
kVK_ANSI_E = 0x0E,
|
||||
kVK_ANSI_R = 0x0F,
|
||||
kVK_ANSI_Y = 0x10,
|
||||
kVK_ANSI_T = 0x11,
|
||||
kVK_ANSI_1 = 0x12,
|
||||
kVK_ANSI_2 = 0x13,
|
||||
kVK_ANSI_3 = 0x14,
|
||||
kVK_ANSI_4 = 0x15,
|
||||
kVK_ANSI_6 = 0x16,
|
||||
kVK_ANSI_5 = 0x17,
|
||||
kVK_ANSI_Equal = 0x18,
|
||||
kVK_ANSI_9 = 0x19,
|
||||
kVK_ANSI_7 = 0x1A,
|
||||
kVK_ANSI_Minus = 0x1B,
|
||||
kVK_ANSI_8 = 0x1C,
|
||||
kVK_ANSI_0 = 0x1D,
|
||||
kVK_ANSI_RightBracket = 0x1E,
|
||||
kVK_ANSI_O = 0x1F,
|
||||
kVK_ANSI_U = 0x20,
|
||||
kVK_ANSI_LeftBracket = 0x21,
|
||||
kVK_ANSI_I = 0x22,
|
||||
kVK_ANSI_P = 0x23,
|
||||
kVK_ANSI_L = 0x25,
|
||||
kVK_ANSI_J = 0x26,
|
||||
kVK_ANSI_Quote = 0x27,
|
||||
kVK_ANSI_K = 0x28,
|
||||
kVK_ANSI_Semicolon = 0x29,
|
||||
kVK_ANSI_Backslash = 0x2A,
|
||||
kVK_ANSI_Comma = 0x2B,
|
||||
kVK_ANSI_Slash = 0x2C,
|
||||
kVK_ANSI_N = 0x2D,
|
||||
kVK_ANSI_M = 0x2E,
|
||||
kVK_ANSI_Period = 0x2F,
|
||||
kVK_ANSI_Grave = 0x32,
|
||||
kVK_ANSI_KeypadDecimal = 0x41,
|
||||
kVK_ANSI_KeypadMultiply = 0x43,
|
||||
kVK_ANSI_KeypadPlus = 0x45,
|
||||
kVK_ANSI_KeypadClear = 0x47,
|
||||
kVK_ANSI_KeypadDivide = 0x4B,
|
||||
kVK_ANSI_KeypadEnter = 0x4C,
|
||||
kVK_ANSI_KeypadMinus = 0x4E,
|
||||
kVK_ANSI_KeypadEquals = 0x51,
|
||||
kVK_ANSI_Keypad0 = 0x52,
|
||||
kVK_ANSI_Keypad1 = 0x53,
|
||||
kVK_ANSI_Keypad2 = 0x54,
|
||||
kVK_ANSI_Keypad3 = 0x55,
|
||||
kVK_ANSI_Keypad4 = 0x56,
|
||||
kVK_ANSI_Keypad5 = 0x57,
|
||||
kVK_ANSI_Keypad6 = 0x58,
|
||||
kVK_ANSI_Keypad7 = 0x59,
|
||||
kVK_ANSI_Keypad8 = 0x5B,
|
||||
kVK_ANSI_Keypad9 = 0x5C
|
||||
};
|
||||
|
||||
/* keycodes for keys that are independent of keyboard layout*/
|
||||
enum {
|
||||
kVK_Return = 0x24,
|
||||
kVK_Tab = 0x30,
|
||||
kVK_Space = 0x31,
|
||||
kVK_Delete = 0x33,
|
||||
kVK_Escape = 0x35,
|
||||
kVK_Command = 0x37,
|
||||
kVK_Shift = 0x38,
|
||||
kVK_CapsLock = 0x39,
|
||||
kVK_Option = 0x3A,
|
||||
kVK_Control = 0x3B,
|
||||
kVK_RightCommand = 0x36,
|
||||
kVK_RightShift = 0x3C,
|
||||
kVK_RightOption = 0x3D,
|
||||
kVK_RightControl = 0x3E,
|
||||
kVK_Function = 0x3F,
|
||||
kVK_F17 = 0x40,
|
||||
kVK_VolumeUp = 0x48,
|
||||
kVK_VolumeDown = 0x49,
|
||||
kVK_Mute = 0x4A,
|
||||
kVK_F18 = 0x4F,
|
||||
kVK_F19 = 0x50,
|
||||
kVK_F20 = 0x5A,
|
||||
kVK_F5 = 0x60,
|
||||
kVK_F6 = 0x61,
|
||||
kVK_F7 = 0x62,
|
||||
kVK_F3 = 0x63,
|
||||
kVK_F8 = 0x64,
|
||||
kVK_F9 = 0x65,
|
||||
kVK_F11 = 0x67,
|
||||
kVK_F13 = 0x69,
|
||||
kVK_F16 = 0x6A,
|
||||
kVK_F14 = 0x6B,
|
||||
kVK_F10 = 0x6D,
|
||||
kVK_F12 = 0x6F,
|
||||
kVK_F15 = 0x71,
|
||||
kVK_Help = 0x72,
|
||||
kVK_Home = 0x73,
|
||||
kVK_PageUp = 0x74,
|
||||
kVK_ForwardDelete = 0x75,
|
||||
kVK_F4 = 0x76,
|
||||
kVK_End = 0x77,
|
||||
kVK_F2 = 0x78,
|
||||
kVK_PageDown = 0x79,
|
||||
kVK_F1 = 0x7A,
|
||||
kVK_LeftArrow = 0x7B,
|
||||
kVK_RightArrow = 0x7C,
|
||||
kVK_DownArrow = 0x7D,
|
||||
kVK_UpArrow = 0x7E
|
||||
};
|
||||
|
||||
/* ISO keyboards only*/
|
||||
enum {
|
||||
kVK_ISO_Section = 0x0A
|
||||
};
|
||||
|
||||
/* JIS keyboards only*/
|
||||
enum {
|
||||
kVK_JIS_Yen = 0x5D,
|
||||
kVK_JIS_Underscore = 0x5E,
|
||||
kVK_JIS_KeypadComma = 0x5F,
|
||||
kVK_JIS_Eisu = 0x66,
|
||||
kVK_JIS_Kana = 0x68
|
||||
};
|
||||
|
||||
struct EventRecord {
|
||||
EventKind what;
|
||||
unsigned long message;
|
||||
UInt32 when;
|
||||
Point where;
|
||||
EventModifiers modifiers;
|
||||
};
|
||||
typedef struct EventRecord EventRecord;
|
||||
typedef CALLBACK_API( void , FKEYProcPtr )(void);
|
||||
typedef STACK_UPP_TYPE(FKEYProcPtr) FKEYUPP;
|
||||
/*
|
||||
* NewFKEYUPP()
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: not available
|
||||
* CarbonLib: not available
|
||||
* Non-Carbon CFM: available as macro/inline
|
||||
*/
|
||||
|
||||
/*
|
||||
* DisposeFKEYUPP()
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: not available
|
||||
* CarbonLib: not available
|
||||
* Non-Carbon CFM: available as macro/inline
|
||||
*/
|
||||
|
||||
/*
|
||||
* InvokeFKEYUPP()
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: not available
|
||||
* CarbonLib: not available
|
||||
* Non-Carbon CFM: available as macro/inline
|
||||
*/
|
||||
|
||||
#if !__LP64__
|
||||
/*
|
||||
* GetMouse() *** DEPRECATED ***
|
||||
*
|
||||
* Deprecated:
|
||||
* Use HIGetMousePosition instead.
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework [32-bit only] but deprecated in 10.5
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern void
|
||||
GetMouse(Point * mouseLoc) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5;
|
||||
|
||||
|
||||
#endif /* !__LP64__ */
|
||||
|
||||
/*
|
||||
* Button() *** DEPRECATED ***
|
||||
*
|
||||
* Deprecated:
|
||||
* Use GetCurrentButtonState or GetCurrentEventButtonState instead.
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework but deprecated in 10.6
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern Boolean
|
||||
Button(void) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6;
|
||||
|
||||
|
||||
#if !__LP64__
|
||||
/*
|
||||
* StillDown()
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework [32-bit only]
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern Boolean
|
||||
StillDown(void) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
|
||||
|
||||
|
||||
/*
|
||||
* WaitMouseUp()
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework [32-bit only]
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern Boolean
|
||||
WaitMouseUp(void) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
|
||||
|
||||
|
||||
/*
|
||||
* KeyTranslate() *** DEPRECATED ***
|
||||
*
|
||||
* Deprecated:
|
||||
* Use UCKeyTranslate instead.
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework [32-bit only] but deprecated in 10.6
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern UInt32
|
||||
KeyTranslate(
|
||||
const void * transData,
|
||||
UInt16 keycode,
|
||||
UInt32 * state) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6;
|
||||
|
||||
|
||||
/*
|
||||
* GetCaretTime()
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework [32-bit only]
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern UInt32
|
||||
GetCaretTime(void) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
|
||||
|
||||
|
||||
|
||||
#endif /* !__LP64__ */
|
||||
|
||||
/*
|
||||
QuickTime 3.0 supports GetKeys() on unix and win32
|
||||
But, on little endian machines you will have to be
|
||||
careful about bit numberings and/or use a KeyMapByteArray
|
||||
instead.
|
||||
*/
|
||||
#if TARGET_API_MAC_OS8
|
||||
|
||||
typedef UInt32 KeyMap[4];
|
||||
#else
|
||||
typedef BigEndianUInt32 KeyMap[4];
|
||||
#endif /* TARGET_API_MAC_OS8 */
|
||||
|
||||
typedef UInt8 KeyMapByteArray[16];
|
||||
/*
|
||||
* GetKeys()
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern void
|
||||
GetKeys(KeyMap theKeys) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
|
||||
|
||||
|
||||
/* Obsolete event types & masks */
|
||||
enum {
|
||||
networkEvt = 10,
|
||||
driverEvt = 11,
|
||||
app1Evt = 12,
|
||||
app2Evt = 13,
|
||||
app3Evt = 14,
|
||||
app4Evt = 15,
|
||||
networkMask = 0x0400,
|
||||
driverMask = 0x0800,
|
||||
app1Mask = 0x1000,
|
||||
app2Mask = 0x2000,
|
||||
app3Mask = 0x4000,
|
||||
app4Mask = 0x8000
|
||||
};
|
||||
|
||||
struct EvQEl {
|
||||
QElemPtr qLink;
|
||||
SInt16 qType;
|
||||
EventKind evtQWhat; /* this part is identical to the EventRecord as defined above */
|
||||
unsigned long evtQMessage;
|
||||
UInt32 evtQWhen;
|
||||
Point evtQWhere;
|
||||
EventModifiers evtQModifiers;
|
||||
};
|
||||
typedef struct EvQEl EvQEl;
|
||||
typedef EvQEl * EvQElPtr;
|
||||
typedef CALLBACK_API( void , GetNextEventFilterProcPtr )(EventRecord *theEvent, Boolean *result);
|
||||
typedef STACK_UPP_TYPE(GetNextEventFilterProcPtr) GetNextEventFilterUPP;
|
||||
/*
|
||||
* NewGetNextEventFilterUPP()
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: not available
|
||||
* CarbonLib: not available
|
||||
* Non-Carbon CFM: available as macro/inline
|
||||
*/
|
||||
|
||||
/*
|
||||
* DisposeGetNextEventFilterUPP()
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: not available
|
||||
* CarbonLib: not available
|
||||
* Non-Carbon CFM: available as macro/inline
|
||||
*/
|
||||
|
||||
/*
|
||||
* InvokeGetNextEventFilterUPP()
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: not available
|
||||
* CarbonLib: not available
|
||||
* Non-Carbon CFM: available as macro/inline
|
||||
*/
|
||||
|
||||
typedef GetNextEventFilterUPP GNEFilterUPP;
|
||||
#if !__LP64__
|
||||
/*
|
||||
* GetDblTime()
|
||||
*
|
||||
* Summary:
|
||||
* Returns the maximum time (in units of 1/60th of a second) allowed
|
||||
* between two consecutive mouse-down events in order for the second
|
||||
* click to be considered a double-click.
|
||||
*
|
||||
* Discussion:
|
||||
* In 64-bit applications, you may replace calls to this API with
|
||||
* calls to NXClickTime (declared in
|
||||
* <IOKit/hidsystem/event_status_driver.h>) or with +[NSEvent
|
||||
* doubleClickInterval] (available in Mac OS X 10.6 and later).
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Result:
|
||||
* The maximum time between mouse-downs allowed for a double-click.
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework [32-bit only]
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern UInt32
|
||||
GetDblTime(void) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
|
||||
|
||||
|
||||
/*
|
||||
* SetEventMask()
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework [32-bit only]
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern void
|
||||
SetEventMask(EventMask value) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
|
||||
|
||||
|
||||
/*
|
||||
* GetNextEvent() *** DEPRECATED ***
|
||||
*
|
||||
* Deprecated:
|
||||
* Use ReceiveNextEvent instead.
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework [32-bit only] but deprecated in 10.6
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern Boolean
|
||||
GetNextEvent(
|
||||
EventMask eventMask,
|
||||
EventRecord * theEvent) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6;
|
||||
|
||||
|
||||
/*
|
||||
* WaitNextEvent() *** DEPRECATED ***
|
||||
*
|
||||
* Deprecated:
|
||||
* Use ReceiveNextEvent instead.
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework [32-bit only] but deprecated in 10.6
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern Boolean
|
||||
WaitNextEvent(
|
||||
EventMask eventMask,
|
||||
EventRecord * theEvent,
|
||||
UInt32 sleep,
|
||||
RgnHandle mouseRgn) /* can be NULL */ AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6;
|
||||
|
||||
|
||||
/*
|
||||
* EventAvail() *** DEPRECATED ***
|
||||
*
|
||||
* Deprecated:
|
||||
* Use FindSpecificEventInQueue instead.
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework [32-bit only] but deprecated in 10.6
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern Boolean
|
||||
EventAvail(
|
||||
EventMask eventMask,
|
||||
EventRecord * theEvent) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6;
|
||||
|
||||
|
||||
/*
|
||||
* PostEvent() *** DEPRECATED ***
|
||||
*
|
||||
* Deprecated:
|
||||
* Use PostEventToQueue or CGEventPost instead.
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework [32-bit only] but deprecated in 10.6
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern OSErr
|
||||
PostEvent(
|
||||
EventKind eventNum,
|
||||
UInt32 eventMsg) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6;
|
||||
|
||||
|
||||
#endif /* !__LP64__ */
|
||||
|
||||
/*
|
||||
* FlushEvents() *** DEPRECATED ***
|
||||
*
|
||||
* Deprecated:
|
||||
* Use FlushEventsMatchingListFromQueue,
|
||||
* FlushSpecificEventsFromQueue, or FlushEventQueue instead.
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework but deprecated in 10.6
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern void
|
||||
FlushEvents(
|
||||
EventMask whichMask,
|
||||
EventMask stopMask) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6;
|
||||
|
||||
|
||||
#if OLDROUTINENAMES
|
||||
#define KeyTrans(transData, keycode, state) KeyTranslate(transData, keycode, state)
|
||||
#endif /* OLDROUTINENAMES */
|
||||
|
||||
#if !__LP64__
|
||||
/*
|
||||
* KeyScript() *** DEPRECATED ***
|
||||
*
|
||||
* Deprecated:
|
||||
* Use TISSelectInputSource API for positive verbs (ScriptCode).
|
||||
* Use TSMDocument properties to restrict input sources:
|
||||
* kTSMDocumentEnabledInputSourcesPropertyTag
|
||||
* kTSMDocumentInputSourceOverridePropertyTag
|
||||
*
|
||||
* Summary:
|
||||
* Switch to the specified script's default (last used) input source.
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework [32-bit only] but deprecated in 10.5
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern void
|
||||
KeyScript(short code) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_5;
|
||||
|
||||
|
||||
#endif /* !__LP64__ */
|
||||
|
||||
/*
|
||||
* IsCmdChar() *** DEPRECATED ***
|
||||
*
|
||||
* Deprecated:
|
||||
* Use IsUserCancelEventRef or CheckEventQueueForUserCancel instead.
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework but deprecated in 10.6
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern Boolean
|
||||
IsCmdChar(
|
||||
const EventRecord * event,
|
||||
short test) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_6;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
LowMem accessor functions previously in LowMem.h
|
||||
*/
|
||||
/*
|
||||
* LMGetKeyThresh()
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern SInt16
|
||||
LMGetKeyThresh(void) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
|
||||
|
||||
|
||||
#if !__LP64__
|
||||
/*
|
||||
* LMSetKeyThresh()
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework [32-bit only]
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern void
|
||||
LMSetKeyThresh(SInt16 value) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
|
||||
|
||||
|
||||
|
||||
#endif /* !__LP64__ */
|
||||
|
||||
/*
|
||||
* LMGetKeyRepThresh()
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern SInt16
|
||||
LMGetKeyRepThresh(void) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
|
||||
|
||||
|
||||
#if !__LP64__
|
||||
/*
|
||||
* LMSetKeyRepThresh()
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework [32-bit only]
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern void
|
||||
LMSetKeyRepThresh(SInt16 value) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
|
||||
|
||||
|
||||
#endif /* !__LP64__ */
|
||||
|
||||
/*
|
||||
* LMGetKbdLast()
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern UInt8
|
||||
LMGetKbdLast(void) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
|
||||
|
||||
|
||||
#if !__LP64__
|
||||
/*
|
||||
* LMSetKbdLast()
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework [32-bit only]
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern void
|
||||
LMSetKbdLast(UInt8 value) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
|
||||
|
||||
|
||||
|
||||
#endif /* !__LP64__ */
|
||||
|
||||
/*
|
||||
* LMGetKbdType()
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern UInt8
|
||||
LMGetKbdType(void) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
|
||||
|
||||
|
||||
#if !__LP64__
|
||||
/*
|
||||
* LMSetKbdType()
|
||||
*
|
||||
* Mac OS X threading:
|
||||
* Not thread safe
|
||||
*
|
||||
* Availability:
|
||||
* Mac OS X: in version 10.0 and later in Carbon.framework [32-bit only]
|
||||
* CarbonLib: in CarbonLib 1.0 and later
|
||||
* Non-Carbon CFM: in InterfaceLib 7.1 and later
|
||||
*/
|
||||
extern void
|
||||
LMSetKbdType(UInt8 value) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER;
|
||||
|
||||
|
||||
#endif /* !__LP64__ */
|
||||
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __EVENTS__ */
|
||||
|
12
README.md
12
README.md
@ -1,8 +1,11 @@
|
||||
rusty-keys
|
||||
======
|
||||
uinput level keyboard mapper for linux, with advanced caps lock and shift swapping behavior
|
||||
==========
|
||||
|
||||
This is the only keymapper I am aware of capable of implementing this layout:
|
||||
[![Build Status](https://ci.moparisthe.best/job/moparisthebest/job/rusty-keys/job/master/badge/icon%3Fstyle=plastic)](https://ci.moparisthe.best/job/moparisthebest/job/rusty-keys/job/master/)
|
||||
|
||||
low level keyboard mapper for linux and windows, with advanced caps lock and shift swapping behavior
|
||||
|
||||
This is the only keymapper I am aware of capable of implementing this layout, which I call Unix Programmer's Dvorak, which has been my daily driver since 2014:
|
||||
![Unix Programmer's Dvorak](https://www.moparisthebest.com/kbs/programmer-dvorak-NoSecondary-NumpadStandard-NoSwap-StandardNums-SwapAt-SwapPipe.svg)
|
||||
|
||||
The Problem
|
||||
@ -17,7 +20,7 @@ The Solution
|
||||
2. Create a new keyboard input device with uinput, this looks identical to any other keyboard device to anything running on the box.
|
||||
3. Read input_events from the real device, map them, send them to our created device.
|
||||
|
||||
This solution is what rusty-keys implements, it works in ttys, in X, in virtualbox even running windows or whatever,
|
||||
This solution is what rusty-keys implements, it works in ttys, in X, in Wayland, in virtualbox even running windows or whatever,
|
||||
on SDL games, it will work literally everywhere, because rusty-keys just creates a regular keyboard.
|
||||
|
||||
How to run
|
||||
@ -49,6 +52,7 @@ How to install
|
||||
--------------
|
||||
* `cargo install rusty-keys`
|
||||
* Arch Linux [rusty-keys](https://aur.archlinux.org/packages/rusty-keys/) [rusty-keys-git](https://aur.archlinux.org/packages/rusty-keys-git/)
|
||||
* Download a static binary for your system from the [releases](https://code.moparisthebest.com/moparisthebest/rusty-keys/releases) section. [github mirror](https://github.com/moparisthebest/rusty-keys/releases)
|
||||
|
||||
License
|
||||
-------
|
||||
|
90
appveyor.yml
Normal file
90
appveyor.yml
Normal file
@ -0,0 +1,90 @@
|
||||
# Based on the "trust" template v0.1.2
|
||||
# https://github.com/japaric/trust/tree/v0.1.2
|
||||
|
||||
environment:
|
||||
global:
|
||||
# TODO This is the Rust channel that build jobs will use by default but can be
|
||||
# overridden on a case by case basis down below
|
||||
RUST_VERSION: stable
|
||||
|
||||
# TODO Update this to match the name of your project.
|
||||
CRATE_NAME: rusty-keys
|
||||
|
||||
# TODO These are all the build jobs. Adjust as necessary. Comment out what you
|
||||
# don't need
|
||||
matrix:
|
||||
# MinGW
|
||||
- TARGET: i686-pc-windows-gnu
|
||||
- TARGET: x86_64-pc-windows-gnu
|
||||
|
||||
# MSVC
|
||||
- TARGET: i686-pc-windows-msvc
|
||||
- TARGET: x86_64-pc-windows-msvc
|
||||
|
||||
# Testing other channels
|
||||
- TARGET: x86_64-pc-windows-gnu
|
||||
RUST_VERSION: nightly
|
||||
- TARGET: x86_64-pc-windows-msvc
|
||||
RUST_VERSION: nightly
|
||||
|
||||
install:
|
||||
- ps: >-
|
||||
If ($Env:TARGET -eq 'x86_64-pc-windows-gnu') {
|
||||
$Env:PATH += ';C:\msys64\mingw64\bin'
|
||||
} ElseIf ($Env:TARGET -eq 'i686-pc-windows-gnu') {
|
||||
$Env:PATH += ';C:\msys64\mingw32\bin'
|
||||
}
|
||||
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
|
||||
- rustup-init.exe -y --default-host %TARGET% --default-toolchain %RUST_VERSION%
|
||||
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
|
||||
- rustc -Vv
|
||||
- cargo -V
|
||||
|
||||
# TODO This is the "test phase", tweak it as you see fit
|
||||
test_script:
|
||||
# we don't run the "test phase" when doing deploys
|
||||
- if [%APPVEYOR_REPO_TAG%]==[false] (
|
||||
cargo build --target %TARGET% --release &&
|
||||
cargo run --target %TARGET% --release --bin rusty-keys -- -h
|
||||
)
|
||||
|
||||
before_deploy:
|
||||
# TODO Update this to build the artifacts that matter to you
|
||||
- cargo rustc --target %TARGET% --release --bin rusty-keys -- -C lto
|
||||
- ps: ci\before_deploy.ps1
|
||||
|
||||
deploy:
|
||||
artifact: /rusty-keys-.*\.exe/
|
||||
# TODO update `auth_token.secure`
|
||||
# - Create a `public_repo` GitHub token. Go to: https://github.com/settings/tokens/new
|
||||
# - Encrypt it. Go to https://ci.appveyor.com/tools/encrypt
|
||||
# - Paste the output down here
|
||||
auth_token:
|
||||
secure: gyQW6TqUY94X8IpcQeezbngBQA/PROaCPpr8K+8IxGBG5gf2iHra2CLlp/QJJZYx
|
||||
description: ''
|
||||
on:
|
||||
# TODO Here you can pick which targets will generate binary releases
|
||||
# In this example, there are some targets that are tested using the stable
|
||||
# and nightly channels. This condition makes sure there is only one release
|
||||
# for such targets and that's generated using the stable channel
|
||||
RUST_VERSION: stable
|
||||
appveyor_repo_tag: true
|
||||
provider: GitHub
|
||||
|
||||
cache:
|
||||
- C:\Users\appveyor\.cargo\registry
|
||||
- target
|
||||
|
||||
branches:
|
||||
only:
|
||||
# Release tags
|
||||
- /^v\d+\.\d+\.\d+.*$/
|
||||
- master
|
||||
- dev
|
||||
|
||||
notifications:
|
||||
- provider: Email
|
||||
on_build_success: false
|
||||
|
||||
# Building is done in the test phase, so we disable Appveyor's build phase.
|
||||
build: false
|
10
build.sh
10
build.sh
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# https://github.com/millerjs/modelm
|
||||
# mount.cifs -o user=mopar,pass=,uid=1000,gid=1000,forceuid //mojave/mopar /mnt/mojave/
|
||||
|
||||
ssh mojave bash -s "$@" <<EOF
|
||||
. .profile
|
||||
cd /Users/mopar/IdeaProjects/rusty-keys
|
||||
cargo "\$@"
|
||||
EOF
|
@ -1,76 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# pressing all of these keys along with a number key representing the index of keymaps changes the layout
|
||||
# ie, in this case pressing both and 0 would go QWERTY, while both and 1 would go dvorak
|
||||
switch_layout_keys = ['LEFTSHIFT','RIGHTSHIFT']
|
||||
|
||||
# pressing QWERTY reverts to the index specified in revert_keymap_index for only the duration of the pressing
|
||||
# used so QWERTY shortcuts like Ctrl+C still work
|
||||
revert_default_key = 'LEFTCTRL'
|
||||
revert_keymap_index = 0
|
||||
|
||||
# this is the default index to use when the program first starts
|
||||
# in this case, 2 means modified Progammer Dvorak
|
||||
default_keymap_index = 2
|
||||
|
||||
# these are keys that caps_lock doesn't modify by default, but that you would like it to, affects all keymaps
|
||||
caps_lock_modify = """
|
||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, PSLS,PAST,PMNS,
|
||||
LBRC,RBRC,BSLS, P7, P8, P9,
|
||||
SCLN,QUOT, P4, P5, P6, PPLS,
|
||||
COMM,DOT, SLSH, P1, P2, P3,
|
||||
P0, PDOT
|
||||
"""
|
||||
|
||||
# these are the keymaps available, you can add as many as you want or re-order them, just be aware the mapping is
|
||||
# always done from the first one to all subsequent ones, so you probably want to leave QWERTY or similar up top
|
||||
keymaps = [
|
||||
# default key layout, QWERTY in this case
|
||||
"""
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS,
|
||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9,
|
||||
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS,
|
||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3,
|
||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT
|
||||
""",
|
||||
# Dvorak http://en.wikipedia.org/wiki/Dvorak_Simplified_Keyboard
|
||||
# https://www.moparisthebest.com/kbs/standard-dvorak-QwertySecondary.svg
|
||||
"""
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, LBRC,RBRC,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS,
|
||||
TAB, QUOT,COMM,DOT, P, Y, F, G, C, R, L, SLSH,EQL, BSLS, DEL, END, PGDN, P7, P8, P9,
|
||||
CAPS,A, O, E, U, I, D, H, T, N, S, MINS, ENT, P4, P5, P6, PPLS,
|
||||
LSFT,SCLN,Q, J, K, X, B, M, W, V, Z, RSFT, UP, P1, P2, P3,
|
||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT
|
||||
""",
|
||||
# Unix Dvorak Programmer Dvorak - for unix developers who are switching from dvorak
|
||||
# https://www.moparisthebest.com/kbs/programmer-dvorak-NoSecondary-NumpadStandard-NoSwap-StandardNums-SwapAt-SwapPipe.svg
|
||||
"""
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
^4:^GRV, ^7:1, LBRC:2, ^LBRC:3, ^RBRC:4, ^9:5, ^2:6, ^8:7, ^0:8, ^EQL:9, RBRC:0, ^1:^5, ^3:GRV, BSPC, INS, HOME,PGUP, NLCK, PSLS:^9, PAST:^0, PMNS:^4,
|
||||
TAB, QUOT, COMM, DOT, P, Y, F, G, C, R, L, SLSH, EQL:^6, ^BSLS:BSLS, DEL, END, PGDN, P7:^A, P8:^B, P9:^C,
|
||||
CAPS, A, O, E, U, I, D, H, T, N, S, MINS, ENT, P4:^D, P5:^E, P6:^F, PPLS:COMM,
|
||||
LSFT, SCLN, Q, J, K, X, B, M, W, V, Z, RSFT, UP, P1:EQL, P2:X, P3:^SCLN,
|
||||
LCTL, LGUI, LALT, SPC, RALT, RGUI, APP, RCTL, LEFT,DOWN,RGHT, P0:BSLS, PDOT:SCLN, PENT
|
||||
""",
|
||||
# Unix Dvorak Programmer Dvorak - for unix developers who are switching from dvorak - phone numpad
|
||||
# https://www.moparisthebest.com/kbs/programmer-dvorak-QwertySecondary-NumpadPhone-NoSwap-StandardNums-SwapAt-SwapPipe.svg
|
||||
"""
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
^4:^GRV, ^7:1, LBRC:2, ^LBRC:3, ^RBRC:4, ^9:5, ^2:6, ^8:7, ^0:8, ^EQL:9, RBRC:0, ^1:^5, ^3:GRV, BSPC, INS, HOME,PGUP, NLCK, PSLS:^9, PAST:^0, PMNS:^4,
|
||||
TAB, QUOT, COMM, DOT, P, Y, F, G, C, R, L, SLSH, EQL:^6, ^BSLS:BSLS, DEL, END, PGDN, P1:^A, P2:^B, P3:^C,
|
||||
CAPS, A, O, E, U, I, D, H, T, N, S, MINS, ENT, P4:^D, P5:^E, P6:^F, PPLS:COMM,
|
||||
LSFT, SCLN, Q, J, K, X, B, M, W, V, Z, RSFT, UP, P7:EQL, P8:X, P9:^SCLN,
|
||||
LCTL, LGUI, LALT, SPC, RALT, RGUI, APP, RCTL, LEFT,DOWN,RGHT, P0:BSLS, PDOT:SCLN, PENT
|
||||
""",
|
||||
# Programmer Dvorak http://www.kaufmann.no/roland/dvorak/
|
||||
# https://www.moparisthebest.com/kbs/programmer-dvorak-QwertySecondary-NumpadPhone-StrictSwap-StrictNums-StrictAt-StrictPipe.svg
|
||||
"""
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
^4:^GRV, ^7:^5, LBRC:7, ^LBRC:5, ^RBRC:3, ^9:1, EQL:9, ^8:0, ^0:2, ^EQL:4, RBRC:6, ^1:8, ^3:GRV, BSPC, INS, HOME,PGUP, NLCK, PSLS:^9, PAST:^0, PMNS:^4,
|
||||
TAB, SCLN, COMM, DOT, P, Y, F, G, C, R, L, SLSH, ^2:^6, BSLS, DEL, END, PGDN, P1:^A, P2:^B, P3:^C,
|
||||
CAPS, A, O, E, U, I, D, H, T, N, S, MINS, ENT, P4:^D, P5:^E, P6:^F, PPLS:COMM,
|
||||
LSFT, QUOT, Q, J, K, X, B, M, W, V, Z, RSFT, UP, P7:EQL, P8:X, P9:^SCLN,
|
||||
LCTL, LGUI, LALT, SPC, RALT, RGUI, APP, RCTL, LEFT,DOWN,RGHT, P0:BSLS, PDOT:SCLN, PENT
|
||||
""",
|
||||
]
|
16
keymap.toml
16
keymap.toml
@ -3,9 +3,9 @@
|
||||
# ie, in this case pressing both and 0 would go QWERTY, while both and 1 would go dvorak
|
||||
switch_layout_keys = ['LEFTSHIFT','RIGHTSHIFT']
|
||||
|
||||
# pressing QWERTY reverts to the index specified in revert_keymap_index for only the duration of the pressing
|
||||
# pressing any of these keys reverts to the index specified in revert_keymap_index for only the duration of the pressing
|
||||
# used so QWERTY shortcuts like Ctrl+C still work
|
||||
revert_default_key = 'LEFTCTRL'
|
||||
revert_default_keys = ['LCTL','LGUI','LALT']
|
||||
revert_keymap_index = 0
|
||||
|
||||
# this is the default index to use when the program first starts
|
||||
@ -17,31 +17,31 @@ default_keymap_index = 2
|
||||
keymaps = [
|
||||
# default key layout, QWERTY in this case
|
||||
"""
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,TAB,
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS,
|
||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9,
|
||||
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS,
|
||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3,
|
||||
LCTL,TAB,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT
|
||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT
|
||||
""",
|
||||
# Dvorak http://en.wikipedia.org/wiki/Dvorak_Simplified_Keyboard
|
||||
# https://www.moparisthebest.com/kbs/standard-dvorak-QwertySecondary.svg
|
||||
"""
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,TAB,
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, LBRC,RBRC,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS,
|
||||
TAB, QUOT,COMM,DOT, P, Y, F, G, C, R, L, SLSH,EQL, BSLS, DEL, END, PGDN, P7, P8, P9,
|
||||
CAPS,A, O, E, U, I, D, H, T, N, S, MINS, ENT, P4, P5, P6, PPLS,
|
||||
LSFT,SCLN,Q, J, K, X, B, M, W, V, Z, RSFT, UP, P1, P2, P3,
|
||||
LCTL,TAB,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT
|
||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT
|
||||
""",
|
||||
# Unix Programmer Dvorak - for unix developers who are switching from dvorak
|
||||
# https://www.moparisthebest.com/kbs/programmer-dvorak-NoSecondary-NumpadStandard-NoSwap-StandardNums-SwapAt-SwapPipe.svg
|
||||
"""
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,TAB,
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
*^4:*^GRV, *^7:*1, *LBRC:*2, *^LBRC:*3, *^RBRC:*4, *^9:*5, *^2:*6, *^8:*7, *^0:*8, *^EQL:*9, *RBRC:*0, *^1:*^5, *^3:*GRV, BSPC, INS, HOME,PGUP, NLCK, *PSLS:*^9, *PAST:*^0, *PMNS:*^4,
|
||||
TAB, *QUOT, *COMM, *DOT, P, Y, F, G, C, R, L, *SLSH, *EQL:*^6, *^BSLS, DEL, END, PGDN, *P7:^A, *P8:^B, *P9:^C,
|
||||
CAPS, A, O, E, U, I, D, H, T, N, S, *MINS, ENT, *P4:^D, *P5:^E, *P6:^F, *PPLS:*COMM,
|
||||
LSFT, *SCLN, Q, J, K, X, B, M, W, V, Z, RSFT, UP, *P1:*EQL, *P2:X, *P3:*^SCLN,
|
||||
LCTL, TAB, LALT, SPC, RALT, RGUI, APP, RCTL, LEFT,DOWN,RGHT, *P0:*BSLS, *PDOT:*SCLN, PENT
|
||||
LCTL, LGUI, LALT, SPC, RALT, RGUI, APP, RCTL, LEFT,DOWN,RGHT, *P0:*BSLS, *PDOT:*SCLN, PENT
|
||||
""",
|
||||
]
|
||||
|
179
keys.txt
179
keys.txt
@ -1,179 +0,0 @@
|
||||
Finished dev [unoptimized + debuginfo] target(s) in 0.07s
|
||||
Running `target/debug/rusty-keys`
|
||||
chosen config file: keymap.toml
|
||||
Created event tap...
|
||||
KEY 53
|
||||
KEY 18
|
||||
KEY 19
|
||||
KEY 20
|
||||
KEY 21
|
||||
KEY 23
|
||||
KEY 22
|
||||
KEY 26
|
||||
KEY 28
|
||||
KEY 25
|
||||
KEY 29
|
||||
KEY 27
|
||||
KEY 24
|
||||
KEY 51
|
||||
KEY 48
|
||||
KEY 12
|
||||
KEY 13
|
||||
KEY 14
|
||||
KEY 15
|
||||
KEY 17
|
||||
KEY 16
|
||||
KEY 32
|
||||
KEY 34
|
||||
KEY 31
|
||||
KEY 35
|
||||
KEY 33
|
||||
KEY 30
|
||||
KEY 36
|
||||
KEY 59
|
||||
KEY 59
|
||||
KEY 0
|
||||
KEY 1
|
||||
KEY 2
|
||||
KEY 3
|
||||
KEY 5
|
||||
KEY 4
|
||||
KEY 38
|
||||
KEY 40
|
||||
KEY 37
|
||||
KEY 41
|
||||
KEY 39
|
||||
KEY 50
|
||||
KEY 56
|
||||
KEY 56
|
||||
KEY 42
|
||||
KEY 6
|
||||
KEY 7
|
||||
KEY 8
|
||||
KEY 9
|
||||
KEY 11
|
||||
KEY 45
|
||||
KEY 46
|
||||
KEY 43
|
||||
KEY 47
|
||||
KEY 44
|
||||
KEY 60
|
||||
KEY 60
|
||||
KEY 67
|
||||
KEY 58
|
||||
KEY 58
|
||||
KEY 49
|
||||
KEY 122
|
||||
KEY 120
|
||||
KEY 99
|
||||
KEY 118
|
||||
KEY 96
|
||||
KEY 97
|
||||
KEY 98
|
||||
KEY 100
|
||||
KEY 101
|
||||
KEY 109
|
||||
KEY 71
|
||||
KEY 107
|
||||
KEY 89
|
||||
KEY 91
|
||||
KEY 92
|
||||
KEY 78
|
||||
KEY 107
|
||||
KEY 86
|
||||
KEY 87
|
||||
KEY 88
|
||||
KEY 69
|
||||
KEY 83
|
||||
KEY 84
|
||||
KEY 85
|
||||
KEY 82
|
||||
KEY 65
|
||||
KEY 10
|
||||
KEY 103
|
||||
KEY 111
|
||||
KEY 76
|
||||
KEY 62
|
||||
KEY 62
|
||||
KEY 75
|
||||
KEY 105
|
||||
KEY 61
|
||||
KEY 61
|
||||
KEY 113
|
||||
KEY 115
|
||||
KEY 126
|
||||
KEY 116
|
||||
KEY 123
|
||||
KEY 124
|
||||
KEY 119
|
||||
KEY 125
|
||||
KEY 121
|
||||
KEY 114
|
||||
KEY 117
|
||||
KEY 105
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 54
|
||||
KEY 113
|
||||
KEY 54
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 71
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 55
|
||||
KEY 55
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 55
|
||||
KEY 55
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 54
|
||||
KEY 54
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 113
|
||||
KEY 110
|
||||
KEY 71
|
120
out2.txt
120
out2.txt
@ -1,120 +0,0 @@
|
||||
KEY 0x0035
|
||||
KEY 0x0012
|
||||
KEY 0x0013
|
||||
KEY 0x0014
|
||||
KEY 0x0015
|
||||
KEY 0x0017
|
||||
KEY 0x0016
|
||||
KEY 0x001A
|
||||
KEY 0x001C
|
||||
KEY 0x0019
|
||||
KEY 0x001D
|
||||
KEY 0x001B
|
||||
KEY 0x0018
|
||||
KEY 0x0033
|
||||
KEY 0x0030
|
||||
KEY 0x000C
|
||||
KEY 0x000D
|
||||
KEY 0x000E
|
||||
KEY 0x000F
|
||||
KEY 0x0011
|
||||
KEY 0x0010
|
||||
KEY 0x0020
|
||||
KEY 0x0022
|
||||
KEY 0x001F
|
||||
KEY 0x0023
|
||||
KEY 0x0021
|
||||
KEY 0x001E
|
||||
KEY 0x0024
|
||||
KEY 0x003B
|
||||
KEY 0x003B
|
||||
KEY 0x0000
|
||||
KEY 0x0001
|
||||
KEY 0x0002
|
||||
KEY 0x0003
|
||||
KEY 0x0005
|
||||
KEY 0x0004
|
||||
KEY 0x0026
|
||||
KEY 0x0028
|
||||
KEY 0x0025
|
||||
KEY 0x0029
|
||||
KEY 0x0027
|
||||
KEY 0x0032
|
||||
KEY 0x0038
|
||||
KEY 0x0038
|
||||
KEY 0x002A
|
||||
KEY 0x0006
|
||||
KEY 0x0007
|
||||
KEY 0x0008
|
||||
KEY 0x0009
|
||||
KEY 0x000B
|
||||
KEY 0x002D
|
||||
KEY 0x002E
|
||||
KEY 0x002B
|
||||
KEY 0x002F
|
||||
KEY 0x002C
|
||||
KEY 0x003C
|
||||
KEY 0x003C
|
||||
KEY 0x0043
|
||||
KEY 0x003A
|
||||
KEY 0x003A
|
||||
KEY 0x0031
|
||||
KEY 0x007A
|
||||
KEY 0x0078
|
||||
KEY 0x0063
|
||||
KEY 0x0076
|
||||
KEY 0x0060
|
||||
KEY 0x0061
|
||||
KEY 0x0062
|
||||
KEY 0x0064
|
||||
KEY 0x0065
|
||||
KEY 0x006D
|
||||
KEY 0x0047
|
||||
KEY 0x006B
|
||||
KEY 0x006B
|
||||
KEY 0x0059
|
||||
KEY 0x005B
|
||||
KEY 0x005C
|
||||
KEY 0x004E
|
||||
KEY 0x0056
|
||||
KEY 0x0057
|
||||
KEY 0x0058
|
||||
KEY 0x0045
|
||||
KEY 0x0053
|
||||
KEY 0x0054
|
||||
KEY 0x0055
|
||||
KEY 0x0052
|
||||
KEY 0x0041
|
||||
KEY 0x000A
|
||||
KEY 0x0067
|
||||
KEY 0x006F
|
||||
KEY 0x004C
|
||||
KEY 0x003E
|
||||
KEY 0x003E
|
||||
KEY 0x004B
|
||||
KEY 0x0069
|
||||
KEY 0x003D
|
||||
KEY 0x003D
|
||||
KEY 0x0071
|
||||
KEY 0x0073
|
||||
KEY 0x007E
|
||||
KEY 0x0074
|
||||
KEY 0x007B
|
||||
KEY 0x007C
|
||||
KEY 0x0077
|
||||
KEY 0x007D
|
||||
KEY 0x0079
|
||||
KEY 0x0072
|
||||
KEY 0x0075
|
||||
KEY 0x0069
|
||||
KEY 0x0047
|
||||
KEY 0x0036
|
||||
KEY 0x0036
|
||||
KEY 0x0037
|
||||
KEY 0x0037
|
||||
KEY 0x0037
|
||||
KEY 0x0037
|
||||
KEY 0x0036
|
||||
KEY 0x0036
|
||||
KEY 0x006E
|
||||
KEY 0x0047
|
59
src/error.rs
59
src/error.rs
@ -3,15 +3,9 @@ use std::error;
|
||||
use std::ffi;
|
||||
use std::io;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use std::sync::mpsc;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use nix;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use libc;
|
||||
|
||||
/// UInput error.
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
@ -23,15 +17,17 @@ pub enum Error {
|
||||
Nul(ffi::NulError),
|
||||
|
||||
Io(io::Error),
|
||||
|
||||
#[cfg(feature = "toml_serde")]
|
||||
Toml(toml::de::Error),
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
Send(mpsc::SendError<libc::input_event>),
|
||||
|
||||
/// The uinput file could not be found.
|
||||
NotFound,
|
||||
|
||||
NotAKeyboard,
|
||||
|
||||
/// error reading input_event
|
||||
ShortRead,
|
||||
|
||||
/// epoll already added
|
||||
EpollAlreadyAdded,
|
||||
}
|
||||
|
||||
impl From<ffi::NulError> for Error {
|
||||
@ -53,41 +49,26 @@ impl From<io::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
impl From<mpsc::SendError<libc::input_event>> for Error {
|
||||
fn from(value: mpsc::SendError<libc::input_event>) -> Self {
|
||||
Error::Send(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
f.write_str(error::Error::description(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
match self {
|
||||
#[cfg(target_os = "linux")]
|
||||
&Error::Nix(ref err) =>
|
||||
err.description(),
|
||||
&Error::Nix(ref err) => err.fmt(f),
|
||||
|
||||
&Error::Nul(ref err) =>
|
||||
err.description(),
|
||||
&Error::Nul(ref err) => err.fmt(f),
|
||||
|
||||
&Error::Io(ref err) =>
|
||||
err.description(),
|
||||
&Error::Io(ref err) => err.fmt(f),
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
&Error::Send(ref err) =>
|
||||
err.description(),
|
||||
#[cfg(feature = "toml_serde")]
|
||||
&Error::Toml(ref err) => err.fmt(f),
|
||||
|
||||
&Error::NotAKeyboard => f.write_str("This device file is not a keyboard"),
|
||||
|
||||
&Error::NotFound =>
|
||||
"Device not found.",
|
||||
|
||||
&Error::ShortRead =>
|
||||
"Error while reading from device file.",
|
||||
&Error::ShortRead => f.write_str("Error while reading from device file."),
|
||||
|
||||
&Error::EpollAlreadyAdded => f.write_str("epoll already added, delete first"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {}
|
||||
|
300
src/keymapper.rs
300
src/keymapper.rs
@ -1,11 +1,12 @@
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use crate::{Error, Result};
|
||||
#[cfg(feature = "toml_serde")]
|
||||
use std::path::Path;
|
||||
|
||||
use crate::Result;
|
||||
|
||||
const INVERT_KEY_FLAG: char = '^';
|
||||
const CAPS_MODIFY_KEY_FLAG: char = '*';
|
||||
@ -14,7 +15,7 @@ const HALF_KEY_SEPARATOR: char = ':';
|
||||
// nightly only...
|
||||
//pub trait KeyCode = Into<usize> + TryFrom<usize> + Copy + Clone + Eq + Hash + Default + 'static;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum KeyState {
|
||||
DOWN,
|
||||
UP,
|
||||
@ -31,7 +32,7 @@ pub trait KeyEvent<T>
|
||||
|
||||
pub trait Keyboard<T, E, R = ()>
|
||||
where
|
||||
T: Into<usize>,
|
||||
T: Into<usize> + Copy,
|
||||
E: KeyEvent<T>,
|
||||
{
|
||||
fn send(&self, event: &mut E) -> Result<R>;
|
||||
@ -42,11 +43,52 @@ pub trait Keyboard<T, E, R = ()>
|
||||
fn right_shift_code(&self) -> T;
|
||||
fn caps_lock_code(&self) -> T;
|
||||
fn block_key(&self) -> Result<R>;
|
||||
|
||||
fn send_half_inverted_key(&self, half_inverted_key: &HalfInvertedKey<T>, event: &mut E, left_shift: bool, right_shift: bool, caps_lock: bool) -> Result<R> {
|
||||
let value = event.value();
|
||||
let mut invert_shift = half_inverted_key.invert_shift;
|
||||
if value == KeyState::DOWN {
|
||||
if caps_lock && half_inverted_key.capslock_nomodify {
|
||||
invert_shift = !invert_shift;
|
||||
}
|
||||
if invert_shift {
|
||||
let (shift_code, up_not_down) = if left_shift {
|
||||
(self.left_shift_code(), true)
|
||||
} else if right_shift {
|
||||
(self.right_shift_code(), true)
|
||||
} else {
|
||||
(self.left_shift_code(), false)
|
||||
};
|
||||
self.send_mod_code_value(shift_code, up_not_down, event)?;
|
||||
// SYN_REPORT after, then key, then key's SYN_REPORT
|
||||
self.synchronize()?;
|
||||
}
|
||||
}
|
||||
let ret = self.send_mod_code(half_inverted_key.code, event)?;
|
||||
if value == KeyState::UP {
|
||||
if caps_lock && half_inverted_key.capslock_nomodify {
|
||||
invert_shift = !invert_shift;
|
||||
}
|
||||
if invert_shift {
|
||||
let (shift_code, up_not_down) = if left_shift {
|
||||
(self.left_shift_code(), false)
|
||||
} else if right_shift {
|
||||
(self.right_shift_code(), false)
|
||||
} else {
|
||||
(self.left_shift_code(), true)
|
||||
};
|
||||
// SYN_REPORT first after key, then shift, then key's SYN_REPORT which will be used for shift's
|
||||
self.synchronize()?;
|
||||
self.send_mod_code_value(shift_code, up_not_down, event)?;
|
||||
}
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait KeyMapper<K, T, E, R>
|
||||
where
|
||||
T: Into<usize>,
|
||||
T: Into<usize> + Copy,
|
||||
E: KeyEvent<T>,
|
||||
K: Keyboard<T, E, R>,
|
||||
{
|
||||
@ -63,7 +105,7 @@ pub struct KeyMaps<K, T, E, R = ()>
|
||||
keymap_index_keys: HashMap<T, usize>,
|
||||
switch_layout_keys: Vec<usize>,
|
||||
key_state: [bool; KEY_MAX],
|
||||
revert_default_key: T,
|
||||
revert_default_keys: Vec<T>,
|
||||
revert_keymap_index: usize,
|
||||
// above do not change, below does
|
||||
chosen_keymap_index: usize,
|
||||
@ -120,6 +162,7 @@ impl<K, T, E, R> KeyMaps<K, T, E, R>
|
||||
E: KeyEvent<T>,
|
||||
K: Keyboard<T, E, R>,
|
||||
{
|
||||
#[cfg(feature = "toml_serde")]
|
||||
pub fn from_cfg<P: AsRef<Path>>(key_map: &HashMap<&'static str, T>, path: P) -> KeyMaps<K, T, E, R> {
|
||||
let key_map_config = parse_cfg(path).expect("provided config cannot be found/parsed");
|
||||
KeyMaps::new(key_map, key_map_config)
|
||||
@ -147,8 +190,14 @@ impl<K, T, E, R> KeyMaps<K, T, E, R>
|
||||
let mut keymap = KeyMap::new();
|
||||
let mut i: usize = 0;
|
||||
for key_code in v {
|
||||
// todo: if these are the same, do Noop instead
|
||||
keymap.map(base_keymap[i], key_code);
|
||||
// if it's a direct key and it's the same, don't do any mapping
|
||||
if let Key::Direct(key) = key_code {
|
||||
if base_keymap[i] != key {
|
||||
keymap.map(base_keymap[i], key_code);
|
||||
}
|
||||
} else {
|
||||
keymap.map(base_keymap[i], key_code);
|
||||
}
|
||||
i = i + 1;
|
||||
if i > base_keymap.len() {
|
||||
panic!("all keymaps must be the same length, keymap index 0 length: {}, index {} length: {},", base_keymap.len(), x, i);
|
||||
@ -161,7 +210,9 @@ impl<K, T, E, R> KeyMaps<K, T, E, R>
|
||||
let mut keymap = CodeKeyMap::new();
|
||||
let mut i: usize = 0;
|
||||
for key_code in v {
|
||||
keymap.map(base_keymap[i], key_code);
|
||||
if base_keymap[i] != key_code {
|
||||
keymap.map(base_keymap[i], key_code);
|
||||
}
|
||||
i = i + 1;
|
||||
if i > base_keymap.len() {
|
||||
panic!("all keymaps must be the same length, keymap index 0 length: {}, index {} length: {},", base_keymap.len(), x, i);
|
||||
@ -173,13 +224,27 @@ impl<K, T, E, R> KeyMaps<K, T, E, R>
|
||||
//println!("keymaps: {:?}", keymaps);
|
||||
//println!("keymap_index_keys: {:?}", keymap_index_keys);
|
||||
|
||||
let mut revert_default_keys = Vec::new();
|
||||
if config.revert_default_key.is_some() {
|
||||
revert_default_keys.push(parse_key(key_map, &config.revert_default_key.unwrap()));
|
||||
}
|
||||
if config.revert_default_keys.is_some() {
|
||||
for revert_default_key in config.revert_default_keys.unwrap() {
|
||||
let revert_default_key = parse_key(key_map, &revert_default_key);
|
||||
if !revert_default_keys.contains(&revert_default_key) {
|
||||
revert_default_keys.push(revert_default_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
// revert_default_keys may be empty, but that's ok
|
||||
|
||||
KeyMaps {
|
||||
keymaps: keymaps,
|
||||
keymap_index_keys: keymap_index_keys,
|
||||
switch_layout_keys: config.switch_layout_keys.iter().map(|k| parse_key(key_map, k).into()).collect(),
|
||||
key_state: [false; KEY_MAX],
|
||||
// todo: detect key state? at least CAPSLOCK...
|
||||
revert_default_key: parse_key(key_map, &config.revert_default_key),
|
||||
revert_default_keys,
|
||||
revert_keymap_index: config.revert_keymap_index,
|
||||
chosen_keymap_index: config.default_keymap_index,
|
||||
current_keymap_index: config.default_keymap_index,
|
||||
@ -190,7 +255,6 @@ impl<K, T, E, R> KeyMaps<K, T, E, R>
|
||||
//impl KeyMapper for KeyMaps {
|
||||
//impl KeyMaps {
|
||||
pub fn send_event(&mut self, mut event: &mut E, device: &K) -> Result<R> {
|
||||
//println!("type: {} code: {} value: {}", event.type_, event.code, event.value);
|
||||
let value = event.value();
|
||||
if value != KeyState::OTHER {
|
||||
// todo: index check here...
|
||||
@ -199,7 +263,12 @@ pub fn send_event(&mut self, mut event: &mut E, device: &K) -> Result<R> {
|
||||
self.key_state[device.caps_lock_code().into()] = !self.key_state[device.caps_lock_code().into()];
|
||||
}
|
||||
} else {
|
||||
self.key_state[event.code().into()] = value == KeyState::DOWN;
|
||||
let idx = event.code().into();
|
||||
if idx >= KEY_MAX {
|
||||
// oh well, send it directly then
|
||||
return device.send(event);
|
||||
}
|
||||
self.key_state[idx] = value == KeyState::DOWN;
|
||||
}
|
||||
let mut switch_layout_keys_pressed = true;
|
||||
for layout_switch_key in self.switch_layout_keys.iter_mut() {
|
||||
@ -217,11 +286,27 @@ pub fn send_event(&mut self, mut event: &mut E, device: &K) -> Result<R> {
|
||||
return device.block_key(); // we don't want to also send this keypress, so bail
|
||||
}
|
||||
}
|
||||
if event.code() == self.revert_default_key {
|
||||
if self.revert_default_keys.contains(&event.code()) {
|
||||
match value {
|
||||
// todo: ctrl+c will get c stuck because code c value 1 will be sent, but then we'll let go of ctrl, and code j value 0 is sent, so c is never released... fix that...
|
||||
KeyState::DOWN => self.current_keymap_index = self.revert_keymap_index,
|
||||
KeyState::UP => self.current_keymap_index = self.chosen_keymap_index,
|
||||
KeyState::DOWN => {
|
||||
// todo: should we release currently held keys and then press them back down here, kinda the opposite of below? not for now...
|
||||
self.current_keymap_index = self.revert_keymap_index
|
||||
},
|
||||
KeyState::UP => {
|
||||
self.current_keymap_index = self.chosen_keymap_index;
|
||||
#[cfg(not(target_os = "macos"))] {
|
||||
// need to release all currently held down keys, except this one, otherwise ctrl+c will get c stuck because code c value 1 will be sent, but then we'll let go of ctrl, and code j value 0 is sent, so c is never released
|
||||
let orig_code = event.code();
|
||||
for (idx, key_down) in self.key_state.iter_mut().enumerate() {
|
||||
if *key_down {
|
||||
device.send_mod_code_value(T::try_from(idx).unwrap_or_else(|_| panic!("cannot convert from usize to T ????")), true, event)?;
|
||||
*key_down = false;
|
||||
}
|
||||
}
|
||||
// todo: seems like we should not send this here, and instead just set the original code back, and pass it through the keymaps?
|
||||
return device.send_mod_code_value(orig_code, true, event)
|
||||
}
|
||||
},
|
||||
_ => () // do nothing for 2
|
||||
}
|
||||
}
|
||||
@ -234,42 +319,16 @@ pub fn send_event(&mut self, mut event: &mut E, device: &K) -> Result<R> {
|
||||
const KEY_MAX: usize = 249;
|
||||
|
||||
struct KeyMap<T: Into<usize> + Copy> {
|
||||
//keymap: Vec<Key>,
|
||||
keymap: [Key<T>; KEY_MAX],
|
||||
}
|
||||
|
||||
impl<T: Into<usize> + Copy> KeyMap<T> {
|
||||
pub fn new() -> Self {
|
||||
//let mut keymap = [0u16; KEY_MAX];
|
||||
//let mut keymap : [Box<KeyMapper>; KEY_MAX] = [Box::new(NOOP); KEY_MAX];
|
||||
//let mut keymap : [Box<KeyMapper>; KEY_MAX] = [Box::new(0u16); KEY_MAX];
|
||||
let keymap: [Key<T>; KEY_MAX] = [Key::Noop; KEY_MAX];
|
||||
/*
|
||||
let mut keymap: Vec<Key> = Vec::with_capacity(KEY_MAX);
|
||||
#[allow(unused_variables)]
|
||||
for x in 0..KEY_MAX {
|
||||
keymap.push(Key::Noop);
|
||||
}
|
||||
*/
|
||||
// which is rustier
|
||||
/*
|
||||
for x in 0..KEY_MAX {
|
||||
keymap[x as usize] = x as u16;
|
||||
}
|
||||
for (x, v) in keymap.iter_mut().enumerate() {
|
||||
*v = x as u16;
|
||||
}
|
||||
*/
|
||||
//println!("keymap: {:?}", &keymap[..]);
|
||||
KeyMap {
|
||||
keymap: keymap
|
||||
keymap: [Key::Noop; KEY_MAX]
|
||||
}
|
||||
}
|
||||
/*
|
||||
pub fn map(&mut self, from : u16, to: u16) {
|
||||
self.keymap[from as usize] = to;
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn map(&mut self, from: T, to: Key<T>) {
|
||||
self.keymap[from.into()] = to;
|
||||
}
|
||||
@ -287,25 +346,18 @@ impl<K, T, E, R> KeyMapper<K, T, E, R> for KeyMap<T>
|
||||
}
|
||||
|
||||
struct CodeKeyMap<T: Into<usize> + TryFrom<usize> + Copy + Default> {
|
||||
//keymap: Vec<Key>,
|
||||
keymap: [T; KEY_MAX],
|
||||
}
|
||||
|
||||
impl<T: Into<usize> + TryFrom<usize> + Copy + Default> CodeKeyMap<T> {
|
||||
pub fn new() -> Self {
|
||||
let mut keymap = [T::default(); KEY_MAX];
|
||||
// which is rustier
|
||||
/*
|
||||
for x in 0..KEY_MAX {
|
||||
keymap[x as usize] = x as u16;
|
||||
}
|
||||
*/
|
||||
for (x, v) in keymap.iter_mut().enumerate() {
|
||||
*v = T::try_from(x).unwrap_or_else(|_| panic!("cannot convert from usize to T ????"));
|
||||
}
|
||||
//println!("keymap: {:?}", &keymap[..]);
|
||||
CodeKeyMap {
|
||||
keymap: keymap
|
||||
keymap
|
||||
}
|
||||
}
|
||||
|
||||
@ -328,61 +380,15 @@ impl<K, T, E, R> KeyMapper<K, T, E, R> for CodeKeyMap<T>
|
||||
|
||||
// todo:capslock_nomodify is like a whole-key thing, not a half-key thing, split code/invert_shift to own struct, send into send_key from *InvertedKey, maybe anyway, consider it, maybe 1 char for whole key and another for half?
|
||||
#[derive(Clone, Copy)]
|
||||
struct HalfInvertedKey<T: Clone + Copy> {
|
||||
code: T,
|
||||
pub struct HalfInvertedKey<T: Clone + Copy> {
|
||||
pub code: T,
|
||||
// code this is describing
|
||||
invert_shift: bool,
|
||||
pub invert_shift: bool,
|
||||
// true to invert shift for this code
|
||||
capslock_nomodify: bool,
|
||||
pub capslock_nomodify: bool,
|
||||
// true means capslock does not normally modify this, but you would like it to
|
||||
}
|
||||
|
||||
fn send_half_inverted_key<K, T, E, R>(half_inverted_key: &HalfInvertedKey<T>, event: &mut E, device: &K, left_shift: bool, right_shift: bool, caps_lock: bool) -> Result<R>
|
||||
where
|
||||
T: Into<usize> + Clone + Copy,
|
||||
E: KeyEvent<T>,
|
||||
K: Keyboard<T, E, R>,
|
||||
{
|
||||
let value = event.value();
|
||||
let mut invert_shift = half_inverted_key.invert_shift;
|
||||
if value == KeyState::DOWN {
|
||||
if caps_lock && half_inverted_key.capslock_nomodify {
|
||||
invert_shift = !invert_shift;
|
||||
}
|
||||
if invert_shift {
|
||||
let (shift_code, up_not_down) = if left_shift {
|
||||
(device.left_shift_code(), true)
|
||||
} else if right_shift {
|
||||
(device.right_shift_code(), true)
|
||||
} else {
|
||||
(device.left_shift_code(), false)
|
||||
};
|
||||
device.send_mod_code_value(shift_code, up_not_down, event)?;
|
||||
// SYN_REPORT after, then key, then key's SYN_REPORT
|
||||
device.synchronize()?;
|
||||
}
|
||||
}
|
||||
let ret = device.send_mod_code(half_inverted_key.code, event)?;
|
||||
if value == KeyState::UP {
|
||||
if caps_lock && half_inverted_key.capslock_nomodify {
|
||||
invert_shift = !invert_shift;
|
||||
}
|
||||
if invert_shift {
|
||||
let (shift_code, up_not_down) = if left_shift {
|
||||
(device.left_shift_code(), false)
|
||||
} else if right_shift {
|
||||
(device.right_shift_code(), false)
|
||||
} else {
|
||||
(device.left_shift_code(), true)
|
||||
};
|
||||
// SYN_REPORT first after key, then shift, then key's SYN_REPORT which will be used for shift's
|
||||
device.synchronize()?;
|
||||
device.send_mod_code_value(shift_code, up_not_down, event)?;
|
||||
}
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
impl<K, T, E, R> KeyMapper<K, T, E, R> for HalfInvertedKey<T>
|
||||
where
|
||||
T: Into<usize> + Clone + Copy,
|
||||
@ -393,7 +399,7 @@ impl<K, T, E, R> KeyMapper<K, T, E, R> for HalfInvertedKey<T>
|
||||
let left_shift = key_state[device.left_shift_code().into()];
|
||||
let right_shift = key_state[device.right_shift_code().into()];
|
||||
let caps_lock = key_state[device.caps_lock_code().into()];
|
||||
send_half_inverted_key(self, event, device, left_shift, right_shift, caps_lock)
|
||||
device.send_half_inverted_key(self, event, left_shift, right_shift, caps_lock)
|
||||
}
|
||||
}
|
||||
|
||||
@ -430,34 +436,96 @@ impl<K, T, E, R> KeyMapper<K, T, E, R> for Key<T>
|
||||
let right_shift = key_state[device.right_shift_code().into()];
|
||||
let caps_lock = key_state[device.caps_lock_code().into()];
|
||||
if caps_lock != (left_shift || right_shift) {
|
||||
send_half_inverted_key(shift_half, event, device, left_shift, right_shift, caps_lock)
|
||||
device.send_half_inverted_key(shift_half, event, left_shift, right_shift, caps_lock)
|
||||
} else {
|
||||
send_half_inverted_key(noshift_half, event, device, left_shift, right_shift, caps_lock)
|
||||
device.send_half_inverted_key(noshift_half, event, left_shift, right_shift, caps_lock)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use std::path::Path;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[cfg(feature = "toml_serde")]
|
||||
#[derive(serde::Deserialize, Debug)]
|
||||
pub struct KeymapConfig {
|
||||
switch_layout_keys: Vec<String>,
|
||||
revert_default_key: String,
|
||||
revert_default_key: Option<String>,
|
||||
revert_default_keys: Option<Vec<String>>,
|
||||
revert_keymap_index: usize,
|
||||
default_keymap_index: usize,
|
||||
keymaps: Vec<String>
|
||||
}
|
||||
|
||||
#[cfg(feature = "toml_serde")]
|
||||
fn parse_cfg<P: AsRef<Path>>(path: P) -> Result<KeymapConfig> {
|
||||
let mut f = File::open(path)?;
|
||||
use std::io::Read;
|
||||
let mut f = std::fs::File::open(path)?;
|
||||
let mut input = String::new();
|
||||
f.read_to_string(&mut input)?;
|
||||
//toml::from_str(&input)?
|
||||
match toml::from_str(&input) {
|
||||
Ok(toml) => Ok(toml),
|
||||
Err(_) => Err(Error::NotFound) // todo: something better
|
||||
toml::from_str(&input).map_err(|e| crate::Error::Toml(e))
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "toml_serde"))]
|
||||
#[derive(Debug)]
|
||||
pub struct KeymapConfig {
|
||||
switch_layout_keys: Vec<&'static str>,
|
||||
revert_default_key: Option<&'static str>,
|
||||
revert_default_keys: Option<Vec<&'static str>>,
|
||||
revert_keymap_index: usize,
|
||||
default_keymap_index: usize,
|
||||
keymaps: Vec<&'static str>
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "toml_serde"))]
|
||||
impl Default for KeymapConfig {
|
||||
fn default() -> Self {
|
||||
KeymapConfig {
|
||||
switch_layout_keys: vec!["LEFTSHIFT", "RIGHTSHIFT"],
|
||||
|
||||
// pressing any of these keys reverts to the index specified in revert_keymap_index for only the duration of the pressing
|
||||
// used so QWERTY shortcuts like Ctrl+C still work
|
||||
revert_default_keys: Some(vec!["LCTL", "LGUI", "LALT"]),
|
||||
revert_keymap_index: 0,
|
||||
|
||||
// this is the default index to use when the program first starts
|
||||
// in this case, 2 means Unix Programmer Dvorak
|
||||
default_keymap_index: 2,
|
||||
|
||||
// these are the keymaps available, you can add as many as you want or re-order them, just be aware the mapping is
|
||||
// always done from the first one to all subsequent ones, so you probably want to leave QWERTY or similar up top
|
||||
keymaps: vec![
|
||||
// default key layout, QWERTY in this case
|
||||
r###"
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS,
|
||||
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, END, PGDN, P7, P8, P9,
|
||||
CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, P4, P5, P6, PPLS,
|
||||
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RSFT, UP, P1, P2, P3,
|
||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT
|
||||
"###,
|
||||
// Dvorak http://en.wikipedia.org/wiki/Dvorak_Simplified_Keyboard
|
||||
// https://www.moparisthebest.com/kbs/standard-dvorak-QwertySecondary.svg
|
||||
r###"
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, LBRC,RBRC,BSPC, INS, HOME,PGUP, NLCK,PSLS,PAST,PMNS,
|
||||
TAB, QUOT,COMM,DOT, P, Y, F, G, C, R, L, SLSH,EQL, BSLS, DEL, END, PGDN, P7, P8, P9,
|
||||
CAPS,A, O, E, U, I, D, H, T, N, S, MINS, ENT, P4, P5, P6, PPLS,
|
||||
LSFT,SCLN,Q, J, K, X, B, M, W, V, Z, RSFT, UP, P1, P2, P3,
|
||||
LCTL,LGUI,LALT, SPC, RALT,RGUI,APP, RCTL, LEFT,DOWN,RGHT, P0, PDOT,PENT
|
||||
"###,
|
||||
// Unix Programmer Dvorak - for unix developers who are switching from dvorak
|
||||
// https://www.moparisthebest.com/kbs/programmer-dvorak-NoSecondary-NumpadStandard-NoSwap-StandardNums-SwapAt-SwapPipe.svg
|
||||
r###"
|
||||
ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK,
|
||||
*^4:*^GRV, *^7:*1, *LBRC:*2, *^LBRC:*3, *^RBRC:*4, *^9:*5, *^2:*6, *^8:*7, *^0:*8, *^EQL:*9, *RBRC:*0, *^1:*^5, *^3:*GRV, BSPC, INS, HOME,PGUP, NLCK, *PSLS:*^9, *PAST:*^0, *PMNS:*^4,
|
||||
TAB, *QUOT, *COMM, *DOT, P, Y, F, G, C, R, L, *SLSH, *EQL:*^6, *^BSLS, DEL, END, PGDN, *P7:^A, *P8:^B, *P9:^C,
|
||||
CAPS, A, O, E, U, I, D, H, T, N, S, *MINS, ENT, *P4:^D, *P5:^E, *P6:^F, *PPLS:*COMM,
|
||||
LSFT, *SCLN, Q, J, K, X, B, M, W, V, Z, RSFT, UP, *P1:*EQL, *P2:X, *P3:*^SCLN,
|
||||
LCTL, LGUI, LALT, SPC, RALT, RGUI, APP, RCTL, LEFT,DOWN,RGHT, *P0:*BSLS, *PDOT:*SCLN, PENT
|
||||
"###,
|
||||
],
|
||||
revert_default_key: None, // use revert_default_keys instead
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#![recursion_limit = "1000"]
|
||||
|
||||
pub const NAME: &'static str = env!("CARGO_PKG_NAME");
|
||||
pub const VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
pub mod error;
|
||||
@ -15,7 +16,6 @@ mod windows;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use windows::*;
|
||||
|
||||
/*
|
||||
#[cfg(target_os = "linux")]
|
||||
mod linux;
|
||||
#[cfg(target_os = "linux")]
|
||||
@ -25,7 +25,3 @@ pub use linux::*;
|
||||
mod macos;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use macos::*;
|
||||
*/
|
||||
|
||||
mod macos;
|
||||
pub use macos::*;
|
@ -2,11 +2,42 @@ use std::path::Path;
|
||||
use std::{mem, slice};
|
||||
use std::ffi::CString;
|
||||
use libc::c_int;
|
||||
use nix::{self, fcntl, unistd, errno::Errno};
|
||||
use nix::{self, fcntl, unistd, ioctl_write_ptr, ioctl_none};
|
||||
use nix::sys::stat;
|
||||
use uinput_sys::*;
|
||||
use crate::{Result as Res, Device};
|
||||
use crate::{Result, Device};
|
||||
use std::collections::hash_map::Values;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
use crate::linux::device::codes::*;
|
||||
|
||||
ioctl_write_ptr!(ui_set_evbit, b'U', 100, c_int);
|
||||
ioctl_write_ptr!(ui_set_keybit, b'U', 101, c_int);
|
||||
ioctl_none!(ui_dev_create, b'U', 1);
|
||||
|
||||
pub const UINPUT_MAX_NAME_SIZE: c_int = 80;
|
||||
pub const ABS_MAX: c_int = 0x3f;
|
||||
pub const ABS_CNT: c_int = ABS_MAX + 1;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct input_id {
|
||||
pub bustype: u16,
|
||||
pub vendor: u16,
|
||||
pub product: u16,
|
||||
pub version: u16,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct uinput_user_dev {
|
||||
pub name: [c_char; UINPUT_MAX_NAME_SIZE as usize],
|
||||
pub id: input_id,
|
||||
|
||||
pub ff_effects_max: u32,
|
||||
pub absmax: [i32; ABS_CNT as usize],
|
||||
pub absmin: [i32; ABS_CNT as usize],
|
||||
pub absfuzz: [i32; ABS_CNT as usize],
|
||||
pub absflat: [i32; ABS_CNT as usize],
|
||||
}
|
||||
|
||||
/// Device builder.
|
||||
pub struct Builder {
|
||||
@ -17,7 +48,7 @@ pub struct Builder {
|
||||
|
||||
impl Builder {
|
||||
/// Create a builder from the specified path.
|
||||
pub fn open<P: AsRef<Path>>(path: P) -> Res<Self> {
|
||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
|
||||
Ok(Builder {
|
||||
fd: fcntl::open(path.as_ref(), fcntl::OFlag::O_WRONLY | fcntl::OFlag::O_NONBLOCK, stat::Mode::empty())?,
|
||||
def: unsafe { mem::zeroed() },
|
||||
@ -26,17 +57,17 @@ impl Builder {
|
||||
}
|
||||
|
||||
/// Create a builder from `/dev/uinput`.
|
||||
pub fn default() -> Res<Self> {
|
||||
pub fn default() -> Result<Self> {
|
||||
Builder::open("/dev/uinput")
|
||||
}
|
||||
|
||||
/// Set the name.
|
||||
pub fn name<T: AsRef<str>>(mut self, value: T) -> Res<Self> {
|
||||
pub fn name<T: AsRef<str>>(mut self, value: T) -> Result<Self> {
|
||||
let string = CString::new(value.as_ref())?;
|
||||
let bytes = string.as_bytes_with_nul();
|
||||
|
||||
if bytes.len() > UINPUT_MAX_NAME_SIZE as usize {
|
||||
Err(nix::Error::from_errno(Errno::EINVAL))?;
|
||||
Err(nix::Error::EINVAL)?;
|
||||
}
|
||||
|
||||
(&mut self.def.name)[..bytes.len()]
|
||||
@ -69,164 +100,18 @@ impl Builder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn event(mut self, key_codes: Values<&str, u16>) -> Res<Self> {
|
||||
pub fn event(mut self, key_codes: Values<&str, u16>) -> Result<Self> {
|
||||
self.abs = None;
|
||||
//let test_ev_key : c_int = EV_KEY as c_int;
|
||||
unsafe {
|
||||
//try!(Errno::result(ui_set_evbit(self.fd, EV_KEY)));
|
||||
//try!(Errno::result(ui_set_keybit(self.fd, KEY_H)));
|
||||
Errno::result(ui_set_evbit(self.fd, EV_KEY as i32))?;
|
||||
//ui_set_keybit(self.fd, KEY_H as *const c_int)?;
|
||||
ui_set_evbit(self.fd, EV_KEY as *const c_int)?;
|
||||
|
||||
for key_code in key_codes {
|
||||
Errno::result(ui_set_keybit(self.fd, *key_code as i32))?;
|
||||
ui_set_keybit(self.fd, *key_code as *const c_int)?;
|
||||
}
|
||||
//try!(ui_set_keybit(self.fd, &KEY_H));
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
/*
|
||||
/// Enable the given event.
|
||||
pub fn event<T: Into<Event>>(mut self, value: T) -> Res<Self> {
|
||||
self.abs = None;
|
||||
|
||||
match value.into() {
|
||||
Event::All => {
|
||||
try!(self.event(Event::Keyboard(event::Keyboard::All)))
|
||||
.event(Event::Controller(event::Controller::All))
|
||||
}
|
||||
|
||||
Event::Keyboard(value) => {
|
||||
match value {
|
||||
event::Keyboard::All => {
|
||||
let mut builder = self;
|
||||
|
||||
for item in event::keyboard::Key::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
for item in event::keyboard::KeyPad::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
for item in event::keyboard::Misc::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
for item in event::keyboard::InputAssist::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
for item in event::keyboard::Function::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
for item in event::keyboard::Braille::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
for item in event::keyboard::Numeric::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
for item in event::keyboard::TouchPad::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
for item in event::keyboard::Camera::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
for item in event::keyboard::Attendant::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
Ok(builder)
|
||||
}
|
||||
|
||||
value => {
|
||||
unsafe {
|
||||
try!(Errno::result(ui_set_evbit(self.fd, value.kind())));
|
||||
try!(Errno::result(ui_set_keybit(self.fd, value.code())));
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Event::Controller(value) => {
|
||||
match value {
|
||||
event::Controller::All => {
|
||||
let mut builder = self;
|
||||
|
||||
for item in event::controller::Misc::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
for item in event::controller::Mouse::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
for item in event::controller::JoyStick::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
for item in event::controller::GamePad::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
for item in event::controller::Digi::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
for item in event::controller::Wheel::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
for item in event::controller::DPad::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
for item in event::controller::TriggerHappy::iter_variants() {
|
||||
builder = try!(builder.event(item));
|
||||
}
|
||||
|
||||
Ok(builder)
|
||||
}
|
||||
|
||||
value => {
|
||||
unsafe {
|
||||
try!(Errno::result(ui_set_evbit(self.fd, value.kind())));
|
||||
try!(Errno::result(ui_set_keybit(self.fd, value.code())));
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Event::Relative(value) => {
|
||||
unsafe {
|
||||
try!(Errno::result(ui_set_evbit(self.fd, value.kind())));
|
||||
try!(Errno::result(ui_set_relbit(self.fd, value.code())));
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
Event::Absolute(value) => {
|
||||
unsafe {
|
||||
try!(Errno::result(ui_set_evbit(self.fd, value.kind())));
|
||||
try!(Errno::result(ui_set_absbit(self.fd, value.code())));
|
||||
}
|
||||
|
||||
self.abs = Some(value.code());
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
/// Set the maximum value for the previously enabled absolute event.
|
||||
pub fn max(mut self, value: i32) -> Self {
|
||||
self.def.absmax[self.abs.unwrap() as usize] = value;
|
||||
@ -252,15 +137,13 @@ impl Builder {
|
||||
}
|
||||
|
||||
/// Create the defined device.
|
||||
pub fn create(self) -> Res<Device> {
|
||||
pub fn create(self) -> Result<Device> {
|
||||
unsafe {
|
||||
let ptr = &self.def as *const _ as *const u8;
|
||||
let size = mem::size_of_val(&self.def);
|
||||
|
||||
unistd::write(self.fd, slice::from_raw_parts(ptr, size))?;
|
||||
//todo: try!(Errno::result(ui_dev_create(self.fd)));
|
||||
// try1: Errno::result(ui_dev_create(self.fd)).unwrap();
|
||||
Errno::result(ui_dev_create(self.fd))?;
|
||||
ui_dev_create(self.fd)?;
|
||||
}
|
||||
|
||||
Ok(Device::new(self.fd))
|
||||
|
780
src/linux/device/codes.rs
Normal file
780
src/linux/device/codes.rs
Normal file
@ -0,0 +1,780 @@
|
||||
use libc::{c_int};
|
||||
|
||||
pub const INPUT_PROP_POINTER: c_int = 0x00; /* needs a pointer */
|
||||
pub const INPUT_PROP_DIRECT: c_int = 0x01; /* direct input devices */
|
||||
pub const INPUT_PROP_BUTTONPAD: c_int = 0x02; /* has button: c_int = s under pad */
|
||||
pub const INPUT_PROP_SEMI_MT: c_int = 0x03; /* touch rectangle only */
|
||||
pub const INPUT_PROP_TOPBUTTONPAD: c_int = 0x04; /* softbuttons at top of pad */
|
||||
pub const INPUT_PROP_POINTING_STICK: c_int = 0x05; /* is a pointing stick */
|
||||
pub const INPUT_PROP_ACCELEROMETER: c_int = 0x06; /* has accelerometer */
|
||||
|
||||
pub const INPUT_PROP_MAX: c_int = 0x1f;
|
||||
pub const INPUT_PROP_CNT: c_int = INPUT_PROP_MAX + 1;
|
||||
|
||||
/*
|
||||
* Event types
|
||||
*/
|
||||
|
||||
pub const EV_SYN: c_int = 0x00;
|
||||
pub const EV_KEY: c_int = 0x01;
|
||||
pub const EV_REL: c_int = 0x02;
|
||||
pub const EV_ABS: c_int = 0x03;
|
||||
pub const EV_MSC: c_int = 0x04;
|
||||
pub const EV_SW: c_int = 0x05;
|
||||
pub const EV_LED: c_int = 0x11;
|
||||
pub const EV_SND: c_int = 0x12;
|
||||
pub const EV_REP: c_int = 0x14;
|
||||
pub const EV_FF: c_int = 0x15;
|
||||
pub const EV_PWR: c_int = 0x16;
|
||||
pub const EV_FF_STATUS: c_int = 0x17;
|
||||
pub const EV_MAX: c_int = 0x1f;
|
||||
pub const EV_CNT: c_int = EV_MAX + 1;
|
||||
|
||||
/*
|
||||
* Synchronization events.
|
||||
*/
|
||||
|
||||
pub const SYN_REPORT: c_int = 0;
|
||||
pub const SYN_CONFIG: c_int = 1;
|
||||
pub const SYN_MT_REPORT: c_int = 2;
|
||||
pub const SYN_DROPPED: c_int = 3;
|
||||
pub const SYN_MAX: c_int = 0xf;
|
||||
pub const SYN_CNT: c_int = SYN_MAX + 1;
|
||||
|
||||
/*
|
||||
* Keys and buttons
|
||||
*
|
||||
* Most of the keys/buttons are modeled after USB HUT 1.12 (see
|
||||
* http://www.usb.org/developers/hidpage).
|
||||
* Abbreviations in the comments:
|
||||
* AC - Application Control
|
||||
* AL - Application Launch Button
|
||||
* SC - System Control
|
||||
*/
|
||||
|
||||
pub const KEY_RESERVED: c_int = 0;
|
||||
pub const KEY_ESC: c_int = 1;
|
||||
pub const KEY_1: c_int = 2;
|
||||
pub const KEY_2: c_int = 3;
|
||||
pub const KEY_3: c_int = 4;
|
||||
pub const KEY_4: c_int = 5;
|
||||
pub const KEY_5: c_int = 6;
|
||||
pub const KEY_6: c_int = 7;
|
||||
pub const KEY_7: c_int = 8;
|
||||
pub const KEY_8: c_int = 9;
|
||||
pub const KEY_9: c_int = 10;
|
||||
pub const KEY_10: c_int = 11;
|
||||
pub const KEY_MINUS: c_int = 12;
|
||||
pub const KEY_EQUAL: c_int = 13;
|
||||
pub const KEY_BACKSPACE: c_int = 14;
|
||||
pub const KEY_TAB: c_int = 15;
|
||||
pub const KEY_Q: c_int = 16;
|
||||
pub const KEY_W: c_int = 17;
|
||||
pub const KEY_E: c_int = 18;
|
||||
pub const KEY_R: c_int = 19;
|
||||
pub const KEY_T: c_int = 20;
|
||||
pub const KEY_Y: c_int = 21;
|
||||
pub const KEY_U: c_int = 22;
|
||||
pub const KEY_I: c_int = 23;
|
||||
pub const KEY_O: c_int = 24;
|
||||
pub const KEY_P: c_int = 25;
|
||||
pub const KEY_LEFTBRACE: c_int = 26;
|
||||
pub const KEY_RIGHTBRACE: c_int = 27;
|
||||
pub const KEY_ENTER: c_int = 28;
|
||||
pub const KEY_LEFTCTRL: c_int = 29;
|
||||
pub const KEY_A: c_int = 30;
|
||||
pub const KEY_S: c_int = 31;
|
||||
pub const KEY_D: c_int = 32;
|
||||
pub const KEY_F: c_int = 33;
|
||||
pub const KEY_G: c_int = 34;
|
||||
pub const KEY_H: c_int = 35;
|
||||
pub const KEY_J: c_int = 36;
|
||||
pub const KEY_K: c_int = 37;
|
||||
pub const KEY_L: c_int = 38;
|
||||
pub const KEY_SEMICOLON: c_int = 39;
|
||||
pub const KEY_APOSTROPHE: c_int = 40;
|
||||
pub const KEY_GRAVE: c_int = 41;
|
||||
pub const KEY_LEFTSHIFT: c_int = 42;
|
||||
pub const KEY_BACKSLASH: c_int = 43;
|
||||
pub const KEY_Z: c_int = 44;
|
||||
pub const KEY_X: c_int = 45;
|
||||
pub const KEY_C: c_int = 46;
|
||||
pub const KEY_V: c_int = 47;
|
||||
pub const KEY_B: c_int = 48;
|
||||
pub const KEY_N: c_int = 49;
|
||||
pub const KEY_M: c_int = 50;
|
||||
pub const KEY_COMMA: c_int = 51;
|
||||
pub const KEY_DOT: c_int = 52;
|
||||
pub const KEY_SLASH: c_int = 53;
|
||||
pub const KEY_RIGHTSHIFT: c_int = 54;
|
||||
pub const KEY_KPASTERISK: c_int = 55;
|
||||
pub const KEY_LEFTALT: c_int = 56;
|
||||
pub const KEY_SPACE: c_int = 57;
|
||||
pub const KEY_CAPSLOCK: c_int = 58;
|
||||
pub const KEY_F1: c_int = 59;
|
||||
pub const KEY_F2: c_int = 60;
|
||||
pub const KEY_F3: c_int = 61;
|
||||
pub const KEY_F4: c_int = 62;
|
||||
pub const KEY_F5: c_int = 63;
|
||||
pub const KEY_F6: c_int = 64;
|
||||
pub const KEY_F7: c_int = 65;
|
||||
pub const KEY_F8: c_int = 66;
|
||||
pub const KEY_F9: c_int = 67;
|
||||
pub const KEY_F10: c_int = 68;
|
||||
pub const KEY_NUMLOCK: c_int = 69;
|
||||
pub const KEY_SCROLLLOCK: c_int = 70;
|
||||
pub const KEY_KP7: c_int = 71;
|
||||
pub const KEY_KP8: c_int = 72;
|
||||
pub const KEY_KP9: c_int = 73;
|
||||
pub const KEY_KPMINUS: c_int = 74;
|
||||
pub const KEY_KP4: c_int = 75;
|
||||
pub const KEY_KP5: c_int = 76;
|
||||
pub const KEY_KP6: c_int = 77;
|
||||
pub const KEY_KPPLUS: c_int = 78;
|
||||
pub const KEY_KP1: c_int = 79;
|
||||
pub const KEY_KP2: c_int = 80;
|
||||
pub const KEY_KP3: c_int = 81;
|
||||
pub const KEY_KP0: c_int = 82;
|
||||
pub const KEY_KPDOT: c_int = 83;
|
||||
|
||||
pub const KEY_ZENKAKUHANKAKU: c_int = 85;
|
||||
pub const KEY_102ND: c_int = 86;
|
||||
pub const KEY_F11: c_int = 87;
|
||||
pub const KEY_F12: c_int = 88;
|
||||
pub const KEY_RO: c_int = 89;
|
||||
pub const KEY_KATAKANA: c_int = 90;
|
||||
pub const KEY_HIRAGANA: c_int = 91;
|
||||
pub const KEY_HENKAN: c_int = 92;
|
||||
pub const KEY_KATAKANAHIRAGANA: c_int = 93;
|
||||
pub const KEY_MUHENKAN: c_int = 94;
|
||||
pub const KEY_KPJPCOMMA: c_int = 95;
|
||||
pub const KEY_KPENTER: c_int = 96;
|
||||
pub const KEY_RIGHTCTRL: c_int = 97;
|
||||
pub const KEY_KPSLASH: c_int = 98;
|
||||
pub const KEY_SYSRQ: c_int = 99;
|
||||
pub const KEY_RIGHTALT: c_int = 100;
|
||||
pub const KEY_LINEFEED: c_int = 101;
|
||||
pub const KEY_HOME: c_int = 102;
|
||||
pub const KEY_UP: c_int = 103;
|
||||
pub const KEY_PAGEUP: c_int = 104;
|
||||
pub const KEY_LEFT: c_int = 105;
|
||||
pub const KEY_RIGHT: c_int = 106;
|
||||
pub const KEY_END: c_int = 107;
|
||||
pub const KEY_DOWN: c_int = 108;
|
||||
pub const KEY_PAGEDOWN: c_int = 109;
|
||||
pub const KEY_INSERT: c_int = 110;
|
||||
pub const KEY_DELETE: c_int = 111;
|
||||
pub const KEY_MACRO: c_int = 112;
|
||||
pub const KEY_MUTE: c_int = 113;
|
||||
pub const KEY_VOLUMEDOWN: c_int = 114;
|
||||
pub const KEY_VOLUMEUP: c_int = 115;
|
||||
pub const KEY_POWER: c_int = 116; /* SC System Power Down */
|
||||
pub const KEY_KPEQUAL: c_int = 117;
|
||||
pub const KEY_KPPLUSMINUS: c_int = 118;
|
||||
pub const KEY_PAUSE: c_int = 119;
|
||||
pub const KEY_SCALE: c_int = 120; /* AL Compiz Scale : c_int = Expose */
|
||||
|
||||
pub const KEY_KPCOMMA: c_int = 121;
|
||||
pub const KEY_HANGEUL: c_int = 122;
|
||||
pub const KEY_HANGUEL: c_int = KEY_HANGEUL;
|
||||
pub const KEY_HANJA: c_int = 123;
|
||||
pub const KEY_YEN: c_int = 124;
|
||||
pub const KEY_LEFTMETA: c_int = 125;
|
||||
pub const KEY_RIGHTMETA: c_int = 126;
|
||||
pub const KEY_COMPOSE: c_int = 127;
|
||||
|
||||
pub const KEY_STOP: c_int = 128; /* AC Stop */
|
||||
pub const KEY_AGAIN: c_int = 129;
|
||||
pub const KEY_PROPS: c_int = 130; /* AC Properties */
|
||||
pub const KEY_UNDO: c_int = 131; /* AC Undo */
|
||||
pub const KEY_FRONT: c_int = 132;
|
||||
pub const KEY_COPY: c_int = 133; /* AC Copy */
|
||||
pub const KEY_OPEN: c_int = 134; /* AC Open */
|
||||
pub const KEY_PASTE: c_int = 135; /* AC Paste */
|
||||
pub const KEY_FIND: c_int = 136; /* AC Search */
|
||||
pub const KEY_CUT: c_int = 137; /* AC Cut */
|
||||
pub const KEY_HELP: c_int = 138; /* AL Integrated Help Center */
|
||||
pub const KEY_MENU: c_int = 139; /* Menu : c_int = show menu */
|
||||
pub const KEY_CALC: c_int = 140; /* AL Calculator */
|
||||
pub const KEY_SETUP: c_int = 141;
|
||||
pub const KEY_SLEEP: c_int = 142; /* SC System Sleep */
|
||||
pub const KEY_WAKEUP: c_int = 143; /* System Wake Up */
|
||||
pub const KEY_FILE: c_int = 144; /* AL Local Machine Browser */
|
||||
pub const KEY_SENDFILE: c_int = 145;
|
||||
pub const KEY_DELETEFILE: c_int = 146;
|
||||
pub const KEY_XFER: c_int = 147;
|
||||
pub const KEY_PROG1: c_int = 148;
|
||||
pub const KEY_PROG2: c_int = 149;
|
||||
pub const KEY_WWW: c_int = 150; /* AL Internet Browser */
|
||||
pub const KEY_MSDOS: c_int = 151;
|
||||
pub const KEY_COFFEE: c_int = 152; /* AL Terminal Lock/Screensaver */
|
||||
pub const KEY_SCREENLOCK: c_int = KEY_COFFEE;
|
||||
pub const KEY_ROTATE_DISPLAY: c_int = 153; /* Display orientation for e.g. tablets */
|
||||
pub const KEY_DIRECTION: c_int = KEY_ROTATE_DISPLAY;
|
||||
pub const KEY_CYCLEWINDOWS: c_int = 154;
|
||||
pub const KEY_MAIL: c_int = 155;
|
||||
pub const KEY_BOOKMARKS: c_int = 156; /* AC Bookmarks */
|
||||
pub const KEY_COMPUTER: c_int = 157;
|
||||
pub const KEY_BACK: c_int = 158; /* AC Back */
|
||||
pub const KEY_FORWARD: c_int = 159; /* AC Forward */
|
||||
pub const KEY_CLOSECD: c_int = 160;
|
||||
pub const KEY_EJECTCD: c_int = 161;
|
||||
pub const KEY_EJECTCLOSECD: c_int = 162;
|
||||
pub const KEY_NEXTSONG: c_int = 163;
|
||||
pub const KEY_PLAYPAUSE: c_int = 164;
|
||||
pub const KEY_PREVIOUSSONG: c_int = 165;
|
||||
pub const KEY_STOPCD: c_int = 166;
|
||||
pub const KEY_RECORD: c_int = 167;
|
||||
pub const KEY_REWIND: c_int = 168;
|
||||
pub const KEY_PHONE: c_int = 169; /* Media Select Telephone */
|
||||
pub const KEY_ISO: c_int = 170;
|
||||
pub const KEY_CONFIG: c_int = 171; /* AL Consumer Control Configuration */
|
||||
pub const KEY_HOMEPAGE: c_int = 172; /* AC Home */
|
||||
pub const KEY_REFRESH: c_int = 173; /* AC Refresh */
|
||||
pub const KEY_EXIT: c_int = 174; /* AC Exit */
|
||||
pub const KEY_MOVE: c_int = 175;
|
||||
pub const KEY_EDIT: c_int = 176;
|
||||
pub const KEY_SCROLLUP: c_int = 177;
|
||||
pub const KEY_SCROLLDOWN: c_int = 178;
|
||||
pub const KEY_KPLEFTPAREN: c_int = 179;
|
||||
pub const KEY_KPRIGHTPAREN: c_int = 180;
|
||||
pub const KEY_NEW: c_int = 181; /* AC New */
|
||||
pub const KEY_REDO: c_int = 182; /* AC Redo/Repeat */
|
||||
|
||||
pub const KEY_F13: c_int = 183;
|
||||
pub const KEY_F14: c_int = 184;
|
||||
pub const KEY_F15: c_int = 185;
|
||||
pub const KEY_F16: c_int = 186;
|
||||
pub const KEY_F17: c_int = 187;
|
||||
pub const KEY_F18: c_int = 188;
|
||||
pub const KEY_F19: c_int = 189;
|
||||
pub const KEY_F20: c_int = 190;
|
||||
pub const KEY_F21: c_int = 191;
|
||||
pub const KEY_F22: c_int = 192;
|
||||
pub const KEY_F23: c_int = 193;
|
||||
pub const KEY_F24: c_int = 194;
|
||||
|
||||
pub const KEY_PLAYCD: c_int = 200;
|
||||
pub const KEY_PAUSECD: c_int = 201;
|
||||
pub const KEY_PROG3: c_int = 202;
|
||||
pub const KEY_PROG4: c_int = 203;
|
||||
pub const KEY_DASHBOARD: c_int = 204; /* AL Dashboard */
|
||||
pub const KEY_SUSPEND: c_int = 205;
|
||||
pub const KEY_CLOSE: c_int = 206; /* AC Close */
|
||||
pub const KEY_PLAY: c_int = 207;
|
||||
pub const KEY_FASTFORWARD: c_int = 208;
|
||||
pub const KEY_BASSBOOST: c_int = 209;
|
||||
pub const KEY_PRINT: c_int = 210; /* AC Print */
|
||||
pub const KEY_HP: c_int = 211;
|
||||
pub const KEY_CAMERA: c_int = 212;
|
||||
pub const KEY_SOUND: c_int = 213;
|
||||
pub const KEY_QUESTION: c_int = 214;
|
||||
pub const KEY_EMAIL: c_int = 215;
|
||||
pub const KEY_CHAT: c_int = 216;
|
||||
pub const KEY_SEARCH: c_int = 217;
|
||||
pub const KEY_CONNECT: c_int = 218;
|
||||
pub const KEY_FINANCE: c_int = 219; /* AL Checkbook/Finance */
|
||||
pub const KEY_SPORT: c_int = 220;
|
||||
pub const KEY_SHOP: c_int = 221;
|
||||
pub const KEY_ALTERASE: c_int = 222;
|
||||
pub const KEY_CANCEL: c_int = 223; /* AC Cancel */
|
||||
pub const KEY_BRIGHTNESSDOWN: c_int = 224;
|
||||
pub const KEY_BRIGHTNESSUP: c_int = 225;
|
||||
pub const KEY_MEDIA: c_int = 226;
|
||||
|
||||
pub const KEY_SWITCHVIDEOMODE: c_int = 227; /* Cycle between available video outputs (Monitor/LCD/TV-out/etc) */
|
||||
pub const KEY_KBDILLUMTOGGLE: c_int = 228;
|
||||
pub const KEY_KBDILLUMDOWN: c_int = 229;
|
||||
pub const KEY_KBDILLUMUP: c_int = 230;
|
||||
|
||||
pub const KEY_SEND: c_int = 231; /* AC Send */
|
||||
pub const KEY_REPLY: c_int = 232; /* AC Reply */
|
||||
pub const KEY_FORWARDMAIL: c_int = 233; /* AC Forward Msg */
|
||||
pub const KEY_SAVE: c_int = 234; /* AC Save */
|
||||
pub const KEY_DOCUMENTS: c_int = 235;
|
||||
|
||||
pub const KEY_BATTERY: c_int = 236;
|
||||
|
||||
pub const KEY_BLUETOOTH: c_int = 237;
|
||||
pub const KEY_WLAN: c_int = 238;
|
||||
pub const KEY_UWB: c_int = 239;
|
||||
|
||||
pub const KEY_UNKNOWN: c_int = 240;
|
||||
|
||||
pub const KEY_VIDEO_NEXT: c_int = 241; /* drive next video source */
|
||||
pub const KEY_VIDEO_PREV: c_int = 242; /* drive previous video source */
|
||||
pub const KEY_BRIGHTNESS_CYCLE: c_int = 243; /* brightness up, after max is min */
|
||||
pub const KEY_BRIGHTNESS_AUTO: c_int = 244; /* Set Auto Brightness: manual brightness control is off, rely on ambient */
|
||||
pub const KEY_BRIGHTNESS_ZERO: c_int = KEY_BRIGHTNESS_AUTO;
|
||||
pub const KEY_DISPLAY_OFF: c_int = 245; /* display device to off state */
|
||||
|
||||
pub const KEY_WWAN: c_int = 246; /* Wireless WAN : c_int = LTE, UMTS, GSM, etc. */
|
||||
pub const KEY_WIMAX: c_int = KEY_WWAN;
|
||||
pub const KEY_RFKILL: c_int = 247; /* Key that controls all radios */
|
||||
|
||||
pub const KEY_MICMUTE: c_int = 248; /* Mute / unmute the microphone */
|
||||
|
||||
/* Code 255 is reserved for special needs of AT keyboard driver */
|
||||
|
||||
pub const BTN_MISC: c_int = 0x100;
|
||||
pub const BTN_0: c_int = 0x100;
|
||||
pub const BTN_1: c_int = 0x101;
|
||||
pub const BTN_2: c_int = 0x102;
|
||||
pub const BTN_3: c_int = 0x103;
|
||||
pub const BTN_4: c_int = 0x104;
|
||||
pub const BTN_5: c_int = 0x105;
|
||||
pub const BTN_6: c_int = 0x106;
|
||||
pub const BTN_7: c_int = 0x107;
|
||||
pub const BTN_8: c_int = 0x108;
|
||||
pub const BTN_9: c_int = 0x109;
|
||||
|
||||
pub const BTN_MOUSE: c_int = 0x110;
|
||||
pub const BTN_LEFT: c_int = 0x110;
|
||||
pub const BTN_RIGHT: c_int = 0x111;
|
||||
pub const BTN_MIDDLE: c_int = 0x112;
|
||||
pub const BTN_SIDE: c_int = 0x113;
|
||||
pub const BTN_EXTRA: c_int = 0x114;
|
||||
pub const BTN_FORWARD: c_int = 0x115;
|
||||
pub const BTN_BACK: c_int = 0x116;
|
||||
pub const BTN_TASK: c_int = 0x117;
|
||||
|
||||
pub const BTN_JOYSTICK: c_int = 0x120;
|
||||
pub const BTN_TRIGGER: c_int = 0x120;
|
||||
pub const BTN_THUMB: c_int = 0x121;
|
||||
pub const BTN_THUMB2: c_int = 0x122;
|
||||
pub const BTN_TOP: c_int = 0x123;
|
||||
pub const BTN_TOP2: c_int = 0x124;
|
||||
pub const BTN_PINKIE: c_int = 0x125;
|
||||
pub const BTN_BASE: c_int = 0x126;
|
||||
pub const BTN_BASE2: c_int = 0x127;
|
||||
pub const BTN_BASE3: c_int = 0x128;
|
||||
pub const BTN_BASE4: c_int = 0x129;
|
||||
pub const BTN_BASE5: c_int = 0x12a;
|
||||
pub const BTN_BASE6: c_int = 0x12b;
|
||||
pub const BTN_DEAD: c_int = 0x12f;
|
||||
|
||||
pub const BTN_GAMEPAD: c_int = 0x130;
|
||||
pub const BTN_SOUTH: c_int = 0x130;
|
||||
pub const BTN_A: c_int = BTN_SOUTH;
|
||||
pub const BTN_EAST: c_int = 0x131;
|
||||
pub const BTN_B: c_int = BTN_EAST;
|
||||
pub const BTN_C: c_int = 0x132;
|
||||
pub const BTN_NORTH: c_int = 0x133;
|
||||
pub const BTN_X: c_int = BTN_NORTH;
|
||||
pub const BTN_WEST: c_int = 0x134;
|
||||
pub const BTN_Y: c_int = BTN_WEST;
|
||||
pub const BTN_Z: c_int = 0x135;
|
||||
pub const BTN_TL: c_int = 0x136;
|
||||
pub const BTN_TR: c_int = 0x137;
|
||||
pub const BTN_TL2: c_int = 0x138;
|
||||
pub const BTN_TR2: c_int = 0x139;
|
||||
pub const BTN_SELECT: c_int = 0x13a;
|
||||
pub const BTN_START: c_int = 0x13b;
|
||||
pub const BTN_MODE: c_int = 0x13c;
|
||||
pub const BTN_THUMBL: c_int = 0x13d;
|
||||
pub const BTN_THUMBR: c_int = 0x13e;
|
||||
|
||||
pub const BTN_DIGI: c_int = 0x140;
|
||||
pub const BTN_TOOL_PEN: c_int = 0x140;
|
||||
pub const BTN_TOOL_RUBBER: c_int = 0x141;
|
||||
pub const BTN_TOOL_BRUSH: c_int = 0x142;
|
||||
pub const BTN_TOOL_PENCIL: c_int = 0x143;
|
||||
pub const BTN_TOOL_AIRBRUSH: c_int = 0x144;
|
||||
pub const BTN_TOOL_FINGER: c_int = 0x145;
|
||||
pub const BTN_TOOL_MOUSE: c_int = 0x146;
|
||||
pub const BTN_TOOL_LENS: c_int = 0x147;
|
||||
pub const BTN_TOOL_QUINTTAP: c_int = 0x148; /* Five fingers on trackpad */
|
||||
pub const BTN_TOUCH: c_int = 0x14a;
|
||||
pub const BTN_STYLUS: c_int = 0x14b;
|
||||
pub const BTN_STYLUS2: c_int = 0x14c;
|
||||
pub const BTN_TOOL_DOUBLETAP: c_int = 0x14d;
|
||||
pub const BTN_TOOL_TRIPLETAP: c_int = 0x14e;
|
||||
pub const BTN_TOOL_QUADTAP: c_int = 0x14f; /* Four fingers on trackpad */
|
||||
|
||||
pub const BTN_WHEEL: c_int = 0x150;
|
||||
pub const BTN_GEAR_DOWN: c_int = 0x150;
|
||||
pub const BTN_GEAR_UP: c_int = 0x151;
|
||||
|
||||
pub const KEY_OK: c_int = 0x160;
|
||||
pub const KEY_SELECT: c_int = 0x161;
|
||||
pub const KEY_GOTO: c_int = 0x162;
|
||||
pub const KEY_CLEAR: c_int = 0x163;
|
||||
pub const KEY_POWER2: c_int = 0x164;
|
||||
pub const KEY_OPTION: c_int = 0x165;
|
||||
pub const KEY_INFO: c_int = 0x166; /* AL OEM Features/Tips/Tutorial */
|
||||
pub const KEY_TIME: c_int = 0x167;
|
||||
pub const KEY_VENDOR: c_int = 0x168;
|
||||
pub const KEY_ARCHIVE: c_int = 0x169;
|
||||
pub const KEY_PROGRAM: c_int = 0x16a; /* Media Select Program Guide */
|
||||
pub const KEY_CHANNEL: c_int = 0x16b;
|
||||
pub const KEY_FAVORITES: c_int = 0x16c;
|
||||
pub const KEY_EPG: c_int = 0x16d;
|
||||
pub const KEY_PVR: c_int = 0x16e; /* Media Select Home */
|
||||
pub const KEY_MHP: c_int = 0x16f;
|
||||
pub const KEY_LANGUAGE: c_int = 0x170;
|
||||
pub const KEY_TITLE: c_int = 0x171;
|
||||
pub const KEY_SUBTITLE: c_int = 0x172;
|
||||
pub const KEY_ANGLE: c_int = 0x173;
|
||||
pub const KEY_ZOOM: c_int = 0x174;
|
||||
pub const KEY_MODE: c_int = 0x175;
|
||||
pub const KEY_KEYBOARD: c_int = 0x176;
|
||||
pub const KEY_SCREEN: c_int = 0x177;
|
||||
pub const KEY_PC: c_int = 0x178; /* Media Select Computer */
|
||||
pub const KEY_TV: c_int = 0x179; /* Media Select TV */
|
||||
pub const KEY_TV2: c_int = 0x17a; /* Media Select Cable */
|
||||
pub const KEY_VCR: c_int = 0x17b; /* Media Select VCR */
|
||||
pub const KEY_VCR2: c_int = 0x17c; /* VCR Plus */
|
||||
pub const KEY_SAT: c_int = 0x17d; /* Media Select Satellite */
|
||||
pub const KEY_SAT2: c_int = 0x17e;
|
||||
pub const KEY_CD: c_int = 0x17f; /* Media Select CD */
|
||||
pub const KEY_TAPE: c_int = 0x180; /* Media Select Tape */
|
||||
pub const KEY_RADIO: c_int = 0x181;
|
||||
pub const KEY_TUNER: c_int = 0x182; /* Media Select Tuner */
|
||||
pub const KEY_PLAYER: c_int = 0x183;
|
||||
pub const KEY_TEXT: c_int = 0x184;
|
||||
pub const KEY_DVD: c_int = 0x185; /* Media Select DVD */
|
||||
pub const KEY_AUX: c_int = 0x186;
|
||||
pub const KEY_MP3: c_int = 0x187;
|
||||
pub const KEY_AUDIO: c_int = 0x188; /* AL Audio Browser */
|
||||
pub const KEY_VIDEO: c_int = 0x189; /* AL Movie Browser */
|
||||
pub const KEY_DIRECTORY: c_int = 0x18a;
|
||||
pub const KEY_LIST: c_int = 0x18b;
|
||||
pub const KEY_MEMO: c_int = 0x18c; /* Media Select Messages */
|
||||
pub const KEY_CALENDAR: c_int = 0x18d;
|
||||
pub const KEY_RED: c_int = 0x18e;
|
||||
pub const KEY_GREEN: c_int = 0x18f;
|
||||
pub const KEY_YELLOW: c_int = 0x190;
|
||||
pub const KEY_BLUE: c_int = 0x191;
|
||||
pub const KEY_CHANNELUP: c_int = 0x192; /* Channel Increment */
|
||||
pub const KEY_CHANNELDOWN: c_int = 0x193; /* Channel Decrement */
|
||||
pub const KEY_FIRST: c_int = 0x194;
|
||||
pub const KEY_LAST: c_int = 0x195; /* Recall Last */
|
||||
pub const KEY_AB: c_int = 0x196;
|
||||
pub const KEY_NEXT: c_int = 0x197;
|
||||
pub const KEY_RESTART: c_int = 0x198;
|
||||
pub const KEY_SLOW: c_int = 0x199;
|
||||
pub const KEY_SHUFFLE: c_int = 0x19a;
|
||||
pub const KEY_BREAK: c_int = 0x19b;
|
||||
pub const KEY_PREVIOUS: c_int = 0x19c;
|
||||
pub const KEY_DIGITS: c_int = 0x19d;
|
||||
pub const KEY_TEEN: c_int = 0x19e;
|
||||
pub const KEY_TWEN: c_int = 0x19f;
|
||||
pub const KEY_VIDEOPHONE: c_int = 0x1a0; /* Media Select Video Phone */
|
||||
pub const KEY_GAMES: c_int = 0x1a1; /* Media Select Games */
|
||||
pub const KEY_ZOOMIN: c_int = 0x1a2; /* AC Zoom In */
|
||||
pub const KEY_ZOOMOUT: c_int = 0x1a3; /* AC Zoom Out */
|
||||
pub const KEY_ZOOMRESET: c_int = 0x1a4; /* AC Zoom */
|
||||
pub const KEY_WORDPROCESSOR: c_int = 0x1a5; /* AL Word Processor */
|
||||
pub const KEY_EDITOR: c_int = 0x1a6; /* AL Text Editor */
|
||||
pub const KEY_SPREADSHEET: c_int = 0x1a7; /* AL Spreadsheet */
|
||||
pub const KEY_GRAPHICSEDITOR: c_int = 0x1a8; /* AL Graphics Editor */
|
||||
pub const KEY_PRESENTATION: c_int = 0x1a9; /* AL Presentation App */
|
||||
pub const KEY_DATABASE: c_int = 0x1aa; /* AL Database App */
|
||||
pub const KEY_NEWS: c_int = 0x1ab; /* AL Newsreader */
|
||||
pub const KEY_VOICEMAIL: c_int = 0x1ac; /* AL Voicemail */
|
||||
pub const KEY_ADDRESSBOOK: c_int = 0x1ad; /* AL Contacts/Address Book */
|
||||
pub const KEY_MESSENGER: c_int = 0x1ae; /* AL Instant Messaging */
|
||||
pub const KEY_DISPLAYTOGGLE: c_int = 0x1af; /* Turn display : c_int = LCD on and off */
|
||||
pub const KEY_BRIGHTNESS_TOGGLE: c_int = KEY_DISPLAYTOGGLE;
|
||||
pub const KEY_SPELLCHECK: c_int = 0x1b0; /* AL Spell Check */
|
||||
pub const KEY_LOGOFF: c_int = 0x1b1; /* AL Logoff */
|
||||
|
||||
pub const KEY_DOLLAR: c_int = 0x1b2;
|
||||
pub const KEY_EURO: c_int = 0x1b3;
|
||||
|
||||
pub const KEY_FRAMEBACK: c_int = 0x1b4; /* Consumer - transport controls */
|
||||
pub const KEY_FRAMEFORWARD: c_int = 0x1b5;
|
||||
pub const KEY_CONTEXT_MENU: c_int = 0x1b6; /* GenDesc - system context menu */
|
||||
pub const KEY_MEDIA_REPEAT: c_int = 0x1b7; /* Consumer - transport control */
|
||||
pub const KEY_10CHANNELSUP: c_int = 0x1b8; /* 10 channels up : c_int = 10+ */
|
||||
pub const KEY_10CHANNELSDOWN: c_int = 0x1b9; /* 10 channels down : c_int = 10- */
|
||||
pub const KEY_IMAGES: c_int = 0x1ba; /* AL Image Browser */
|
||||
|
||||
pub const KEY_DEL_EOL: c_int = 0x1c0;
|
||||
pub const KEY_DEL_EOS: c_int = 0x1c1;
|
||||
pub const KEY_INS_LINE: c_int = 0x1c2;
|
||||
pub const KEY_DEL_LINE: c_int = 0x1c3;
|
||||
|
||||
pub const KEY_FN: c_int = 0x1d0;
|
||||
pub const KEY_FN_ESC: c_int = 0x1d1;
|
||||
pub const KEY_FN_F1: c_int = 0x1d2;
|
||||
pub const KEY_FN_F2: c_int = 0x1d3;
|
||||
pub const KEY_FN_F3: c_int = 0x1d4;
|
||||
pub const KEY_FN_F4: c_int = 0x1d5;
|
||||
pub const KEY_FN_F5: c_int = 0x1d6;
|
||||
pub const KEY_FN_F6: c_int = 0x1d7;
|
||||
pub const KEY_FN_F7: c_int = 0x1d8;
|
||||
pub const KEY_FN_F8: c_int = 0x1d9;
|
||||
pub const KEY_FN_F9: c_int = 0x1da;
|
||||
pub const KEY_FN_F10: c_int = 0x1db;
|
||||
pub const KEY_FN_F11: c_int = 0x1dc;
|
||||
pub const KEY_FN_F12: c_int = 0x1dd;
|
||||
pub const KEY_FN_1: c_int = 0x1de;
|
||||
pub const KEY_FN_2: c_int = 0x1df;
|
||||
pub const KEY_FN_D: c_int = 0x1e0;
|
||||
pub const KEY_FN_E: c_int = 0x1e1;
|
||||
pub const KEY_FN_F: c_int = 0x1e2;
|
||||
pub const KEY_FN_S: c_int = 0x1e3;
|
||||
pub const KEY_FN_B: c_int = 0x1e4;
|
||||
|
||||
pub const KEY_BRL_DOT1: c_int = 0x1f1;
|
||||
pub const KEY_BRL_DOT2: c_int = 0x1f2;
|
||||
pub const KEY_BRL_DOT3: c_int = 0x1f3;
|
||||
pub const KEY_BRL_DOT4: c_int = 0x1f4;
|
||||
pub const KEY_BRL_DOT5: c_int = 0x1f5;
|
||||
pub const KEY_BRL_DOT6: c_int = 0x1f6;
|
||||
pub const KEY_BRL_DOT7: c_int = 0x1f7;
|
||||
pub const KEY_BRL_DOT8: c_int = 0x1f8;
|
||||
pub const KEY_BRL_DOT9: c_int = 0x1f9;
|
||||
pub const KEY_BRL_DOT10: c_int = 0x1fa;
|
||||
|
||||
pub const KEY_NUMERIC_0: c_int = 0x200; /* used by phones, remote controls, */
|
||||
pub const KEY_NUMERIC_1: c_int = 0x201; /* and other keypads */
|
||||
pub const KEY_NUMERIC_2: c_int = 0x202;
|
||||
pub const KEY_NUMERIC_3: c_int = 0x203;
|
||||
pub const KEY_NUMERIC_4: c_int = 0x204;
|
||||
pub const KEY_NUMERIC_5: c_int = 0x205;
|
||||
pub const KEY_NUMERIC_6: c_int = 0x206;
|
||||
pub const KEY_NUMERIC_7: c_int = 0x207;
|
||||
pub const KEY_NUMERIC_8: c_int = 0x208;
|
||||
pub const KEY_NUMERIC_9: c_int = 0x209;
|
||||
pub const KEY_NUMERIC_STAR: c_int = 0x20a;
|
||||
pub const KEY_NUMERIC_POUND: c_int = 0x20b;
|
||||
pub const KEY_NUMERIC_A: c_int = 0x20c; /* Phone key A - HUT Telephony 0xb9 */
|
||||
pub const KEY_NUMERIC_B: c_int = 0x20d;
|
||||
pub const KEY_NUMERIC_C: c_int = 0x20e;
|
||||
pub const KEY_NUMERIC_D: c_int = 0x20f;
|
||||
|
||||
pub const KEY_CAMERA_FOCUS: c_int = 0x210;
|
||||
pub const KEY_WPS_BUTTON: c_int = 0x211; /* WiFi Protected Setup key */
|
||||
|
||||
pub const KEY_TOUCHPAD_TOGGLE: c_int = 0x212; /* Request switch touchpad on or off */
|
||||
pub const KEY_TOUCHPAD_ON: c_int = 0x213;
|
||||
pub const KEY_TOUCHPAD_OFF: c_int = 0x214;
|
||||
|
||||
pub const KEY_CAMERA_ZOOMIN: c_int = 0x215;
|
||||
pub const KEY_CAMERA_ZOOMOUT: c_int = 0x216;
|
||||
pub const KEY_CAMERA_UP: c_int = 0x217;
|
||||
pub const KEY_CAMERA_DOWN: c_int = 0x218;
|
||||
pub const KEY_CAMERA_LEFT: c_int = 0x219;
|
||||
pub const KEY_CAMERA_RIGHT: c_int = 0x21a;
|
||||
|
||||
pub const KEY_ATTENDANT_ON: c_int = 0x21b;
|
||||
pub const KEY_ATTENDANT_OFF: c_int = 0x21c;
|
||||
pub const KEY_ATTENDANT_TOGGLE: c_int = 0x21d; /* Attendant call on or off */
|
||||
pub const KEY_LIGHTS_TOGGLE: c_int = 0x21e; /* Reading light on or off */
|
||||
|
||||
pub const BTN_DPAD_UP: c_int = 0x220;
|
||||
pub const BTN_DPAD_DOWN: c_int = 0x221;
|
||||
pub const BTN_DPAD_LEFT: c_int = 0x222;
|
||||
pub const BTN_DPAD_RIGHT: c_int = 0x223;
|
||||
|
||||
pub const KEY_ALS_TOGGLE: c_int = 0x230; /* Ambient light sensor */
|
||||
|
||||
pub const KEY_BUTTONCONFIG: c_int = 0x240; /* AL Button Configuration */
|
||||
pub const KEY_TASKMANAGER: c_int = 0x241; /* AL Task/Project Manager */
|
||||
pub const KEY_JOURNAL: c_int = 0x242; /* AL Log/Journal/Timecard */
|
||||
pub const KEY_CONTROLPANEL: c_int = 0x243; /* AL Control Panel */
|
||||
pub const KEY_APPSELECT: c_int = 0x244; /* AL Select Task/Application */
|
||||
pub const KEY_SCREENSAVER: c_int = 0x245; /* AL Screen Saver */
|
||||
pub const KEY_VOICECOMMAND: c_int = 0x246; /* Listening Voice Command */
|
||||
|
||||
pub const KEY_BRIGHTNESS_MIN: c_int = 0x250; /* Set Brightness to Minimum */
|
||||
pub const KEY_BRIGHTNESS_MAX: c_int = 0x251; /* Set Brightness to Maximum */
|
||||
|
||||
pub const KEY_KBDINPUTASSIST_PREV: c_int = 0x260;
|
||||
pub const KEY_KBDINPUTASSIST_NEXT: c_int = 0x261;
|
||||
pub const KEY_KBDINPUTASSIST_PREVGROUP: c_int = 0x262;
|
||||
pub const KEY_KBDINPUTASSIST_NEXTGROUP: c_int = 0x263;
|
||||
pub const KEY_KBDINPUTASSIST_ACCEPT: c_int = 0x264;
|
||||
pub const KEY_KBDINPUTASSIST_CANCEL: c_int = 0x265;
|
||||
|
||||
pub const BTN_TRIGGER_HAPPY: c_int = 0x2c0;
|
||||
pub const BTN_TRIGGER_HAPPY1: c_int = 0x2c0;
|
||||
pub const BTN_TRIGGER_HAPPY2: c_int = 0x2c1;
|
||||
pub const BTN_TRIGGER_HAPPY3: c_int = 0x2c2;
|
||||
pub const BTN_TRIGGER_HAPPY4: c_int = 0x2c3;
|
||||
pub const BTN_TRIGGER_HAPPY5: c_int = 0x2c4;
|
||||
pub const BTN_TRIGGER_HAPPY6: c_int = 0x2c5;
|
||||
pub const BTN_TRIGGER_HAPPY7: c_int = 0x2c6;
|
||||
pub const BTN_TRIGGER_HAPPY8: c_int = 0x2c7;
|
||||
pub const BTN_TRIGGER_HAPPY9: c_int = 0x2c8;
|
||||
pub const BTN_TRIGGER_HAPPY10: c_int = 0x2c9;
|
||||
pub const BTN_TRIGGER_HAPPY11: c_int = 0x2ca;
|
||||
pub const BTN_TRIGGER_HAPPY12: c_int = 0x2cb;
|
||||
pub const BTN_TRIGGER_HAPPY13: c_int = 0x2cc;
|
||||
pub const BTN_TRIGGER_HAPPY14: c_int = 0x2cd;
|
||||
pub const BTN_TRIGGER_HAPPY15: c_int = 0x2ce;
|
||||
pub const BTN_TRIGGER_HAPPY16: c_int = 0x2cf;
|
||||
pub const BTN_TRIGGER_HAPPY17: c_int = 0x2d0;
|
||||
pub const BTN_TRIGGER_HAPPY18: c_int = 0x2d1;
|
||||
pub const BTN_TRIGGER_HAPPY19: c_int = 0x2d2;
|
||||
pub const BTN_TRIGGER_HAPPY20: c_int = 0x2d3;
|
||||
pub const BTN_TRIGGER_HAPPY21: c_int = 0x2d4;
|
||||
pub const BTN_TRIGGER_HAPPY22: c_int = 0x2d5;
|
||||
pub const BTN_TRIGGER_HAPPY23: c_int = 0x2d6;
|
||||
pub const BTN_TRIGGER_HAPPY24: c_int = 0x2d7;
|
||||
pub const BTN_TRIGGER_HAPPY25: c_int = 0x2d8;
|
||||
pub const BTN_TRIGGER_HAPPY26: c_int = 0x2d9;
|
||||
pub const BTN_TRIGGER_HAPPY27: c_int = 0x2da;
|
||||
pub const BTN_TRIGGER_HAPPY28: c_int = 0x2db;
|
||||
pub const BTN_TRIGGER_HAPPY29: c_int = 0x2dc;
|
||||
pub const BTN_TRIGGER_HAPPY30: c_int = 0x2dd;
|
||||
pub const BTN_TRIGGER_HAPPY31: c_int = 0x2de;
|
||||
pub const BTN_TRIGGER_HAPPY32: c_int = 0x2df;
|
||||
pub const BTN_TRIGGER_HAPPY33: c_int = 0x2e0;
|
||||
pub const BTN_TRIGGER_HAPPY34: c_int = 0x2e1;
|
||||
pub const BTN_TRIGGER_HAPPY35: c_int = 0x2e2;
|
||||
pub const BTN_TRIGGER_HAPPY36: c_int = 0x2e3;
|
||||
pub const BTN_TRIGGER_HAPPY37: c_int = 0x2e4;
|
||||
pub const BTN_TRIGGER_HAPPY38: c_int = 0x2e5;
|
||||
pub const BTN_TRIGGER_HAPPY39: c_int = 0x2e6;
|
||||
pub const BTN_TRIGGER_HAPPY40: c_int = 0x2e7;
|
||||
|
||||
/* We avoid low common keys in module aliases so they don't get huge. */
|
||||
pub const KEY_MIN_INTERESTING: c_int = KEY_MUTE;
|
||||
pub const KEY_MAX: c_int = 0x2ff;
|
||||
pub const KEY_CNT: c_int = KEY_MAX + 1;
|
||||
|
||||
/*
|
||||
* Relative axes
|
||||
*/
|
||||
|
||||
pub const REL_X: c_int = 0x00;
|
||||
pub const REL_Y: c_int = 0x01;
|
||||
pub const REL_Z: c_int = 0x02;
|
||||
pub const REL_RX: c_int = 0x03;
|
||||
pub const REL_RY: c_int = 0x04;
|
||||
pub const REL_RZ: c_int = 0x05;
|
||||
pub const REL_HWHEEL: c_int = 0x06;
|
||||
pub const REL_DIAL: c_int = 0x07;
|
||||
pub const REL_WHEEL: c_int = 0x08;
|
||||
pub const REL_MISC: c_int = 0x09;
|
||||
pub const REL_MAX: c_int = 0x0f;
|
||||
pub const REL_CNT: c_int = REL_MAX + 1;
|
||||
|
||||
/*
|
||||
* Absolute axes
|
||||
*/
|
||||
|
||||
pub const ABS_X: c_int = 0x00;
|
||||
pub const ABS_Y: c_int = 0x01;
|
||||
pub const ABS_Z: c_int = 0x02;
|
||||
pub const ABS_RX: c_int = 0x03;
|
||||
pub const ABS_RY: c_int = 0x04;
|
||||
pub const ABS_RZ: c_int = 0x05;
|
||||
pub const ABS_THROTTLE: c_int = 0x06;
|
||||
pub const ABS_RUDDER: c_int = 0x07;
|
||||
pub const ABS_WHEEL: c_int = 0x08;
|
||||
pub const ABS_GAS: c_int = 0x09;
|
||||
pub const ABS_BRAKE: c_int = 0x0a;
|
||||
pub const ABS_HAT0X: c_int = 0x10;
|
||||
pub const ABS_HAT0Y: c_int = 0x11;
|
||||
pub const ABS_HAT1X: c_int = 0x12;
|
||||
pub const ABS_HAT1Y: c_int = 0x13;
|
||||
pub const ABS_HAT2X: c_int = 0x14;
|
||||
pub const ABS_HAT2Y: c_int = 0x15;
|
||||
pub const ABS_HAT3X: c_int = 0x16;
|
||||
pub const ABS_HAT3Y: c_int = 0x17;
|
||||
pub const ABS_PRESSURE: c_int = 0x18;
|
||||
pub const ABS_DISTANCE: c_int = 0x19;
|
||||
pub const ABS_TILT_X: c_int = 0x1a;
|
||||
pub const ABS_TILT_Y: c_int = 0x1b;
|
||||
pub const ABS_TOOL_WIDTH: c_int = 0x1c;
|
||||
|
||||
pub const ABS_VOLUME: c_int = 0x20;
|
||||
|
||||
pub const ABS_MISC: c_int = 0x28;
|
||||
|
||||
pub const ABS_MT_SLOT: c_int = 0x2f; /* MT slot being modified */
|
||||
pub const ABS_MT_TOUCH_MAJOR: c_int = 0x30; /* Major axis of touching ellipse */
|
||||
pub const ABS_MT_TOUCH_MINOR: c_int = 0x31; /* Minor axis : c_int = omit if circular */
|
||||
pub const ABS_MT_WIDTH_MAJOR: c_int = 0x32; /* Major axis of approaching ellipse */
|
||||
pub const ABS_MT_WIDTH_MINOR: c_int = 0x33; /* Minor axis : c_int = omit if circular */
|
||||
pub const ABS_MT_ORIENTATION: c_int = 0x34; /* Ellipse orientation */
|
||||
pub const ABS_MT_POSITION_X: c_int = 0x35; /* Center X touch position */
|
||||
pub const ABS_MT_POSITION_Y: c_int = 0x36; /* Center Y touch position */
|
||||
pub const ABS_MT_TOOL_TYPE: c_int = 0x37; /* Type of touching device */
|
||||
pub const ABS_MT_BLOB_ID: c_int = 0x38; /* Group a set of packets as a blob */
|
||||
pub const ABS_MT_TRACKING_ID: c_int = 0x39; /* Unique ID of initiated contact */
|
||||
pub const ABS_MT_PRESSURE: c_int = 0x3a; /* Pressure on contact area */
|
||||
pub const ABS_MT_DISTANCE: c_int = 0x3b; /* Contact hover distance */
|
||||
pub const ABS_MT_TOOL_X: c_int = 0x3c; /* Center X tool position */
|
||||
pub const ABS_MT_TOOL_Y: c_int = 0x3d; /* Center Y tool position */
|
||||
|
||||
|
||||
pub const ABS_MAX: c_int = 0x3f;
|
||||
pub const ABS_CNT: c_int = ABS_MAX + 1;
|
||||
|
||||
/*
|
||||
* Switch events
|
||||
*/
|
||||
|
||||
pub const SW_LID: c_int = 0x00; /* set = lid shut */
|
||||
pub const SW_TABLET_MODE: c_int = 0x01; /* set = tablet mode */
|
||||
pub const SW_HEADPHONE_INSERT: c_int = 0x02; /* set = inserted */
|
||||
pub const SW_RFKILL_ALL: c_int = 0x03; /* rfkill master switch, type "any" set = radio enabled */
|
||||
pub const SW_RADIO: c_int = SW_RFKILL_ALL; /* deprecated */
|
||||
pub const SW_MICROPHONE_INSERT: c_int = 0x04; /* set = inserted */
|
||||
pub const SW_DOCK: c_int = 0x05; /* set = plugged into dock */
|
||||
pub const SW_LINEOUT_INSERT: c_int = 0x06; /* set = inserted */
|
||||
pub const SW_JACK_PHYSICAL_INSERT: c_int = 0x07; /* set = mechanical switch set */
|
||||
pub const SW_VIDEOOUT_INSERT: c_int = 0x08; /* set = inserted */
|
||||
pub const SW_CAMERA_LENS_COVER: c_int = 0x09; /* set = lens covered */
|
||||
pub const SW_KEYPAD_SLIDE: c_int = 0x0a; /* set = keypad slide out */
|
||||
pub const SW_FRONT_PROXIMITY: c_int = 0x0b; /* set = front proximity sensor active */
|
||||
pub const SW_ROTATE_LOCK: c_int = 0x0c; /* set = rotate locked/disabled */
|
||||
pub const SW_LINEIN_INSERT: c_int = 0x0d; /* set = inserted */
|
||||
pub const SW_MUTE_DEVICE: c_int = 0x0e; /* set = device disabled */
|
||||
pub const SW_MAX: c_int = 0x0f;
|
||||
pub const SW_CNT: c_int = SW_MAX + 1;
|
||||
|
||||
/*
|
||||
* Misc events
|
||||
*/
|
||||
|
||||
pub const MSC_SERIAL: c_int = 0x00;
|
||||
pub const MSC_PULSELED: c_int = 0x01;
|
||||
pub const MSC_GESTURE: c_int = 0x02;
|
||||
pub const MSC_RAW: c_int = 0x03;
|
||||
pub const MSC_SCAN: c_int = 0x04;
|
||||
pub const MSC_TIMESTAMP: c_int = 0x05;
|
||||
pub const MSC_MAX: c_int = 0x07;
|
||||
pub const MSC_CNT: c_int = MSC_MAX + 1;
|
||||
|
||||
/*
|
||||
* LEDs
|
||||
*/
|
||||
|
||||
pub const LED_NUML: c_int = 0x00;
|
||||
pub const LED_CAPSL: c_int = 0x01;
|
||||
pub const LED_SCROLLL: c_int = 0x02;
|
||||
pub const LED_COMPOSE: c_int = 0x03;
|
||||
pub const LED_KANA: c_int = 0x04;
|
||||
pub const LED_SLEEP: c_int = 0x05;
|
||||
pub const LED_SUSPEND: c_int = 0x06;
|
||||
pub const LED_MUTE: c_int = 0x07;
|
||||
pub const LED_MISC: c_int = 0x08;
|
||||
pub const LED_MAIL: c_int = 0x09;
|
||||
pub const LED_CHARGING: c_int = 0x0a;
|
||||
pub const LED_MAX: c_int = 0x0f;
|
||||
pub const LED_CNT: c_int = LED_MAX + 1;
|
||||
|
||||
/*
|
||||
* Autorepeat values
|
||||
*/
|
||||
|
||||
pub const REP_DELAY: c_int = 0x00;
|
||||
pub const REP_PERIOD: c_int = 0x01;
|
||||
pub const REP_MAX: c_int = 0x01;
|
||||
pub const REP_CNT: c_int = REP_MAX + 1;
|
||||
|
||||
/*
|
||||
* Sounds
|
||||
*/
|
||||
|
||||
pub const SND_CLICK: c_int = 0x00;
|
||||
pub const SND_BELL: c_int = 0x01;
|
||||
pub const SND_TONE: c_int = 0x02;
|
||||
pub const SND_MAX: c_int = 0x07;
|
||||
pub const SND_CNT: c_int = SND_MAX + 1;
|
@ -1,8 +1,11 @@
|
||||
use std::{mem, ptr, slice};
|
||||
use libc::{timeval, gettimeofday, input_event, c_int};
|
||||
use nix::{unistd, errno::Errno};
|
||||
use uinput_sys::*;
|
||||
use crate::{Result as Res};
|
||||
use nix::{unistd, ioctl_none};
|
||||
use crate::Result;
|
||||
|
||||
use crate::linux::device::codes::*;
|
||||
|
||||
ioctl_none!(ui_dev_destroy, b'U', 2);
|
||||
|
||||
/// The virtual device.
|
||||
pub struct Device {
|
||||
@ -18,7 +21,7 @@ impl Device {
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn write(&self, kind: c_int, code: c_int, value: c_int) -> Res<()> {
|
||||
pub fn write(&self, kind: c_int, code: c_int, value: c_int) -> Result<()> {
|
||||
let mut event = input_event {
|
||||
time: timeval { tv_sec: 0, tv_usec: 0 },
|
||||
type_: kind as u16,
|
||||
@ -30,7 +33,7 @@ impl Device {
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn write_event(&self, event: &mut input_event) -> Res<()> {
|
||||
pub fn write_event(&self, event: &mut input_event) -> Result<()> {
|
||||
unsafe {
|
||||
gettimeofday(&mut event.time, ptr::null_mut());
|
||||
|
||||
@ -44,35 +47,33 @@ impl Device {
|
||||
}
|
||||
|
||||
/// Synchronize the device.
|
||||
pub fn synchronize(&self) -> Res<()> {
|
||||
pub fn synchronize(&self) -> Result<()> {
|
||||
self.write(EV_SYN, SYN_REPORT, 0)
|
||||
}
|
||||
|
||||
/// Send an event.
|
||||
pub fn send(&self, kind: c_int, code: c_int, value: i32) -> Res<()> {
|
||||
pub fn send(&self, kind: c_int, code: c_int, value: i32) -> Result<()> {
|
||||
self.write(kind, code, value)
|
||||
}
|
||||
|
||||
/// Send a press event.
|
||||
pub fn press(&self, kind: c_int, code: c_int) -> Res<()> {
|
||||
pub fn press(&self, kind: c_int, code: c_int) -> Result<()> {
|
||||
self.write(kind, code, 1)
|
||||
}
|
||||
|
||||
/// Send a release event.
|
||||
pub fn release(&self, kind: c_int, code: c_int) -> Res<()> {
|
||||
pub fn release(&self, kind: c_int, code: c_int) -> Result<()> {
|
||||
self.write(kind, code, 0)
|
||||
}
|
||||
|
||||
/// Send a press and release event.
|
||||
pub fn click(&self, kind: c_int, code: c_int) -> Res<()> {
|
||||
pub fn click(&self, kind: c_int, code: c_int) -> Result<()> {
|
||||
self.press(kind, code)?;
|
||||
self.release(kind, code)?;
|
||||
|
||||
Ok(())
|
||||
self.release(kind, code)
|
||||
}
|
||||
|
||||
/// Send a relative or absolute positioning event.
|
||||
pub fn position(&self, kind: c_int, code: c_int, value: i32) -> Res<()> {
|
||||
pub fn position(&self, kind: c_int, code: c_int, value: i32) -> Result<()> {
|
||||
self.write(kind, code, value)
|
||||
}
|
||||
}
|
||||
@ -80,7 +81,8 @@ impl Device {
|
||||
impl Drop for Device {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
Errno::result(ui_dev_destroy(self.fd)).unwrap();
|
||||
// ignore error here so as to not panic in a drop
|
||||
ui_dev_destroy(self.fd).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,54 +3,148 @@ use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use libc::{input_event, c_int};
|
||||
use nix::ioctl_write_ptr;
|
||||
use nix::{ioctl_write_ptr, ioctl_read_buf};
|
||||
|
||||
#[cfg(feature = "epoll_inotify")]
|
||||
use std::os::unix::prelude::RawFd;
|
||||
|
||||
use crate::{Error,Result};
|
||||
use crate::linux::{EV_KEY, KEY_MAX, NAME, KEY_W, KEY_A, KEY_S, KEY_D, BTN_LEFT};
|
||||
|
||||
ioctl_write_ptr!(eviocgrab, b'E', 0x90, c_int);
|
||||
ioctl_read_buf!(eviocgname, b'E', 0x06, u8);
|
||||
ioctl_read_buf!(eviocgbit, b'E', 0x20, u8);
|
||||
ioctl_read_buf!(eviocgbit_ev_key, b'E', 0x20 + EV_KEY, u8);
|
||||
|
||||
// TODO: use size_of_input_event instead of hard-coding 24.
|
||||
const SIZE_OF_INPUT_EVENT: usize = 24;//mem::size_of::<input_event>();
|
||||
const SIZE_OF_INPUT_EVENT: usize = mem::size_of::<input_event>();
|
||||
|
||||
pub struct InputDevice {
|
||||
device_file: File,
|
||||
buf: [u8; SIZE_OF_INPUT_EVENT],
|
||||
grabbed: bool,
|
||||
#[cfg(feature = "epoll_inotify")]
|
||||
epoll_fd: Option<RawFd>,
|
||||
}
|
||||
|
||||
impl InputDevice {
|
||||
pub fn open(device_file: &str) -> Result<Self> {
|
||||
let device_file = File::open(device_file)?;
|
||||
pub fn open<P: AsRef<std::path::Path>>(path: P) -> Result<Self> {
|
||||
Ok(InputDevice {
|
||||
device_file: device_file,
|
||||
buf: [0u8; SIZE_OF_INPUT_EVENT],
|
||||
device_file: File::open(path)?,
|
||||
grabbed: false,
|
||||
#[cfg(feature = "epoll_inotify")]
|
||||
epoll_fd: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn new_input_event_buf() -> [u8; SIZE_OF_INPUT_EVENT] {
|
||||
[0u8; SIZE_OF_INPUT_EVENT]
|
||||
}
|
||||
|
||||
pub fn read_event(&mut self) -> Result<input_event> {
|
||||
let num_bytes = self.device_file.read(&mut self.buf)?;
|
||||
pub fn read_event(&mut self, buf: &mut [u8; SIZE_OF_INPUT_EVENT]) -> Result<input_event> {
|
||||
let num_bytes = self.device_file.read(buf)?;
|
||||
if num_bytes != SIZE_OF_INPUT_EVENT {
|
||||
return Err(Error::ShortRead);
|
||||
}
|
||||
let event: input_event = unsafe { mem::transmute(self.buf) };
|
||||
let event: input_event = unsafe { mem::transmute(*buf) };
|
||||
Ok(event)
|
||||
}
|
||||
|
||||
pub fn grab(&mut self) -> Result<()> {
|
||||
pub fn valid_keyboard_device(self) -> Result<Self> {
|
||||
use std::os::unix::fs::FileTypeExt;
|
||||
|
||||
// must be a character device
|
||||
if !self.device_file.metadata()?.file_type().is_char_device() {
|
||||
return Err(Error::NotAKeyboard);
|
||||
}
|
||||
|
||||
let raw_fd = self.device_file.as_raw_fd();
|
||||
|
||||
// does it support EV_KEY
|
||||
let mut evbit = [0u8; 8];
|
||||
unsafe {
|
||||
eviocgbit(raw_fd, &mut evbit)?;
|
||||
};
|
||||
let evbit = u64::from_ne_bytes(evbit);
|
||||
if (evbit & (1 << EV_KEY)) == 0 {
|
||||
return Err(Error::NotAKeyboard);
|
||||
}
|
||||
|
||||
// does it support all keys WASD and *not* LEFT mouse button ? (yes this is fairly random but probably good enough, could make configuration probably)
|
||||
let mut key_bits = [0u8; (KEY_MAX as usize / 8) + 1];
|
||||
unsafe {
|
||||
eviocgbit_ev_key(raw_fd, &mut key_bits)?;
|
||||
};
|
||||
let key_unsupported = |key : c_int| (key_bits[key as usize / 8] & (1 << (key % 8))) == 0;
|
||||
if key_unsupported(KEY_W) || key_unsupported(KEY_A) || key_unsupported(KEY_S) || key_unsupported(KEY_D) || !key_unsupported(BTN_LEFT) {
|
||||
return Err(Error::NotAKeyboard);
|
||||
}
|
||||
|
||||
// is it another running copy of rusty-keys ?
|
||||
let mut name = [0u8; NAME.len()];
|
||||
unsafe {
|
||||
eviocgname(raw_fd, &mut name)?
|
||||
};
|
||||
// exclude anything starting with "Yubico" also
|
||||
if NAME.as_bytes() == &name || "Yubico".as_bytes() == &name[0..6] {
|
||||
return Err(Error::NotAKeyboard);
|
||||
}
|
||||
return Ok(self);
|
||||
}
|
||||
|
||||
pub fn grab(mut self) -> Result<Self> {
|
||||
unsafe {
|
||||
eviocgrab(self.device_file.as_raw_fd(), 1 as *const c_int)?;
|
||||
}
|
||||
Ok(())
|
||||
self.grabbed = true;
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn release(&mut self) -> Result<()> {
|
||||
unsafe {
|
||||
eviocgrab(self.device_file.as_raw_fd(), 0 as *const c_int)?;
|
||||
if self.grabbed {
|
||||
unsafe {
|
||||
eviocgrab(self.device_file.as_raw_fd(), 0 as *const c_int)?;
|
||||
}
|
||||
self.grabbed = false;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "epoll_inotify")]
|
||||
pub fn epoll_add(mut self, epoll_fd: RawFd, data: u64) -> Result<Self> {
|
||||
use nix::fcntl::{OFlag, fcntl, FcntlArg};
|
||||
|
||||
if None != self.epoll_fd {
|
||||
return Err(Error::EpollAlreadyAdded);
|
||||
}
|
||||
let raw_fd = self.device_file.as_raw_fd();
|
||||
let flags = unsafe {
|
||||
// https://github.com/nix-rust/nix/issues/1102
|
||||
OFlag::from_bits_unchecked(fcntl(raw_fd, FcntlArg::F_GETFL)?)
|
||||
};
|
||||
fcntl(raw_fd, FcntlArg::F_SETFL(flags | OFlag::O_NONBLOCK))?;
|
||||
|
||||
let epoll_event = epoll::Event::new(epoll::Events::EPOLLIN | epoll::Events::EPOLLET, data);
|
||||
epoll::ctl(epoll_fd, epoll::ControlOptions::EPOLL_CTL_ADD, raw_fd, epoll_event)?;
|
||||
self.epoll_fd = Some(epoll_fd);
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
#[cfg(feature = "epoll_inotify")]
|
||||
pub fn epoll_del(&mut self) -> Result<&mut Self> {
|
||||
if let Some(epoll_fd) = self.epoll_fd {
|
||||
// set this to None first, if we end up returning an Err early, we can't do anything else anyway...
|
||||
self.epoll_fd = None;
|
||||
let empty_event = epoll::Event::new(epoll::Events::empty(), 0);
|
||||
epoll::ctl(epoll_fd, epoll::ControlOptions::EPOLL_CTL_DEL, self.device_file.as_raw_fd(), empty_event)?;
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for InputDevice {
|
||||
fn drop(&mut self) {
|
||||
self.release().ok(); // ignore any errors here, what could we do anyhow?
|
||||
// ignore any errors here, what could we do anyhow?
|
||||
self.release().ok();
|
||||
#[cfg(feature = "epoll_inotify")]
|
||||
self.epoll_del().ok();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
mod builder;
|
||||
pub use self::builder::Builder;
|
||||
|
||||
pub mod codes;
|
||||
pub use codes::*;
|
||||
|
||||
mod device;
|
||||
pub use self::device::Device;
|
||||
|
||||
|
250
src/linux/mod.rs
250
src/linux/mod.rs
@ -1,26 +1,18 @@
|
||||
|
||||
use crate::*;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::linux::device::codes::*;
|
||||
|
||||
pub mod device;
|
||||
pub use device::{Device,InputDevice};
|
||||
pub use device::{Device,InputDevice, Builder};
|
||||
|
||||
/// Open the default uinput device.
|
||||
pub fn default() -> Result<device::Builder> {
|
||||
device::Builder::default()
|
||||
}
|
||||
|
||||
/// Open the specified uinput device.
|
||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<device::Builder> {
|
||||
device::Builder::open(path)
|
||||
}
|
||||
|
||||
use uinput_sys::*;
|
||||
use libc::input_event;
|
||||
use std::process::exit;
|
||||
use std::{env, thread};
|
||||
use std::sync::mpsc;
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::env;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[cfg(feature = "epoll_inotify")]
|
||||
const INPUT_FOLDER: &str = "/dev/input/";
|
||||
|
||||
// 1 is down, 0 is up
|
||||
const DOWN: i32 = 1;
|
||||
@ -28,13 +20,6 @@ const UP: i32 = 0;
|
||||
|
||||
use getopts::Options;
|
||||
|
||||
use inotify::{
|
||||
EventMask,
|
||||
Inotify,
|
||||
WatchMask,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
const EV_KEY_U16: u16 = EV_KEY as u16;
|
||||
|
||||
type LinuxKeyMaps = KeyMaps<Device, u16, input_event>;
|
||||
@ -98,8 +83,6 @@ impl Keyboard<u16, input_event> for Device {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Config {
|
||||
device_files: Vec<String>,
|
||||
@ -119,88 +102,133 @@ pub fn main_res() -> Result<()> {
|
||||
let key_map = key_map();
|
||||
//println!("key_map: {:?}", key_map);
|
||||
|
||||
let device = open("/dev/uinput")
|
||||
.or_else(|_| open("/dev/input/uinput"))
|
||||
.or_else(|_| default())?
|
||||
.name("rusty-keys")?
|
||||
let device = Builder::open("/dev/uinput")
|
||||
.or_else(|_| Builder::open("/dev/input/uinput"))
|
||||
.or_else(|_| Builder::default())?
|
||||
.name(NAME)?
|
||||
.event(key_map.values())?
|
||||
.create()?;
|
||||
|
||||
#[cfg(not(feature = "toml_serde"))]
|
||||
let mut key_map = LinuxKeyMaps::new(&key_map, KeymapConfig::default());
|
||||
#[cfg(feature = "toml_serde")]
|
||||
let mut key_map = LinuxKeyMaps::from_cfg(&key_map, &config.config_file);
|
||||
//println!("keymaps: {:?}", keymaps);
|
||||
|
||||
let mut input_event_buf = InputDevice::new_input_event_buf();
|
||||
|
||||
if config.device_files.len() == 1 {
|
||||
// shortcut, don't bother with threads
|
||||
let mut input_device = InputDevice::open(&config.device_files[0])?;
|
||||
input_device.grab()?;
|
||||
// shortcut, don't bother with epoll
|
||||
let mut input_device = InputDevice::open(&config.device_files[0])?.grab()?;
|
||||
|
||||
loop {
|
||||
let event = input_device.read_event()?;
|
||||
let event = input_device.read_event(&mut input_event_buf)?;
|
||||
send_event(&mut key_map, event, &device)?
|
||||
}
|
||||
} else {
|
||||
// start up some intra thread communication
|
||||
let (tx, rx) = mpsc::channel();
|
||||
#[cfg(not(feature = "epoll_inotify"))]
|
||||
panic!("without epoll_inotify feature, only exactly 1 device is supported");
|
||||
|
||||
if config.device_files.len() > 0 {
|
||||
// we only want to operate on device files sent in then quit
|
||||
for device_file in config.device_files.iter() {
|
||||
let device_file = device_file.clone();
|
||||
let tx = tx.clone();
|
||||
thread::spawn(move || {
|
||||
let ret = spawn_map_thread(tx, &device_file);
|
||||
if let Err(e) = ret {
|
||||
println!("mapping for {} ended due to error: {}", device_file, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
let tx = tx.clone();
|
||||
thread::spawn(move || {
|
||||
// we want to wait forever starting new threads for any new keyboard devices
|
||||
let mut inotify = Inotify::init().expect("Failed to initialize inotify");
|
||||
#[cfg(feature = "epoll_inotify")]
|
||||
{
|
||||
use inotify::{Inotify, WatchMask};
|
||||
|
||||
inotify.add_watch("/dev/input/", WatchMask::CREATE).expect("Failed to add inotify watch");
|
||||
let epoll_fd = epoll::create(true)?;
|
||||
const INOTIFY_DATA: u64 = u64::max_value();
|
||||
|
||||
let device_files = get_keyboard_device_filenames();
|
||||
println!("Detected devices: {:?}", device_files);
|
||||
for device_file in device_files.iter() {
|
||||
inotify_spawn_thread(&tx, device_file);
|
||||
let (device_files, mut inotify) = if config.device_files.len() > 0 {
|
||||
// we operate on exactly the devices sent in and never watch for new devices
|
||||
(config.device_files.iter().map(|device_file| InputDevice::open(&device_file).expect("device_file does not exist!")).collect(), None)
|
||||
} else {
|
||||
use std::os::unix::io::AsRawFd;
|
||||
// we want to wait forever starting new threads for any new keyboard devices
|
||||
// there is a slight race condition here, if a keyboard is plugged in between the time we
|
||||
// enumerate the devices and set up the inotify watch, we'll miss it, doing it the other way
|
||||
// can bring duplicates though, todo: think about this...
|
||||
let device_files = get_keyboard_devices();
|
||||
let mut inotify = Inotify::init()?;
|
||||
inotify.add_watch(INPUT_FOLDER, WatchMask::CREATE)?;
|
||||
let epoll_event = epoll::Event::new(epoll::Events::EPOLLIN | epoll::Events::EPOLLET, INOTIFY_DATA);
|
||||
epoll::ctl(epoll_fd, epoll::ControlOptions::EPOLL_CTL_ADD, inotify.as_raw_fd(), epoll_event)?;
|
||||
(device_files, Some(inotify))
|
||||
};
|
||||
let mut input_devices = Vec::with_capacity(device_files.len());
|
||||
for (idx, device_file) in device_files.into_iter().enumerate() {
|
||||
input_devices.push(Some(device_file.grab()?.epoll_add(epoll_fd, idx as u64)?));
|
||||
}
|
||||
|
||||
let mut buffer = [0u8; 4096];
|
||||
loop {
|
||||
let events = inotify.read_events_blocking(&mut buffer);
|
||||
let mut epoll_buf = [epoll::Event::new(epoll::Events::empty(), 0); 4];
|
||||
let mut inotify_buf = [0u8; 256];
|
||||
|
||||
if let Ok(events) = events {
|
||||
for event in events {
|
||||
if !event.mask.contains(EventMask::ISDIR) {
|
||||
if let Some(device_file) = event.name.and_then(|name|name.to_str()) {
|
||||
// check if this is an eligible keyboard device
|
||||
let device_files = get_keyboard_device_filenames();
|
||||
if !device_files.contains(&device_file.to_string()) {
|
||||
continue;
|
||||
loop {
|
||||
let num_events = epoll::wait(epoll_fd, -1, &mut epoll_buf)?;
|
||||
for event in &epoll_buf[0..num_events] {
|
||||
let idx = event.data as usize;
|
||||
if let Some(Some(input_device)) = &mut input_devices.get_mut(idx) {
|
||||
loop {
|
||||
match input_device.read_event(&mut input_event_buf) {
|
||||
Ok(event) => {
|
||||
//println!("input event: {:?}", event);
|
||||
send_event(&mut key_map, event, &device)?
|
||||
}
|
||||
Err(err) => {
|
||||
if let Error::Io(ref err) = err {
|
||||
if err.kind() == std::io::ErrorKind::WouldBlock {
|
||||
// go back to epoll event loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
// otherwise it's some other error, don't read anything from this again
|
||||
println!("input err: {:?}", err);
|
||||
// remove it from input_devices and drop it
|
||||
let _ = std::mem::replace(&mut input_devices[idx], None);
|
||||
if inotify.is_none() {
|
||||
// if we aren't watching with inotify, and the last device is removed (Vec only has None's in it), exit the program
|
||||
if input_devices.iter().all(|id| id.is_none()) {
|
||||
println!("last device went away, exiting...");
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if event.data == INOTIFY_DATA {
|
||||
if let Some(inotify) = &mut inotify {
|
||||
for event in inotify.read_events(&mut inotify_buf)? {
|
||||
if let Some(device_file) = event.name.and_then(|name| name.to_str()) {
|
||||
// check if this is an eligible keyboard device
|
||||
let mut path = std::path::PathBuf::new();
|
||||
path.push(INPUT_FOLDER);
|
||||
path.push(device_file);
|
||||
|
||||
if let Ok(input_device) = InputDevice::open(path).and_then(|id| id.valid_keyboard_device()) {
|
||||
println!("starting mapping for new keyboard: {}", device_file);
|
||||
|
||||
let idx = input_devices.iter().position(|id| id.is_none()).unwrap_or(input_devices.len());
|
||||
|
||||
let input_device = input_device.grab()?.epoll_add(epoll_fd, idx as u64)?;
|
||||
|
||||
if idx == input_devices.len() {
|
||||
input_devices.push(Some(input_device));
|
||||
} else {
|
||||
// simply replacing None here
|
||||
let _ = std::mem::replace(&mut input_devices[idx], Some(input_device));
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("starting mapping thread for: {}", device_file);
|
||||
inotify_spawn_thread(&tx, device_file.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
drop(tx); // drop our last one, so when the threads finish, everything stops
|
||||
// process all events
|
||||
for event in rx {
|
||||
send_event(&mut key_map, event, &device)?
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn send_event(key_map: &mut LinuxKeyMaps, mut event: input_event, device: &Device) -> Result<()> {
|
||||
if event.type_ == EV_KEY_U16 {
|
||||
// println!("type: {} code: {:?} value: {:?}", event.type_, event.code(), event.value());
|
||||
key_map.send_event(&mut event, &device)?
|
||||
} else {
|
||||
device.write_event(&mut event)?
|
||||
@ -208,28 +236,6 @@ fn send_event(key_map: &mut LinuxKeyMaps, mut event: input_event, device: &Devic
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn inotify_spawn_thread(tx: &Sender<input_event>, device_file: &str) {
|
||||
let mut filename = "/dev/input/".to_string();
|
||||
filename.push_str(&device_file);
|
||||
let tx = tx.clone();
|
||||
thread::spawn(move || {
|
||||
let ret = spawn_map_thread(tx, &filename);
|
||||
if let Err(e) = ret {
|
||||
println!("mapping for {} ended due to error: {}", filename, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn spawn_map_thread(tx: Sender<input_event>, device_file: &str) -> Result<()> {
|
||||
let mut input_device = InputDevice::open(device_file)?;
|
||||
input_device.grab()?;
|
||||
|
||||
loop {
|
||||
let event = input_device.read_event()?;
|
||||
tx.send(event)?
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_args() -> Config {
|
||||
fn print_usage(program: &str, opts: Options) {
|
||||
let brief = format!("Usage: {} [options] [device_files...]", program);
|
||||
@ -255,7 +261,7 @@ fn parse_args() -> Config {
|
||||
}
|
||||
|
||||
if matches.opt_present("v") {
|
||||
println!("rusty-keys {}", VERSION);
|
||||
println!("{} {}", NAME, VERSION);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@ -264,43 +270,25 @@ fn parse_args() -> Config {
|
||||
Config::new(matches.free, config_file)
|
||||
}
|
||||
|
||||
// Detects and returns the name of the keyboard device file. This function uses
|
||||
// the fact that all device information is shown in /proc/bus/input/devices and
|
||||
// the keyboard device file should always have an EV of 120013
|
||||
// grep -E 'Handlers|EV' /proc/bus/input/devices | grep -B1 120013 | grep -Eo event[0-9]+
|
||||
fn get_keyboard_device_filenames() -> Vec<String> {
|
||||
use std::io::BufReader;
|
||||
use std::io::prelude::*;
|
||||
use std::fs::File;
|
||||
|
||||
let f = File::open("/proc/bus/input/devices");
|
||||
if f.is_err() {
|
||||
return Vec::new();
|
||||
}
|
||||
let f = BufReader::new(f.unwrap());
|
||||
let mut filename = None;
|
||||
let mut filenames = Vec::new();
|
||||
for line in f.lines() {
|
||||
if let Ok(line) = line {
|
||||
if line.starts_with("H: Handlers=") {
|
||||
if let Some(event_index) = line.find("event") {
|
||||
let last_index = line[event_index..line.len()-1].find(" ").and_then(|i| Some(i + event_index)).unwrap_or(line.len() - 1);
|
||||
filename = Some(line[event_index..last_index].to_owned());
|
||||
}
|
||||
} else if line.starts_with("B: EV=") && line.contains("120013") {
|
||||
if let Some(ref filename) = filename {
|
||||
filenames.push(filename.clone());
|
||||
#[cfg(feature = "epoll_inotify")]
|
||||
fn get_keyboard_devices() -> Vec<InputDevice> {
|
||||
let mut res = Vec::new();
|
||||
if let Ok(entries) = std::fs::read_dir(INPUT_FOLDER) {
|
||||
for entry in entries {
|
||||
if let Ok(entry) = entry {
|
||||
if let Ok(input_device) = InputDevice::open(entry.path()).and_then(|id|id.valid_keyboard_device()) {
|
||||
res.push(input_device);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
filenames
|
||||
res
|
||||
}
|
||||
|
||||
pub fn key_map() -> HashMap<&'static str, u16> {
|
||||
[
|
||||
// generated like:
|
||||
// grep -o 'KEY_[^ :;]*' ~/.cargo/registry/src/github.com-1ecc6299db9ec823/uinput-sys-0.1.3/src/events.rs | sed 's/^KEY_//' | awk '{print "(\""$1"\", KEY_"$1"),"}'
|
||||
// grep -o 'KEY_[^ :;]*' ~/.cargo/registry/src/github.com-1ecc6299db9ec823/uinput-sys-0.1.3/src/codes | sed 's/^KEY_//' | awk '{print "(\""$1"\", KEY_"$1"),"}'
|
||||
("RESERVED", KEY_RESERVED),
|
||||
("ESC", KEY_ESC),
|
||||
("1", KEY_1),
|
||||
@ -605,5 +593,7 @@ pub fn key_map() -> HashMap<&'static str, u16> {
|
||||
("P0", KEY_KP0),
|
||||
("PDOT", KEY_KPDOT),
|
||||
("PENT", KEY_KPENTER),
|
||||
("TOUCHPAD_TOGGLE", KEY_TOUCHPAD_TOGGLE),
|
||||
].iter().cloned().map(|(m, v)| (m, v as u16)).collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ pub const KEY_KPPLUS: CGKeyCode = 0x0045;
|
||||
pub const KEY_KP1: CGKeyCode = 0x0053;
|
||||
pub const KEY_KP2: CGKeyCode = 0x0054;
|
||||
pub const KEY_KP3: CGKeyCode = 0x0055;
|
||||
pub const KEY_KP0: CGKeyCode = 0x0052;
|
||||
pub const KEY_KP0: CGKeyCode = 0x0052; // https://code-with-me.jetbrains.com/UCsz0dzSd1QAbmOi8g0V3w#p=IC&fp=6298EDAF97FA62E9897E2556D1A6631FB66974568C7252E696472EE85078E8A0
|
||||
pub const KEY_KPDOT: CGKeyCode = 0x0041;
|
||||
// pub const KEY_ZENKAKUHANKAKU: CGKeyCode = NOT_FOUND;
|
||||
pub const KEY_102ND: CGKeyCode = 0x000A;
|
||||
@ -96,7 +96,7 @@ pub const KEY_F12: CGKeyCode = 0x006F;
|
||||
// pub const KEY_HENKAN: CGKeyCode = NOT_FOUND;
|
||||
// pub const KEY_KATAKANAHIRAGANA: CGKeyCode = NOT_FOUND;
|
||||
// pub const KEY_MUHENKAN: CGKeyCode = NOT_FOUND;
|
||||
// pub const KEY_KPJPCOMMA: CGKeyCode = NOT_FOUND;
|
||||
// pub const KEY_KPJPCOMMA: CGKeyCode = NOT_FOUND; // https://code-with-me.jetbrains.com/Mf59EFUeJZQ2mpGCCCjNWw#p=IC&fp=6298EDAF97FA62E9897E2556D1A6631FB66974568C7252E696472EE85078E8A0
|
||||
pub const KEY_KPENTER: CGKeyCode = 0x004C;
|
||||
pub const KEY_RIGHTCTRL: CGKeyCode = 0x003E;
|
||||
pub const KEY_KPSLASH: CGKeyCode = 0x004B;
|
||||
@ -120,15 +120,15 @@ pub const KEY_DELETE: CGKeyCode = 0x0075;
|
||||
// pub const KEY_POWER: CGKeyCode = NOT_FOUND;
|
||||
pub const KEY_KPEQUAL: CGKeyCode = 0x0069;
|
||||
// pub const KEY_KPPLUSMINUS: CGKeyCode = NOT_FOUND;
|
||||
// pub const KEY_PAUSE: CGKeyCode = NOT_FOUND;
|
||||
pub const KEY_PAUSE: CGKeyCode = KEY_LINEFEED;
|
||||
pub const KEY_SCALE: CGKeyCode = 0x0047;
|
||||
pub const KEY_KPCOMMA: CGKeyCode = 0x0036;
|
||||
// pub const KEY_HANGEUL: CGKeyCode = NOT_FOUND;
|
||||
// pub const KEY_HANGUEL: CGKeyCode = NOT_FOUND;
|
||||
// pub const KEY_HANGEUL: CGKeyCode = NOT_FOUND;
|
||||
// pub const KEY_HANJA: CGKeyCode = NOT_FOUND;
|
||||
pub const KEY_YEN: CGKeyCode = 0x0037;
|
||||
// pub const KEY_LEFTMETA: CGKeyCode = NOT_FOUND;
|
||||
//pub const KEY_YEN: CGKeyCode = NOT_FOUND;
|
||||
pub const KEY_LEFTMETA: CGKeyCode = 0x0037;
|
||||
pub const KEY_RIGHTMETA: CGKeyCode = 0x0036;
|
||||
pub const KEY_COMPOSE: CGKeyCode = 0x006E;
|
||||
// pub const KEY_STOP: CGKeyCode = NOT_FOUND;
|
||||
@ -516,7 +516,7 @@ pub fn key_map() -> HashMap<&'static str, CGKeyCode> {
|
||||
// below manual shortcuts
|
||||
("PSCR", KEY_SYSRQ),
|
||||
("SLCK", KEY_SCROLLLOCK),
|
||||
//("BRK", KEY_PAUSE),
|
||||
("BRK", KEY_PAUSE),
|
||||
("GRV", KEY_GRAVE),
|
||||
("0", KEY_10), // dumb or named wrong?
|
||||
("MINS", KEY_MINUS),
|
||||
@ -540,7 +540,7 @@ pub fn key_map() -> HashMap<&'static str, CGKeyCode> {
|
||||
("RCTL", KEY_RIGHTCTRL),
|
||||
("LALT", KEY_LEFTALT),
|
||||
("RALT", KEY_RIGHTALT),
|
||||
//("LGUI", KEY_LEFTMETA),
|
||||
("LGUI", KEY_LEFTMETA),
|
||||
("RGUI", KEY_RIGHTMETA),
|
||||
("INS", KEY_INSERT),
|
||||
("PGUP", KEY_PAGEUP),
|
||||
|
401
src/macos/mod.rs
401
src/macos/mod.rs
@ -9,126 +9,114 @@ use std::process::exit;
|
||||
|
||||
use getopts::Options;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
|
||||
pub mod codes;
|
||||
use codes::*;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use std::sync::Mutex;
|
||||
use core_graphics::event::CGKeyCode;
|
||||
use core_graphics::event::*;
|
||||
use core_graphics::event_source::*;
|
||||
use core_foundation_sys::*;
|
||||
use core_foundation_sys::base::*;
|
||||
use core_foundation_sys::runloop::*;
|
||||
|
||||
use core_graphics::event::{CGEventTapLocation, CGEventType};
|
||||
|
||||
type MacOSKeyMaps = KeyMaps<CGEventSource, CGKeyCode, CGEvent, Option<CGEvent>>;
|
||||
type CallbackPointer = (MacOSKeyMaps, CGEventSource);
|
||||
|
||||
/*
|
||||
extern {
|
||||
/// Return the type identifier for the opaque type `CGEventRef'.
|
||||
//fn CGEventGetTypeID() -> CFTypeID;
|
||||
pub fn CFRunLoopRun();
|
||||
}
|
||||
*/
|
||||
// possible types for event_source
|
||||
Private = -1,
|
||||
CombinedSessionState = 0,
|
||||
HIDSystemState = 1,
|
||||
|
||||
type MacOSKeyMaps = KeyMaps<Device, CGKeyCode, InputEvent, Option<CGEventRef>>;
|
||||
// possible types for tapLocation
|
||||
HID,
|
||||
Session,
|
||||
AnnotatedSession,
|
||||
*/
|
||||
|
||||
// this is used for identifying the fake keypresses we insert, so we don't process them in an infinite loop
|
||||
//const FAKE_EXTRA_INFO: ULONG_PTR = 332;
|
||||
// macOS seems to require this, or it ignores shift, WHY?
|
||||
const delay: std::time::Duration = std::time::Duration::from_millis(20);
|
||||
const tapLocation: CGEventTapLocation = CGEventTapLocation::Session;
|
||||
// this is only used if tapLocation is HID, to prevent us from mapping our own key inputs
|
||||
const uniqueHIDUserData: i64 = 45;
|
||||
|
||||
//const BLOCK_KEY: *const CGEventRef = std::ptr::null();
|
||||
//const BLOCK_KEY: *mut CGEventRef = std::ptr::null_mut();
|
||||
|
||||
pub struct InputEvent {
|
||||
event_type: CGEventType,
|
||||
event: CGEventRef,
|
||||
}
|
||||
|
||||
impl KeyEvent<CGKeyCode> for InputEvent {
|
||||
impl KeyEvent<CGKeyCode> for CGEvent {
|
||||
fn code(&self) -> CGKeyCode {
|
||||
//1
|
||||
//self.event.to_owned().get_integer_value_field(EventField::KEYBOARD_EVENT_KEYCODE) as CGKeyCode
|
||||
unsafe { CGEventGetIntegerValueField(self.event, kCGKeyboardEventKeycode) }
|
||||
self.get_integer_value_field(EventField::KEYBOARD_EVENT_KEYCODE) as CGKeyCode
|
||||
}
|
||||
/*
|
||||
fn set_code(&self, code: CGKeyCode) {
|
||||
//1
|
||||
//self.event.to_owned().get_integer_value_field(EventField::KEYBOARD_EVENT_KEYCODE) as CGKeyCode
|
||||
unsafe { CGEventSetIntegerValueField(self.event, kCGKeyboardEventKeycode) }
|
||||
}
|
||||
*/
|
||||
|
||||
fn value(&self) -> KeyState {
|
||||
match self.event_type {
|
||||
kCGEventFlagsChanged => KeyState::DOWN,
|
||||
kCGEventKeyDown => KeyState::DOWN,
|
||||
kCGEventKeyUp => KeyState::UP,
|
||||
kCGEventTapDisabledByTimeout => {
|
||||
let event_type = self.get_type();
|
||||
match event_type {
|
||||
CGEventType::FlagsChanged => {
|
||||
let flags = self.get_flags().bits(); // todo: fix cast?
|
||||
let mask = match self.code() {
|
||||
KEY_LEFTCTRL => NX_DEVICELCTLKEYMASK,
|
||||
KEY_RIGHTCTRL => NX_DEVICERCTLKEYMASK,
|
||||
KEY_LEFTSHIFT => NX_DEVICELSHIFTKEYMASK,
|
||||
KEY_RIGHTSHIFT => NX_DEVICERSHIFTKEYMASK,
|
||||
KEY_LEFTMETA => NX_DEVICELCMDKEYMASK,
|
||||
KEY_RIGHTMETA => NX_DEVICERCMDKEYMASK,
|
||||
KEY_LEFTALT => NX_DEVICELALTKEYMASK,
|
||||
KEY_RIGHTALT => NX_DEVICERALTKEYMASK,
|
||||
KEY_CAPSLOCK => NX_DEVICECAPSLOCKMASK,
|
||||
_ => panic!("unhandled key: {}", self.code()),
|
||||
};
|
||||
if (flags & mask) != 0 { KeyState::DOWN } else { KeyState::UP }
|
||||
},
|
||||
CGEventType::KeyDown => KeyState::DOWN,
|
||||
CGEventType::KeyUp => KeyState::UP,
|
||||
CGEventType::TapDisabledByTimeout => {
|
||||
println!("Quartz event tap disabled because of timeout; attempting to reregister.");
|
||||
todo!("implement register listener");
|
||||
//register_listener(channel);
|
||||
KeyState::OTHER
|
||||
//KeyState::OTHER
|
||||
},
|
||||
_ => {
|
||||
println!("Received unknown EventType: {}", self.event_type);
|
||||
println!("Received unknown EventType: {:?}", event_type);
|
||||
KeyState::OTHER
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum DeviceRet {
|
||||
EVENT(CGEventRef),
|
||||
NULL,
|
||||
}
|
||||
|
||||
pub struct Device;
|
||||
|
||||
impl Keyboard<CGKeyCode, InputEvent, Option<CGEventRef>> for Device {
|
||||
fn send(&self, event: &mut InputEvent) -> Result<Option<CGEventRef>> {
|
||||
println!("send orig: {}", event.code());
|
||||
Ok(Some(event.event))
|
||||
}
|
||||
|
||||
fn send_mod_code(&self, code: CGKeyCode, event: &mut InputEvent) -> Result<Option<CGEventRef>> {
|
||||
// event.value should only ever be UP/DOWN when this method is called
|
||||
println!("send_mod_code orig: {} code: {}", event.code(), code);
|
||||
//event.event.set_integer_value_field();
|
||||
//unsafe { CGEventSetIntegerValueField(event.event, kCGKeyboardEventKeycode, code as i64) };
|
||||
impl Keyboard<CGKeyCode, CGEvent, Option<CGEvent>> for CGEventSource {
|
||||
fn send(&self, event: &mut CGEvent) -> Result<Option<CGEvent>> {
|
||||
//println!("send orig: {}", event.code());
|
||||
|
||||
//Ok(Some(event.event))
|
||||
//Ok(None)
|
||||
|
||||
self.send_mod_code_value(event.code(), event.value() == KeyState::UP, event)
|
||||
}
|
||||
|
||||
fn send_mod_code(&self, code: CGKeyCode, event: &mut CGEvent) -> Result<Option<CGEvent>> {
|
||||
// event.value should only ever be UP/DOWN when this method is called
|
||||
//println!("send_mod_code orig: {} code: {}", event.code(), code);
|
||||
|
||||
//unsafe { CGEventSetIntegerValueField(event.event, kCGKeyboardEventKeycode, code as i64) };
|
||||
//Ok(Some(event.event))
|
||||
|
||||
self.send_mod_code_value(code, event.value() == KeyState::UP, event)
|
||||
}
|
||||
|
||||
fn send_mod_code_value(&self, code: CGKeyCode, up_not_down: bool, event: &mut InputEvent) -> Result<Option<CGEventRef>> {
|
||||
println!("send_mod_code_value orig: {} code: {}, up_not_down: {}", event.code(), code, up_not_down);
|
||||
|
||||
// https://github.com/enigo-rs/enigo/blob/master/src/macos/macos_impl.rs
|
||||
/*
|
||||
let event_source = CGEventSource::new(CGEventSourceStateID::CombinedSessionState)
|
||||
.expect("Failed creating event source");
|
||||
fn send_mod_code_value(&self, code: CGKeyCode, up_not_down: bool, _event: &mut CGEvent) -> Result<Option<CGEvent>> {
|
||||
//println!("send_mod_code_value orig: {} code: {}, up_not_down: {}", event.code(), code, up_not_down);
|
||||
//return Ok(None);
|
||||
|
||||
let event =
|
||||
CGEvent::new_keyboard_event(event_source.clone(), code, !up_not_down)
|
||||
CGEvent::new_keyboard_event(self.clone(), code, !up_not_down)
|
||||
.expect("Failed creating event");
|
||||
event.post(CGEventTapLocation::HID);
|
||||
*/
|
||||
match tapLocation {
|
||||
CGEventTapLocation::HID => event.set_integer_value_field(EventField::EVENT_SOURCE_USER_DATA, uniqueHIDUserData),
|
||||
_ => {}
|
||||
};
|
||||
event.post(tapLocation);
|
||||
|
||||
unsafe { CGEventSetIntegerValueField(event.event, kCGKeyboardEventKeycode, code as i64) };
|
||||
|
||||
|
||||
let flags = unsafe { CGEventGetFlags(event.event) };
|
||||
print_flags(flags);
|
||||
let flags = flags >> NX_DEVICERSHIFTKEYMASK;
|
||||
print_flags(flags);
|
||||
//CGEventSetFlags(event, flags);
|
||||
|
||||
Ok(Some(event.event))
|
||||
//Ok(None)
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn synchronize(&self) -> Result<Option<CGEventRef>> {
|
||||
// no-op here
|
||||
fn synchronize(&self) -> Result<Option<CGEvent>> {
|
||||
std::thread::sleep(delay);
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
@ -144,55 +132,25 @@ impl Keyboard<CGKeyCode, InputEvent, Option<CGEventRef>> for Device {
|
||||
KEY_CAPSLOCK
|
||||
}
|
||||
|
||||
fn block_key(&self) -> Result<Option<CGEventRef>> {
|
||||
fn block_key(&self) -> Result<Option<CGEvent>> {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Send for MacOSKeyMaps {
|
||||
// windows promises us keybd_proc will only be called by a single thread at a time
|
||||
// but rust makes us wrap in mutex anyway, so we are extra safe...
|
||||
}
|
||||
|
||||
const DEVICE: Device = Device;
|
||||
|
||||
/*
|
||||
lazy_static! {
|
||||
static ref KEY_MAPPER: Mutex<MacOSKeyMaps> = {
|
||||
|
||||
pub fn main_res() -> Result<()> {
|
||||
let config = parse_args();
|
||||
//println!("Config: {:?}", config);
|
||||
|
||||
let key_map = key_map();
|
||||
//println!("key_map: {:?}", key_map);
|
||||
|
||||
println!("chosen config file: {}", config.config_file);
|
||||
|
||||
Mutex::new(MacOSKeyMaps::from_cfg(&key_map, &config.config_file))
|
||||
};
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
pub fn main_res() -> Result<()> {
|
||||
// this is just to cause the lazy_static init to run first, so if -h or -v is wanted, we do that
|
||||
// and exit immediately... todo: how to avoid mutex/lazy_static entirely???
|
||||
//let _ = KEY_MAPPER.lock().unwrap();
|
||||
|
||||
let config = parse_args();
|
||||
println!("Config: {:?}", config);
|
||||
|
||||
let key_map = key_map();
|
||||
println!("key_map: {:?}", key_map);
|
||||
|
||||
println!("chosen config file: {}", config.config_file);
|
||||
|
||||
let key_maps = MacOSKeyMaps::from_cfg(&key_map, &config.config_file);
|
||||
//println!("key_maps: {}", key_maps);
|
||||
let callback_pointer: CallbackPointer = (key_maps, CGEventSource::new(CGEventSourceStateID::Private).expect("Failed creating event source"));
|
||||
|
||||
let mask = CGEventMaskBit(kCGEventKeyDown)
|
||||
| CGEventMaskBit(kCGEventKeyUp)
|
||||
| CGEventMaskBit(kCGEventFlagsChanged)
|
||||
let mask = CGEventMaskBit(CGEventType::KeyDown)
|
||||
| CGEventMaskBit(CGEventType::KeyUp)
|
||||
| CGEventMaskBit(CGEventType::FlagsChanged)
|
||||
;
|
||||
|
||||
unsafe {
|
||||
@ -205,10 +163,11 @@ pub fn main_res() -> Result<()> {
|
||||
options,
|
||||
mask,
|
||||
callback,
|
||||
&key_maps,
|
||||
&callback_pointer,
|
||||
);
|
||||
assert!(!event_tap.is_null(),
|
||||
"Unable to create event tap. Please make sure you have the correct permissions");
|
||||
if event_tap.is_null() {
|
||||
panic!("Unable to create event tap. Please make sure you have the correct permissions");
|
||||
}
|
||||
println!("Created event tap...");
|
||||
|
||||
let allocator = kCFAllocatorDefault;
|
||||
@ -308,44 +267,22 @@ fn parse_args() -> Config {
|
||||
}
|
||||
|
||||
use libc;
|
||||
use core_graphics::event::CGEventType::Null;
|
||||
|
||||
// Opaque Pointer Types
|
||||
pub type Pointer = *mut libc::c_void;
|
||||
pub type CGEventRef = Pointer;
|
||||
pub type CFMachPortRef = Pointer;
|
||||
type Pointer = *mut libc::c_void;
|
||||
type CFMachPortRef = Pointer;
|
||||
|
||||
// Integer Types
|
||||
pub type CGEventField = u32;
|
||||
pub type CGEventMask = u64;
|
||||
pub type CGEventTapLocation = u32;
|
||||
pub type CGEventTapOptions = u32;
|
||||
pub type CGEventTapPlacement = u32;
|
||||
pub type CGEventType = u32;
|
||||
pub type CGEventFlags = u64;
|
||||
//pub type CGKeyCode = u16;
|
||||
type CGEventMask = u64;
|
||||
type CGEventTapOptions = u32;
|
||||
type CGEventTapPlacement = u32;
|
||||
|
||||
// Callback Type
|
||||
pub type CGEventTapCallBack = extern "C"
|
||||
fn(Pointer, CGEventType, CGEventRef, &mut MacOSKeyMaps) -> CGEventRef;
|
||||
type CGEventTapCallBack = extern "C" fn(Pointer, CGEventType, CGEvent, &mut CallbackPointer) -> CGEvent;
|
||||
|
||||
// Constants
|
||||
/*
|
||||
pub const kCGEventKeyDown: CGEventType = CGEventType::KeyDown;
|
||||
pub const kCGEventKeyUp: CGEventType = CGEventType::KeyUp;
|
||||
pub const kCGEventFlagsChanged: CGEventType = CGEventType::FlagsChanged;
|
||||
pub const kCGSessionEventTap: CGEventTapLocation = 1;
|
||||
pub const kCGHeadInsertEventTap: CGEventTapPlacement = 0;
|
||||
pub const kCGKeyboardEventKeycode: CGEventField = 9;
|
||||
pub const kCGEventTapDisabledByTimeout: CGEventType = CGEventType::TapDisabledByTimeout;
|
||||
*/
|
||||
pub const kCGEventKeyDown: CGEventType = 10;
|
||||
pub const kCGEventKeyUp: CGEventType = 11;
|
||||
pub const kCGEventFlagsChanged: CGEventType = 12;
|
||||
pub const kCGSessionEventTap: CGEventTapLocation = 1;
|
||||
pub const kCGHeadInsertEventTap: CGEventTapPlacement = 0;
|
||||
pub const kCGKeyboardEventKeycode: CGEventField = 9;
|
||||
pub const kCGEventTapDisabledByTimeout: CGEventType = 0xFFFFFFFE;
|
||||
const kCGSessionEventTap: CGEventTapLocation = CGEventTapLocation::HID;
|
||||
const kCGHeadInsertEventTap: CGEventTapPlacement = 0;
|
||||
|
||||
// Link to ApplicationServices/ApplicationServices.h and Carbon/Carbon.h
|
||||
#[link(name = "ApplicationServices", kind = "framework")]
|
||||
@ -364,14 +301,6 @@ pub const kCGEventTapDisabledByTimeout: CGEventType = 0xFFFFFFFE;
|
||||
/// Obtain the current threads loop
|
||||
pub fn CFRunLoopGetCurrent() -> Pointer;
|
||||
|
||||
/// Get the code of the event back, e.g. the key code
|
||||
pub fn CGEventGetIntegerValueField(
|
||||
event: CGEventRef,
|
||||
field: CGEventField,
|
||||
) -> CGKeyCode;
|
||||
|
||||
fn CGEventSetIntegerValueField(event: CGEventRef, field: CGEventField, value: i64);
|
||||
|
||||
/// Create an event tap
|
||||
///
|
||||
/// # Arguments
|
||||
@ -419,7 +348,7 @@ pub const kCGEventTapDisabledByTimeout: CGEventType = 0xFFFFFFFE;
|
||||
options: CGEventTapOptions,
|
||||
eventsOfInterest: CGEventMask,
|
||||
callback: CGEventTapCallBack,
|
||||
channel: &MacOSKeyMaps,
|
||||
channel: &CallbackPointer,
|
||||
) -> CFMachPortRef;
|
||||
|
||||
/// Creates a CFRunLoopSource object for a CFMachPort
|
||||
@ -442,150 +371,44 @@ pub const kCGEventTapDisabledByTimeout: CGEventType = 0xFFFFFFFE;
|
||||
);
|
||||
|
||||
pub fn CGEventTapEnable(port: CFMachPortRef, enable: bool);
|
||||
|
||||
pub fn CGEventGetType(event: CGEventRef) -> CGEventType;
|
||||
pub fn CGEventGetFlags(event: CGEventRef) -> CGEventFlags;
|
||||
pub fn CGEventSetFlags(event: CGEventRef, flags: CGEventFlags);
|
||||
}
|
||||
|
||||
const CGEventFlagNull: u64 = 0;
|
||||
|
||||
// Device-independent modifier key bits.
|
||||
const CGEventFlagAlphaShift: u64 = 0x00010000;
|
||||
const CGEventFlagShift: u64 = 0x00020000;
|
||||
const CGEventFlagControl: u64 = 0x00040000;
|
||||
const CGEventFlagAlternate: u64 = 0x00080000;
|
||||
const CGEventFlagCommand: u64 = 0x00100000;
|
||||
|
||||
// Special key identifiers.
|
||||
const CGEventFlagHelp: u64 = 0x00400000;
|
||||
const CGEventFlagSecondaryFn: u64 = 0x00800000;
|
||||
|
||||
// Identifies key events from numeric keypad area on extended keyboards.
|
||||
const CGEventFlagNumericPad: u64 = 0x00200000;
|
||||
|
||||
// Indicates if mouse/pen movement events are not being coalesced
|
||||
const CGEventFlagNonCoalesced: u64 = 0x00000100;
|
||||
|
||||
const NX_DEVICELCTLKEYMASK: u64 = 0x00000001;
|
||||
const NX_DEVICERCTLKEYMASK: u64 = 0x00002000;
|
||||
const NX_DEVICELSHIFTKEYMASK: u64 = 0x00000002;
|
||||
const NX_DEVICERSHIFTKEYMASK: u64 = 0x00000004;
|
||||
const NX_DEVICELCMDKEYMASK: u64 = 0x00000008;
|
||||
const NX_DEVICERCMDKEYMASK: u64 = 0x00000010;
|
||||
const NX_DEVICELALTKEYMASK: u64 = 0x00000020;
|
||||
const NX_DEVICERALTKEYMASK: u64 = 0x00000040;
|
||||
const NX_DEVICERCTLKEYMASK: u64 = 0x00002000;
|
||||
|
||||
fn print_flags(flags: CGEventFlags) {
|
||||
println!("flags: {}", flags);
|
||||
println!("flags: {:#064b}", flags);
|
||||
|
||||
println!("EventFlags: {:x} ({} {} {} {} {} {} {} {})\n",
|
||||
flags,
|
||||
if (flags & NX_DEVICELCTLKEYMASK) != 0 { "lcontrol" } else { "" },
|
||||
if (flags & NX_DEVICERCTLKEYMASK) != 0 { "rcontrol" } else { "" },
|
||||
if (flags & NX_DEVICELSHIFTKEYMASK) != 0 { "lshift" } else { "" },
|
||||
if (flags & NX_DEVICERSHIFTKEYMASK) != 0 { "rshift" } else { "" },
|
||||
if (flags & NX_DEVICELCMDKEYMASK) != 0 { "lcommand" } else { "" },
|
||||
if (flags & NX_DEVICERCMDKEYMASK) != 0 { "rcommand" } else { "" },
|
||||
if (flags & NX_DEVICELALTKEYMASK) != 0 { "lalt" } else { "" },
|
||||
if (flags & NX_DEVICERALTKEYMASK) != 0 { "ralt" } else { "" },
|
||||
);
|
||||
}
|
||||
const NX_DEVICECAPSLOCKMASK: u64 = 1 << 16;
|
||||
|
||||
/// This callback will be registered to be invoked from the run loop
|
||||
/// to which the event tap is added as a source.
|
||||
#[no_mangle]
|
||||
#[allow(unused_variables)]
|
||||
pub extern fn callback(proxy: Pointer, event_type: CGEventType, event: CGEventRef, key_maps: &mut MacOSKeyMaps)
|
||||
-> CGEventRef {
|
||||
//print_flags(event);
|
||||
/*
|
||||
println!("+++++++++++++++++++++++++++++++++++++++");
|
||||
let event_type2 = unsafe { CGEventGetType(event) };
|
||||
println!("event_type2: {}", event_type2);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
match event_type {
|
||||
kCGEventKeyDown => println!("key down"),
|
||||
kCGEventKeyUp => println!("key up"),
|
||||
kCGEventFlagsChanged => println!("flags changed"),
|
||||
kCGEventTapDisabledByTimeout => {
|
||||
println!("Quartz event tap disabled because of timeout; attempting to reregister.");
|
||||
//register_listener(channel);
|
||||
//return event;
|
||||
},
|
||||
_ => {
|
||||
println!("Received unknown EventType: {}", event_type as u32);
|
||||
//return event;
|
||||
},
|
||||
};
|
||||
*/
|
||||
|
||||
unsafe {
|
||||
let mut input_event = InputEvent {
|
||||
event_type,
|
||||
event,
|
||||
};
|
||||
println!("got keyCode: {}", input_event.code());
|
||||
/*
|
||||
println!("---------------------------------------");
|
||||
if input_event.value() == KeyState::DOWN {
|
||||
let code = input_event.code();
|
||||
println!("KEY 0x{:04X}", code);
|
||||
write_key_file(code).expect("error writing key file");
|
||||
#[allow(unused_variables, improper_ctypes_definitions)]
|
||||
pub extern fn callback(proxy: Pointer, event_type: CGEventType, mut event: CGEvent, callback_pointer: &mut CallbackPointer) -> CGEvent {
|
||||
let (key_maps, event_source) = callback_pointer;
|
||||
match tapLocation {
|
||||
CGEventTapLocation::HID => {
|
||||
let user_data = event.get_integer_value_field(EventField::EVENT_SOURCE_USER_DATA);
|
||||
if user_data == uniqueHIDUserData {
|
||||
return event;
|
||||
}
|
||||
}
|
||||
std::ptr::null_mut()
|
||||
*/
|
||||
_ => {}
|
||||
};
|
||||
|
||||
|
||||
//input_event.event.set
|
||||
//input_event.event
|
||||
//Null.
|
||||
//Some(input_event.event)
|
||||
key_maps.send_event(&mut input_event, &DEVICE).expect("macos shouldn't error...")
|
||||
.unwrap_or_else(|| {
|
||||
println!("returning NULL from hook");
|
||||
std::ptr::null_mut()
|
||||
}) // None means return NULL
|
||||
//let keyCode = CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
|
||||
//println!("got keyCode: {}", keyCode);
|
||||
/*
|
||||
let event = KeyEvent {
|
||||
etype: match etype as u32 {
|
||||
kCGEventKeyDown => EventType::KeyDown,
|
||||
kCGEventKeyUp => EventType::KeyUp,
|
||||
kCGEventFlagsChanged => EventType::FlagsChanged,
|
||||
kCGEventTapDisabledByTimeout => {
|
||||
warn!("Quartz event tap disabled because of timeout; attempting to reregister.");
|
||||
register_listener(channel);
|
||||
return event;
|
||||
},
|
||||
_ => {
|
||||
error!("Received unknown EventType: {:}", etype);
|
||||
return event;
|
||||
},
|
||||
},
|
||||
code: keyCode,
|
||||
};
|
||||
println!("Received event: {:?}", event);
|
||||
let _ = channel.send(event);
|
||||
*/
|
||||
key_maps.send_event(&mut event, &event_source).expect("macos shouldn't error...")
|
||||
.unwrap_or_else(|| {
|
||||
event.set_type(CGEventType::Null);
|
||||
event
|
||||
}) // None means return NULL
|
||||
}
|
||||
//event
|
||||
}
|
||||
|
||||
fn write_key_file(code: CGKeyCode) -> std::io::Result<()> {
|
||||
let mut buffer = File::create("/Users/mopar/key.txt")?;
|
||||
write!(buffer, "0x{:04X}", code)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Redefine macro for bitshifting from header as function here
|
||||
pub fn CGEventMaskBit(eventType: u32) -> CGEventMask {
|
||||
1 << (eventType)
|
||||
}
|
||||
/// Redefine macro for bitshifting from header as function here
|
||||
pub fn CGEventMaskBit(eventType: CGEventType) -> CGEventMask {
|
||||
1 << (eventType as u32)
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,8 @@ After=systemd-udevd.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/rusty-keys
|
||||
Restart=always
|
||||
RestartSec=1s
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
|
Loading…
Reference in New Issue
Block a user