Showing preview only (851K chars total). Download the full file or copy to clipboard to get everything.
Repository: kevinconway/remouseable
Branch: master
Commit: 9ad73bb8929f
Files: 92
Total size: 815.3 KB
Directory structure:
gitextract_q6gejt6e/
├── .devcontainer/
│ ├── Containerfile
│ └── devcontainer.json
├── .github/
│ └── workflows/
│ ├── pr-workflow.yaml
│ └── tag-workflow.yaml
├── .gitignore
├── .golangci.errcheck.ignore
├── .golangci.yaml
├── .travis.yml
├── LICENSE
├── Makefile
├── README.md
├── go.mod
├── go.sum
├── main.go
├── pkg/
│ ├── domain.go
│ ├── driver.go
│ ├── evdevcodes.go
│ ├── evdeviterator.go
│ ├── evdeviterator_test.go
│ ├── gen.go
│ ├── internal/
│ │ ├── gen.go
│ │ ├── gencodes/
│ │ │ └── main.go
│ │ └── robotgo/
│ │ ├── base/
│ │ │ ├── LICENSE
│ │ │ ├── MMBitmap.h
│ │ │ ├── MMBitmap_c.h
│ │ │ ├── MMPointArray.h
│ │ │ ├── MMPointArray_c.h
│ │ │ ├── UTHashTable.h
│ │ │ ├── UTHashTable_c.h
│ │ │ ├── base64.c
│ │ │ ├── base64.h
│ │ │ ├── base64_c.h
│ │ │ ├── bmp_io.h
│ │ │ ├── bmp_io_c.h
│ │ │ ├── color_find.h
│ │ │ ├── color_find_c.h
│ │ │ ├── deadbeef_rand.h
│ │ │ ├── deadbeef_rand_c.h
│ │ │ ├── endian.h
│ │ │ ├── file_io.h
│ │ │ ├── file_io_c.h
│ │ │ ├── inline_keywords.h
│ │ │ ├── io.c
│ │ │ ├── microsleep.h
│ │ │ ├── ms_stdbool.h
│ │ │ ├── ms_stdint.h
│ │ │ ├── os.h
│ │ │ ├── pasteboard.h
│ │ │ ├── pasteboard_c.h
│ │ │ ├── png_io.h
│ │ │ ├── png_io_c.h
│ │ │ ├── rgb.h
│ │ │ ├── snprintf.h
│ │ │ ├── snprintf_c.h
│ │ │ ├── str_io.h
│ │ │ ├── str_io_c.h
│ │ │ ├── types.h
│ │ │ ├── uthash.h
│ │ │ ├── xdisplay.h
│ │ │ ├── xdisplay_c.h
│ │ │ ├── zlib_util.h
│ │ │ └── zlib_util_c.h
│ │ ├── mouse/
│ │ │ ├── goMouse.h
│ │ │ ├── mouse.h
│ │ │ └── mouse_c.h
│ │ ├── robotgo.go
│ │ ├── screen/
│ │ │ ├── goScreen.h
│ │ │ ├── screen.h
│ │ │ └── screen_c.h
│ │ └── window/
│ │ ├── arr.h
│ │ ├── goWindow.h
│ │ ├── process.h
│ │ ├── pub.h
│ │ ├── win32.h
│ │ ├── win_sys.h
│ │ └── window.h
│ ├── mock_driver_test.go
│ ├── mock_evdeviterator_test.go
│ ├── mock_positionscaler_test.go
│ ├── mock_readcloser_test.go
│ ├── mock_statemachine_test.go
│ ├── positionscaler.go
│ ├── positionscaler_test.go
│ ├── runtime.go
│ ├── runtime_test.go
│ ├── statemachine.go
│ └── statemachine_test.go
├── technical-documentation/
│ ├── README.md
│ └── static-assets/
│ └── diagrams.puml
└── tools/
├── go.mod
├── go.sum
└── tools.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .devcontainer/Containerfile
================================================
FROM docker.io/golang:1-bookworm
RUN apt-get update && apt-get install --yes \
curl wget gpg \
make git vim less \
sudo \
bash-completion man \
gcc libc6-dev libx11-dev xorg-dev libxtst-dev \
gcc-multilib gcc-mingw-w64
# Create a non-root user so linux users can run the container as the current
# OS user. See https://code.visualstudio.com/remote/advancedcontainers/add-nonroot-user
# and https://github.com/devcontainers/spec/blob/main/docs/specs/devcontainer-reference.md#container-creation
# for more information.
ARG USERNAME=dev
ARG USER_UID=1010
ARG USER_GID=1010
RUN groupadd --gid $USER_GID $USERNAME \
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME
================================================
FILE: .devcontainer/devcontainer.json
================================================
{
"name": "remouseable",
"build": {
"dockerfile": "Containerfile",
"context": ".."
},
"remoteUser": "dev",
"updateRemoteUserUID": true,
"containerEnv": {},
"mounts": [],
"customizations": {
"vscode": {
"settings": {
"telemetry.telemetryLevel": "off",
"telemetry.enableTelemetry": false,
"files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true,
"rewrap.wrappingColumn": 80,
"go.formatTool": "goimports",
"go.lintTool": "golangci-lint",
"terminal.integrated.profiles.linux": {
"bash": {
"path": "/usr/bin/bash"
}
},
"terminal.integrated.defaultProfile.linux": "bash"
},
"extensions": [
"golang.go",
"streetsidesoftware.code-spell-checker",
"stkb.rewrap",
"ms-vscode.makefile-tools",
"redhat.vscode-yaml",
"ms-vscode.cpptools-extension-pack"
]
}
}
}
================================================
FILE: .github/workflows/pr-workflow.yaml
================================================
name: Pull Request Checks
on:
pull_request:
branches:
- "**"
workflow_dispatch: {}
jobs:
tests:
name: Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 'stable'
- name: Install Linux Build Dependencies
run: sudo apt-get install --yes gcc libc6-dev libx11-dev xorg-dev libxtst-dev
- uses: actions/cache@v4
id: tools
with:
path: bin
key: ${{ runner.os }}-${{ hashFiles('tools/go.sum') }}
- name: Install build/test tools
if: steps.tools.outputs.cache-hit != 'true'
run: make tools
- name: Lint Tests
run: make lint
- name: Unit Tests
run: make test
linux_windows:
name: Linux And Windows builds
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 'stable'
- name: Install Linux Build Dependencies
run: sudo apt-get install --yes gcc libc6-dev libx11-dev xorg-dev libxtst-dev
- name: Install Windows Build Dependencies
run: sudo apt-get install --yes gcc-multilib gcc-mingw-w64
- name: Build Linux
run: mkdir -p .build && CGO_ENABLED=1 go build -o .build/linux main.go
- name: Build Windows
run: mkdir -p .build && CC=x86_64-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows go build -o .build/windows.exe main.go
osx:
name: OSX Builds
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 'stable'
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- name: Build OSX AMD64
run: mkdir -p .build && CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 go build -o .build/osx-amd main.go
- name: Build OSX ARM64
run: mkdir -p .build && CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 go build -o .build/osx-arm main.go
================================================
FILE: .github/workflows/tag-workflow.yaml
================================================
name: Build Linux/Windows
on:
release:
types:
- published
workflow_dispatch: {}
permissions:
contents: write
jobs:
windows_linux:
name: Windows And Linux releases
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 'stable'
- name: Install Linux Build Dependencies
run: sudo apt-get install --yes gcc libc6-dev libx11-dev xorg-dev libxtst-dev
- name: Install Windows Build Dependencies
run: sudo apt-get install --yes gcc-multilib gcc-mingw-w64
- name: Build Linux
run: mkdir -p .build && CGO_ENABLED=1 go build -o .build/linux main.go
- name: Build Windows
run: mkdir -p .build && CC=x86_64-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows go build -o .build/windows.exe main.go
- name: Add Linux Artifact To Release
run: gh release upload ${{github.event.release.tag_name}} .build/linux --clobber
env:
GH_TOKEN: ${{ github.token }}
- name: Add Windows Artifact To Release
run: gh release upload ${{github.event.release.tag_name}} .build/windows.exe --clobber
env:
GH_TOKEN: ${{ github.token }}
osx:
name: OSX Releases
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 'stable'
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- name: Build OSX AMD64
run: mkdir -p .build && CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 go build -o .build/osx-amd main.go
- name: Build OSX ARM64
run: mkdir -p .build && CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 go build -o .build/osx-arm main.go
- name: Add OSX AMD64 Artifact To Release
run: gh release upload ${{github.event.release.tag_name}} .build/osx-amd --clobber
env:
GH_TOKEN: ${{ github.token }}
- name: Add OSX ARM64 Artifact To Release
run: gh release upload ${{github.event.release.tag_name}} .build/osx-arm --clobber
env:
GH_TOKEN: ${{ github.token }}
================================================
FILE: .gitignore
================================================
# Created by https://www.gitignore.io/api/go,vim,osx,node,linux,emacs,python,windows,intellij,jetbrains,sublimetext,visualstudio,visualstudiocode
# Edit at https://www.gitignore.io/?templates=go,vim,osx,node,linux,emacs,python,windows,intellij,jetbrains,sublimetext,visualstudio,visualstudiocode
### Emacs ###
# -*- mode: gitignore; -*-
*~
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
auto-save-list
tramp
.\#*
# Org-mode
.org-id-locations
*_archive
# flymake-mode
*_flymake.*
# eshell files
/eshell/history
/eshell/lastdir
# elpa packages
/elpa/
# reftex files
*.rel
# AUCTeX auto folder
/auto/
# cask packages
.cask/
dist/
# Flycheck
flycheck_*.el
# server auth directory
/server/
# projectiles files
.projectile
# directory configuration
.dir-locals.el
# network security
/network-security.data
### Go ###
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
### Go Patch ###
/vendor/
/Godeps/
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Intellij Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
.idea/sonarlint
### JetBrains ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
# Generated files
# Sensitive or high-churn files
# Gradle
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
# Mongo Explorer plugin
# File-based project format
# IntelliJ
# mpeltonen/sbt-idea plugin
# JIRA plugin
# Cursive Clojure plugin
# Crashlytics plugin (for Android Studio and IntelliJ)
# Editor-based Rest Client
# Android studio 3.1+ serialized cache file
### JetBrains Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
### Linux ###
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
### OSX ###
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
# Distribution / packaging
.Python
build/
develop-eggs/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
### SublimeText ###
# Cache files for Sublime Text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
# Workspace files are user-specific
*.sublime-workspace
# Project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using Sublime Text
# *.sublime-project
# SFTP configuration file
sftp-config.json
# Package control specific files
Package Control.last-run
Package Control.ca-list
Package Control.ca-bundle
Package Control.system-ca-bundle
Package Control.cache/
Package Control.ca-certs/
Package Control.merged-ca-bundle
Package Control.user-ca-bundle
oscrypto-ca-bundle.crt
bh_unicode_properties.cache
# Sublime-github package stores a github token in this file
# https://packagecontrol.io/packages/sublime-github
GitHub.sublime-settings
### Vim ###
# Swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]
# Session
Session.vim
Sessionx.vim
# Temporary
.netrwhist
# Auto-generated tag files
tags
# Persistent undo
[._]*.un~
### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
### VisualStudioCode Patch ###
# Ignore all local history of files
.history
### Windows ###
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
### VisualStudio ###
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# End of https://www.gitignore.io/api/go,vim,osx,node,linux,emacs,python,windows,intellij,jetbrains,sublimetext,visualstudio,visualstudiocode
# Begin custom overrides
# Project local bin directory
bin/
# Test coverage collection directory
.coverage/
# Antlr files
.antlr/
# Static file bundles that can be created at build time.
statik/statik.go
# Project local build output directory
.build/
# End custom overrides
================================================
FILE: .golangci.errcheck.ignore
================================================
================================================
FILE: .golangci.yaml
================================================
# options for analysis running
run:
# timeout for analysis, e.g. 30s, 5m, default is 1m
deadline: 1m
# exit code when at least one issue was found, default is 1
issues-exit-code: 1
# include test files or not, default is true
tests: true
# list of build tags, all linters use it. Default is empty list.
build-tags:
- integration
# which dirs to skip: they won't be analyzed; can use regexp here:
# generated.*, regexp is applied on full path; default value is empty list,
# but next dirs are always skipped independently from this option's value:
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
skip-dirs:
- internal/proto
# by default isn't set. If set we pass it to "go list -mod={option}". From "go
# help modules": If invoked with -mod=readonly, the go command is disallowed
# from the implicit automatic updating of go.mod described above. Instead, it
# fails when any changes to go.mod are needed. This setting is most useful to
# check that go.mod does not need updates, such as in a continuous integration
# and testing system. If invoked with -mod=vendor, the go command assumes that
# the vendor directory holds the correct copies of dependencies and ignores
# the dependency descriptions in go.mod.
modules-download-mode: readonly
# output configuration options
output:
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is
# "colored-line-number"
format: colored-line-number
# print lines of code with issue, default is true
print-issued-lines: true
# print linter name in the end of issue text, default is true
print-linter-name: true
# all available settings of specific linters
linters-settings:
errcheck:
# report about not checking of errors in type assetions: `a :=
# b.(MyStruct)`; default is false: such cases aren't reported by default.
check-type-assertions: false
# report about assignment of errors to blank identifier: `num, _ :=
# strconv.Atoi(numStr)`; default is false: such cases aren't reported by
# default.
check-blank: false
# [deprecated] comma-separated list of pairs of the form pkg:regex the regex
# is used to ignore names within pkg. (default "fmt:.*"). see
# https://github.com/kisielk/errcheck#the-deprecated-method for details
ignore: fmt:.*
# path to a file containing a list of functions to exclude from checking see
# https://github.com/kisielk/errcheck#excluding-functions for details
exclude: .golangci.errcheck.ignore
govet:
# report about shadowed variables
check-shadowing: true
golint:
# minimal confidence for issues, default is 0.8
min-confidence: 0.8
gofmt:
# simplify code: gofmt with `-s` option, true by default.
# NOTE: Setting to false in order to cooperate with goimports which does
# _not_ apply the simplification.
simplify: false
goimports:
# put imports beginning with prefix after 3rd-party packages; it's a
# comma-separated list of prefixes
local-prefixes: github.com/kevinconway/
gocyclo:
# minimal code complexity to report, 30 by default (but we recommend 10-20)
min-complexity: 60 # Setting high value to account for complex reflection.
maligned:
# print struct with more effective memory layout or not, false by default
suggest-new: true
dupl:
# tokens count to trigger issue, 150 by default
threshold: 300
goconst:
# minimal length of string constant, 3 by default
min-len: 3
# minimal occurrences count to trigger, 3 by default
min-occurrences: 3
misspell:
# Correct spellings using locale preferences for US or UK. Default is to use
# a neutral variety of English. Setting locale to US will correct the
# British spelling of 'colour' to 'color'.
locale: US
ignore-words:
- ignore
lll:
# max line length, lines longer will be reported. Default is 120. '\t' is
# counted as 1 character by default, and can be changed with the tab-width
# option
line-length: 120
# tab width in spaces. Default to 1.
tab-width: 1
unused:
# treat code as a program (not a library) and report unused exported
# identifiers; default is false. XXX: if you enable this setting, unused
# will report a lot of false-positives in text editors: if it's called for
# subdir of a project it can't find funcs usages. All text editor
# integrations with golangci-lint call it on a directory with the changed
# file.
check-exported: false
unparam:
# Inspect exported functions, default is false. Set to true if no external
# program/library imports your code. XXX: if you enable this setting,
# unparam will report a lot of false-positives in text editors: if it's
# called for subdir of a project it can't find external interfaces. All text
# editor integrations with golangci-lint call it on a directory with the
# changed file.
check-exported: false
nakedret:
# make an issue if func has more lines of code than this setting and it has
# naked returns; default is 30
max-func-lines: 1
prealloc:
# XXX: we don't recommend using this linter before doing performance
# profiling. For most programs usage of prealloc will be a premature
# optimization.
# Report preallocation suggestions only on simple loops that have no
# returns/breaks/continues/gotos in them. True by default.
simple: true
range-loops: true # Report preallocation suggestions on range loops, true by default
for-loops: true # Report preallocation suggestions on for loops, false by default
linters:
presets:
- bugs
- test
disable:
- depguard
- gocritic
- lll
- funlen
- wsl
- gocognit
- unused # Disabled because it seems to break if there is no vendor.
- typecheck # Disabled because it seems to break if there is no vendor.
- testifylint # Added to lint suite after project started
- testpackage # Added to lint suite after project started
- paralleltest # Added to lint suite after project started
- exhaustivestruct # Added to lint suite after project started
- exhaustruct # Added to lint suite after project started
issues:
# List of regexps of issue texts to exclude, empty list by default. But
# independently from this option we use default exclude patterns, it can be
# disabled by `exclude-use-default: false`. To list all excluded by default
# patterns execute `golangci-lint run --help`
exclude: []
# Excluding configuration per-path, per-linter, per-text and per-source
exclude-rules:
# Exclude some linters from running on tests files.
- path: _test\.go
linters:
- gocyclo
- errcheck
- dupl
- gosec
# Exclude known linters from partially hard-vendored code, which is
# impossible to exclude via "nolint" comments.
- path: internal/hmac/
text: "weak cryptographic primitive"
linters:
- gosec
# Exclude some staticcheck messages
- linters:
- staticcheck
text: "SA9003:"
# Exclude lll issues for long lines with go:generate
- linters:
- lll
source: "^//go:generate "
# Independently from option `exclude` we use default exclude patterns, it can
# be disabled by this option. To list all excluded by default patterns execute
# `golangci-lint run --help`. Default value for this option is true.
exclude-use-default: true
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
max-issues-per-linter: 50
# Maximum count of issues with the same text. Set to 0 to disable. Default is
# 3.
max-same-issues: 3
# Show only new issues: if there are unstaged changes or untracked files, only
# those changes are analyzed, else only changes in HEAD~ are analyzed. It's a
# super-useful option for integration of golangci-lint into existing large
# codebase. It's not practical to fix all existing issues at the moment of
# integration: much better don't allow issues in new code. Default is false.
new: false
================================================
FILE: .travis.yml
================================================
language: go
go:
- 1.14.x
services:
- xvfb
addons:
homebrew:
update: true
packages:
- go@1.14
- make
- coreutils
- findutils
- gnu-tar
- gnu-sed
- gawk
- gnutls
- gnu-indent
- gnu-getopt
- grep
apt:
packages:
- gcc
- libc6-dev
- libx11-dev
- xorg-dev
- libxtst-dev
- gcc-multilib
- gcc-mingw-w64
os:
- linux
- osx
install:
- GO111MODULE=on go get
script:
- if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then export PATH="$(brew --prefix)/opt/make/libexec/gnubin:${PATH}" ; fi
- make tools
- make lint
- make test
- make coverage
- make BUILDNAME=${TRAVIS_OS_NAME} build
- if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then CC=x86_64-w64-mingw32-gcc GOOS=windows CGO_ENABLED=1 go build -o .build/windows.exe main.go ; fi
deploy:
provider: releases
api_key:
secure: n2pSGM0ygiIptoWD/D9W0VokURsI8p44+qFsBbMuWz1kG3agzsHfJR8ufvYVYnl3CelupOHoU11+uM/R3am5djnqVkpYZhdvJznEaLzdPZeLDuMaMF0GLm6o5UFpcA0nf/68RAaLaBg4iXCBrSfN5nnrscxdmKOfQ1V8PwhkIZNkKXaXBK2myx9o6uhSfuRYHvXlTtZ01R8Yy7l/3TB6I841OuGMsxI/klDPFF/6DYe0bbgmh6Q6FRAsGAZGfrWGUGa4g5gi9cBpYGyR0vZfMxy4nlSaF2Owi9Pguj/8gWabmHLDSyWZqDOcrp2VlVALMNTMeP+0s2MNkp9CbFjlngMoykh1cV/wC/OGKyWasqKLAgX+HTDhGjDIsbhEyaK9RydKUSW4CNAoOJU3jzONOrCocFsmuGRP7H9XoS2XDK7X4cbCJEIbkgqQqSPRKz+i4fdPE5eUiSlxvy4QDE24YUrcIdpyND0naF1OMqyqkMqXVHf2cmqqMWYSoz3FRy4uLs81Mq2hFcQBjYKoSSrJ5UfKrtU5PZy7UpGDPRvCzVaiXpRrCZgRVhuDAAZPa3CvJmN5xDYUTjRc42fziIAwwbtAB0uq40O3xdIYGxt1GaUnagaucbU1aBbc3T/X/o/yDdUA/os6hXSh6FtKdIm/qGD+jssvHi44ILDYdaeTmuw=
file_glob: true
file: ${TRAVIS_BUILD_DIR}/.build/*
on:
repo: kevinconway/remouseable
tags: true
skip_cleanup: true
cleanup: false
================================================
FILE: LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.
================================================
FILE: Makefile
================================================
.PHONY : update updatetools tools
.PHONY : lint test integration coverage
.PHONY : build
.PHONY : clean cleancoverage cleantools
PROJECT_PATH = $(shell pwd -L)
TOOLSDIR = $(PROJECT_PATH)/tools
BINDIR = $(PROJECT_PATH)/bin
BUILDDIR = $(PROJECT_PATH)/.build
GOFLAGS ::= ${GOFLAGS}
COVERDIR = $(PROJECT_PATH)/.coverage
COVEROUT = $(wildcard $(COVERDIR)/*.out)
COVERINTERCHANGE = $(COVEROUT:.out=.interchange)
COVERHTML = $(COVEROUT:.out=.html)
COVERXML = $(COVEROUT:.out=.xml)
COVERCOMBINED ::= $(COVERDIR)/combined.out
BUILDNAME = remouse
# Tools need to be enumerated here in order to support updating them.
# They will only be used in the context of the /tools directory which
# is a special sub-module that is only engaged when handling the tools.
# We do this to prevent having tools included in the actual project
# dependencies.
TOOLS ::= github.com/golang/mock/mockgen
TOOLS ::= $(TOOLS) golang.org/x/tools/cmd/goimports
TOOLS ::= $(TOOLS) github.com/golangci/golangci-lint/cmd/golangci-lint
TOOLS ::= $(TOOLS) github.com/axw/gocov/gocov
TOOLS ::= $(TOOLS) github.com/matm/gocov-html
TOOLS ::= $(TOOLS) github.com/AlekSi/gocov-xml
TOOLS ::= $(TOOLS) github.com/wadey/gocovmerge
UNIT_PKGS = $(shell go list ./... | sed 1d | paste -sd "," -)
update:
GO111MODULE=on go get -u
updatetools: cleantools
# Regenerate the module files for the tools and then
# reinstall them. This should be done periodically but
# infrequently.
cd $(TOOLSDIR) && GO111MODULE=on go get -u $(TOOLS)
$(MAKE) $(BINDIR)
$(BINDIR):
cd $(TOOLSDIR) && GOBIN=$(BINDIR) go install $(TOOLS)
tools: $(BINDIR)
# This is an alias for generating the tools. Unless
# $(BINDIR) is set elsewhere it will generate a local
# /bin directory in the repo.
fmt: $(BINDIR)
# Apply goimports to all code files. Here we intentionally
# ignore everything in /vendor if it is present.
GO111MODULE=on \
GOFLAGS="$(GOFLAGS)" \
$(BINDIR)/goimports -w -v \
-local github.com/kevinconway/ \
$(shell find . -type f -name '*.go' -not -path "./vendor/*")
lint: $(BINDIR)
GO111MODULE=on \
GOFLAGS="$(GOFLAGS)" \
$(BINDIR)/golangci-lint run \
--config .golangci.yaml \
--print-resources-usage \
--verbose
test: $(BINDIR) $(COVERDIR)
GO111MODULE=on \
GOFLAGS="$(GOFLAGS)" \
go test \
-v \
-cover \
-race \
-coverpkg="$(UNIT_PKGS)" \
-coverprofile="$(COVERDIR)/unit.out" \
./...
build: $(BUILDDIR)
# Optionally build the service if it has an executable
# present in the project root.
GO111MODULE=on \
GOFLAGS="$(GOFLAGS)" \
go build -o $(BUILDDIR)/$(BUILDNAME) main.go
$(BUILDDIR):
mkdir -p $(BUILDDIR)
generate: $(BINDIR)
# Run any code generation steps.
GO111MODULE=on \
GOFLAGS="$(GOFLAGS)" \
PATH="${PATH}:$(BINDIR)" \
go generate github.com/kevinconway/remouseable/pkg github.com/kevinconway/remouseable/pkg/internal
$(MAKE) fmt
coverage: $(BINDIR) $(COVERDIR) $(COVERCOMBINED) $(COVERINTERCHANGE) $(COVERHTML) $(COVERXML)
# The cover rule is an alias for a number of other rules that each
# generate part of the full coverage report. First, any coverage reports
# are combined so that there is a report both for an individual test run
# and a report that covers all test runs together. Then all coverage
# files are converted to an interchange format. From there we generate
# an HTML and XML report. XML reports may be used with jUnit style parsers,
# the HTML report is for human consumption in order to help identify
# the location of coverage gaps, and the original reports are available
# for any purpose.
GO111MODULE=on \
GOFLAGS="$(GOFLAGS)" \
go tool cover -func $(COVERCOMBINED)
$(COVERCOMBINED):
GO111MODULE=on \
GOFLAGS="$(GOFLAGS)" \
$(BINDIR)/gocovmerge $(COVERDIR)/*.out > $(COVERCOMBINED)
# NOTE: I couldn't figure out how to automatically include
# the combined files with the list of other .out files that
# are processed in bulk. For now, this needs to have specific
# calls to make for combined coverage.
$(MAKE) $(COVERCOMBINED:.out=.interchange)
$(MAKE) $(COVERCOMBINED:.out=.xml)
$(MAKE) $(COVERCOMBINED:.out=.html)
$(COVERDIR)/%.interchange: $(COVERDIR)/%.out
GO111MODULE=on \
GOFLAGS="$(GOFLAGS)" \
$(BINDIR)/gocov convert $< > $@
$(COVERDIR)/%.xml: $(COVERDIR)/%.interchange
cat $< | \
GO111MODULE=on \
GOFLAGS="$(GOFLAGS)" \
$(BINDIR)/gocov-xml > $@
$(COVERDIR)/%.html: $(COVERDIR)/%.interchange
cat $< | \
GO111MODULE=on \
GOFLAGS="$(GOFLAGS)" \
$(BINDIR)/gocov-html > $@
$(COVERDIR):
mkdir -p $(COVERDIR)
clean: cleancoverage cleantools ;
cleantools:
rm -rf $(BINDIR)
cleancoverage:
rm -rf $(COVERDIR)
================================================
FILE: README.md
================================================
# reMouseable
> Use your reMarkable tablet as a mouse.
- [reMouseable](#remouseable)
- [Update From September 19, 2024](#update-from-september-19-2024)
- [Overview](#overview)
- [Code And Developer Documentation](#code-and-developer-documentation)
- [Installation](#installation)
- [Windows](#windows)
- [OSX](#osx)
- [Linux](#linux)
- [Usage](#usage)
- [reMarkable 2 Tablets](#remarkable-2-tablets)
- [Wireless Tablet](#wireless-tablet)
- [Advanced SSH Setup](#advanced-ssh-setup)
- [All Options](#all-options)
- [Common Issues And Solutions](#common-issues-and-solutions)
- [OSX Privacy Settings](#osx-privacy-settings)
- [Getting "panic: dial unix: missing address" On Windows](#getting-panic-dial-unix-missing-address-on-windows)
- [Building](#building)
- [Linux](#linux-1)
- [OSX](#osx-1)
- [Windows](#windows-1)
- [Windows On Linux](#windows-on-linux)
- [How It Works](#how-it-works)
- [License](#license)
- [Developing](#developing)
- [Thanks](#thanks)
## Update From September 19, 2024
I somewhat recently had a one-off need to connect my tablet and run remouseable
again. Once my tablet installed the last few years of updates then I hit the
same issue as anyone else trying to use this project over the past year and a
half to two years. I'm sharing the fix with folks in case someone finds it
useful but **remouseable is still discontinued**.
Remousable was broken for long enough that I expect nearly everyone who once
used it has moved on. If you start using it again or are considering using it
for the first time then I wish you the best. Please understand, though, that I
do not have time to support you if you need help or encounter an issue. I've
left the GitHub issues enabled so anyone using this can request or offer help to
others but I do not monitor the issues and will not respond to them myself.
You can download the fixed executables from
https://github.com/kevinconway/remouseable/releases and follow this README's
instructions on how to install them. However, consider
https://github.com/Evidlo/remarkable_mouse as a replacement that continued
working while remouseable was broken and continues to have people contributing
to it. It also supports more features than this project such as multi-monitor
support.
If you are a developer and want to add new features then please fork the
project. I've added GitHub actions workflows to automate building new
executables and a [devcontainer](https://containers.dev/) to make running a fork
even easier. If you maintain a fork with newer or better features than mine then
I'm happy to add a link to your project here.
## Overview
I'm a user of the [reMarkable](https://remarkable.com/) tablet. After using it
for a while I started wondering if it could be used as an input for my
computer so I could write and draw on digital whiteboards. It turns out, it can!
There's a great implementation of this feature written in Python at
<https://github.com/Evidlo/remarkable_mouse>. I'm working on this
implementation so that I can offer pre-built binaries that don't require a
specific language to be installed on the host machine.
## Code And Developer Documentation
This README contains how-to information for installing, configuration, and using
the project. To view the code API documentation check out the
[godocs](https://godoc.org/github.com/kevinconway/remouseable).
If you would like to modify the project or add a feature then see the technical
documentation in the `technical-documentation` directory.
## Installation
### Windows
Go to <https://github.com/kevinconway/remouseable/releases/latest> and download
the file named `windows.exe`. Then rename the file to `remouseable.exe`. You
can now open the Windows command prompt and start the program with:
```shell
cd Downloads
remouseable.exe
```
If a new version of the program comes out then you can overwrite your
`remouseable.exe` with a new version using exactly the same steps.
### OSX
Go to <https://github.com/kevinconway/remouseable/releases/latest> and download
the file named `osx-arm` if using an M series model or `osx-amd` if using a
model older than M1. Then rename the file to `remouseable`. Next, make the
program runnable with by opening a command line prompt and:
```shell
cd ~/Downloads
chmod +x remouseable
```
You can now run the program by opening a command line prompt and:
```shell
cd ~/Downloads
./remouseable
```
Note that the first time you run the application your system will prompt you
with a security notice. The remouseable application works by controlling your
mouse and OSX does not allow this by default. To enable the application you
must grant your command line prompt accessibility settings which allow it to
move the mouse. To do this, navigate to
`System Preferences -> Security & Privacy -> Privacy -> Accessibility`. You will
see your terminal or shell in the list of applications that have requested
accessibility permissions.
If you'd like to be able to launch the application through spotlight instead of
only the terminal then check out <https://github.com/isaacwisdom/reMouseableApp>
where another developer has created an Applscript wrapper that makes remouseable
act more like a typical OSX application.
### Linux
Go to <https://github.com/kevinconway/remouseable/releases/latest> and download
the file named `linux`. Then rename the file to `remouseable`. Next, make the
program runnable with by opening a command line prompt and:
```shell
cd ~/Downloads
chmod +x remouseable
```
You can now run the program by opening a command line prompt and:
```shell
cd ~/Downloads
./remouseable
```
Note that project only works in an X11 environment. If your system uses Wayland
then touching the tablet with the mouse will result in a remote desktop prompt
due to something related to Wayland's X11 backwards compatibility choices. Even
if you allow the connection the application will not work correctly. Some forum
threads such as [this](https://discussion.fedoraproject.org/t/fedora-39-keeps-spaming-confirmation-remote-desktop-window/98323)
or [this](https://discussion.fedoraproject.org/t/getting-spammed-with-remote-desktop-connection-window/115561)
may provide some help but Wayland is technically not supported.
## Usage
Most settings default to the correct values. The only value you should need to
set in the common case is the SSH password for the tablet. This password value
is found in the settings menu under `Help` and then `Copyrights and licenses`.
Your password will be near the bottom of the page. If you have an older tablet
that has not been updated to the latest software then your password may be
found in the `About` tab of the tablet menu at the bottom of the `General
Information` section. You may either give the password as text with
```bash
remouseable --ssh-password="XYZ123"
```
or you may choose to have a password prompt with:
```bash
remouseable --ssh-password="-"
```
Run one of these commands with your device connected over USB and your stylus
will become a mouse. The stylus is actually active _before_ it touches the
screen. This means you can see your mouse move by hovering the stylus just above
the writing surface but without directly touching the tablet. Once you touch the
tablet surface with the stylus the computer mouse will click and hold down the
left mouse button while you write or draw and then release the button when you
lift the stylus.
### reMarkable 2 Tablets
The application should work with both reMarkable and reMarkable 2 tablets.
However, the reMarkable 2 requires that you add
`--event-file /dev/input/event1` when executing because of a slight change in
where the stylus events are written in the new tablets. The full command should
look like
`remousable --ssh-password="MYPASSWORD" --event-file="/dev/input/event1"`.
### Wireless Tablet
The default expectation is that you will have your tablet connected over USB
which makes the default `10.11.99.1` address available. However, it is also
possible to access your device over wifi. If you attempt this method then you
will need to arrange for a static, or at least consistent, IP address for the
tablet. This is something you can usually do through configuring your router to
assign a fixed IP address to the device based on the hardware MAC address.
If you cannot assign the same `10.11.99.1` address in your setup then you may
override the default IP address when running the application:
### Advanced SSH Setup
By default, the tablet only accepts the root password for authentication. It is
possible, though, to install a custom public key on the device so that you can
use either password-less authentication or use a key pair that is encrypted with
the password of your choice rather than the device's default password.
If you'd like to create a key pair especially for accessing the reMarkable
tablet then start with a guide like
<https://help.github.com/en/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent>
that walks through creating a new key pair and registering it with your SSH
agent. For even more advanced SSH users, such as those using the gpg-agent as
the SSH agent, the remouseable application will talk to any valid SSH agent
implementation so long as the `SSH_AUTH_SOCK` value is set correctly.
Once you have a key pair ready, copy the public key value from `ssh-add -L` for
the key you want to use. Then copy the key over to your tablet with:
```bash
ssh root@10.11.99.1 # This will prompt for password.
mkdir -p ~/.ssh # This directory does not exist by default.
echo 'INSERT YOUR PUBLIC KEY HERE' >> ~/.ssh/authorized_keys
```
Now future connections over SSH will leverage your key pair and you can omit
the usual password flag when running the application.
Note that windows builds cannot use this option due to incompatibilities with
the current version of the windows ssh-agent.
Note that if you encounter the `Invalid MIT-MAGIC-COOKIE-1 key` error it means
that most likely the ssh fingerprint of the device might have changed to an
update of the tablet OS. Follow the ssh suggestion of removing the outdated
fingerprint then if you are satisfied that your device is indeed the right one
try connecting again.
```bash
remouseable --ssh-ip="192.168.1.110:22" # or other IP
```
### All Options
```
$ remouseable -h
Usage of remouseable:
--debug-events Stream hardware events from the tablet instead of acting as a mouse. This is for debugging.
--disable-drag-event Disable use of the custom OSX drag event. Only use this drawing on an Apple device is not working as expected.
--event-file string The path on the tablet from which to read evdev events. Probably don't change this. (default "/dev/input/event0")
--orientation string Orientation of the tablet. Choices are vertical, right, and left (default "right")
--pressure-threshold int Change the click detection sensitivity. 1000 is when the pen makes contact with the tablet. Set higher to require more pen pressure for a click. (default 1000)
--screen-height int The max units per millimeter of the host screen height. Probably don't change this. (default 1080)
--screen-width int The max units per millimeter of the host screen width. Probably don't change this. (default 1920)
--ssh-ip string The host and port of a tablet. (default "10.11.99.1:22")
--ssh-password string An optional password to use when ssh-ing into the tablet. Use - for a prompt rather than entering a value. If not given then public/private keypair authentication is used.
--ssh-socket string Path to the SSH auth socket. This must not be empty if using public/private keypair authentication.
--ssh-user string The ssh username to use when logging into the tablet. (default "root")
--tablet-height int The max units per millimeter for the hight of the tablet. Probably don't change this. (default 15725)
--tablet-width int The max units per millimeter for the width of the tablet. Probably don't change this. (default 20967)
pflag: help requested
exit status 2
```
## Common Issues And Solutions
### OSX Privacy Settings
If you are using this on an Apple or OSX device then you will need to give the
terminal or shell you are using permissions to control your mouse. Mouse
permissions are treated as an accessibility feature. If you are not prompted by
the operating system to update your permissions the first time you run the
application then you can navigate to
`System Preferences -> Security & Privacy -> Privacy -> Accessibility`. You will
see your terminal or shell in the list of applications that have requested
accessibility permissions.
### Getting "panic: dial unix: missing address" On Windows
This error message happens most often when the `--ssh-password` flag is missing
when running the application. On Windows, you must run the application with
either `remouseable.exe --ssh-password="MYPASSWORD"` or
`remouseable.exe --ssh-password="-"`.
## Building
There are pre-built binaries attached to each release that should work for all
64bit versions of linux, osx, and windows. However, if you prefer to generate
your own build then the following sections detail building a binary on
different platforms.
### Linux
Linux builds are dependent on:
- gcc
- x11 dev headers
- xtst dev headers
- xorg dev headers
These package will vary by name depending on your chosen linux distro. Debian
and Ubuntu users can install these with:
```shell
apt-get install -y gcc libc6-dev libx11-dev xorg-dev libxtst-dev
```
From there you run `make build`.
### OSX
OSX builds will require xcode and the xcode command line tools. These must be
installed through the Apple store.
Beyond xcode the build also requires installing support for gnu make if you want
to use the Makefile for generating a build. Homebrew users can install this
with:
```shell
brew install make coreutils findutils gnu-tar gnu-sed gawk gnutls gnu-indent gnu-getopt grep
export PATH="$(brew --prefix)/opt/make/libexec/gnubin:${PATH}"
```
From there you run `make build`.
### Windows
Windows builds require a GCC implementation. I recommend
<https://jmeubank.github.io/tdm-gcc/>. During installation you will be given the
option to add the GCC install to your path. If you choose not to then you will
need to temporarily add it to your path in PowerShell with:
```shell
$env:Path += ";C:\TDM-GCC-64\bin\"
```
The included Makefile contains too many bash specific commands to work in
PowerShell but you can still generate a binary by running:
```shell
go build main.go
```
#### Windows On Linux
If you want to generate a windows build from a linux machine then you will need
to install a MinGW implementation. Debian and Ubuntu users can do this with:
```shell
apt-get install -y gcc-multilib gcc-mingw-w64
```
The included Makefile does not have a build option for this but you can generate
the binary with:
```shell
CC=x86_64-w64-mingw32-gcc GOOS=windows go build main.go
```
## How It Works
The project is implemented as a set of successive layers that turn the tablet
into a mouse. It follows as:
- SSH into the device and start streaming `evdev` data back to the host.
- Convert the raw byte stream into structured `evdev` data containers.
- Feed all events into a state machine that emits higher level state change
events like "CLICK" and "MOVE".
- Use state change events as a trigger for moving or clicking the mouse
on the host machine.
Each of these layers has an interface defined in the `pkg/domain.go` file.
The mouse interactions on the host are performed by using a modified version of
<https://github.com/go-vgo/robotgo>. The `pkg/internal/robotgo` directory
contains a stripped down version of `robotgo` that contains only the portions
required to detect the screen dimensions and send mouse events. The actual
`robotgo` project contains support for a much larger set of features such as
taking screen shots and controlling windows on the screen. However, each of
those additional features comes with additional system dependencies that make
creating a portable binary build difficult.
## License
remouseable is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3 as published
by the Free Software Foundation.
remouseable is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with remouseable. If not, see <https://www.gnu.org/licenses/>
## Developing
This project is go1.16+ compatible. A Makefile is included to make some things
easier. Some make targets of note:
- make generate
Re-generate any automatically generated code. Note that there is a gomock
bug making it necessary to manually modify the files after generation
because it adds a cyclical import.
- make test
Run all the unit tests and generate a coverage report in `.coverage/`.
- make lint
Run the golangci-lint suite using the included configuration.
- make fmt
Apply `goimports` formatting.
- make build
Generate a binary from the current project state.
- make tools
Generate a `.bin/` directory that contains a built version of each of the
tools used to build and test the project.
- make update / make updatetools
Run `go get -u` for the project or for the project tooling.
- make clean / make cleantools / make cleancoverage
Remove files generated by the Makefile. The top-level `clean` should remove
all artifacts such as `./bin` and `./coverage`. The other are scoped to
specific artifacts for cases where, for example, you want to remove old
coverage reports and regenerate them.
## Thanks
I used the <https://github.com/gvalkov/golang-evdev> project as a reference when
implementing the `evdev` parser. I didn't use it directly because it is very
much oriented towards directly opening and managing a file descriptor for a
device. This project needs to read data from a remote device.
I used the <https://github.com/go-vgo/robotgo> project as the basis for
interacting with the operating system. I embedded portions of it here instead
of importing the Go package in order to limit the number of dependencies
required to build the project.
================================================
FILE: go.mod
================================================
module github.com/kevinconway/remouseable
go 1.23
require (
github.com/dave/jennifer v1.7.1
github.com/golang/mock v1.6.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.9.0
golang.org/x/crypto v0.27.0
golang.org/x/sys v0.25.0
golang.org/x/term v0.24.0
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
================================================
FILE: go.sum
================================================
github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo=
github.com/dave/jennifer v1.7.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
================================================
FILE: main.go
================================================
// This file is part of remouseable.
//
// remouseable is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 3 as published
// by the Free Software Foundation.
//
// remouseable is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with remouseable. If not, see <https://www.gnu.org/licenses/>.
package main
import (
"fmt"
"io"
"net"
"os"
"syscall"
flag "github.com/spf13/pflag"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
"golang.org/x/term"
remouseable "github.com/kevinconway/remouseable/pkg"
)
func main() {
driver := &remouseable.RobotgoDriver{}
fs := flag.NewFlagSet("remouseable", flag.ExitOnError)
orientation := fs.String("orientation", "right", "Orientation of the tablet. Choices are vertical, right, and left")
tabletHeight := fs.Int("tablet-height", remouseable.DefaultTabletHeight, "The max units per millimeter for the hight of the tablet. Probably don't change this.")
tabletWidth := fs.Int("tablet-width", remouseable.DefaultTabletWidth, "The max units per millimeter for the width of the tablet. Probably don't change this.")
tmpScreenWidth, tmpScreenHeight, _ := driver.GetSize()
screenHeight := fs.Int("screen-height", tmpScreenHeight, "The max units per millimeter of the host screen height. Probably don't change this.")
screenWidth := fs.Int("screen-width", tmpScreenWidth, "The max units per millimeter of the host screen width. Probably don't change this.")
sshIP := fs.String("ssh-ip", "10.11.99.1:22", "The host and port of a tablet.")
sshUser := fs.String("ssh-user", "root", "The ssh username to use when logging into the tablet.")
sshPassword := fs.String("ssh-password", "", "An optional password to use when ssh-ing into the tablet. Use - for a prompt rather than entering a value. If not given then public/private keypair authentication is used.")
sshSocket := fs.String("ssh-socket", os.Getenv("SSH_AUTH_SOCK"), "Path to the SSH auth socket. This must not be empty if using public/private keypair authentication.")
evtFile := fs.String("event-file", "/dev/input/event0", "The path on the tablet from which to read evdev events. Probably don't change this.")
debugEvents := fs.Bool("debug-events", false, "Stream hardware events from the tablet instead of acting as a mouse. This is for debugging.")
disableDrag := fs.Bool("disable-drag-event", false, "Disable use of the custom OSX drag event. Only use this drawing on an Apple device is not working as expected.")
pressureThreshold := fs.Int("pressure-threshold", 1000, "Change the click detection sensitivity. 1000 is when the pen makes contact with the tablet. Set higher to require more pen pressure for a click.")
_ = fs.Parse(os.Args[1:])
if *sshPassword == "-" {
fmt.Print("Enter Password: ")
pwd, err := term.ReadPassword(int(syscall.Stdin))
if err != nil {
panic(err)
}
*sshPassword = string(pwd)
}
sshConfig := &ssh.ClientConfig{
User: *sshUser,
Auth: []ssh.AuthMethod{
ssh.Password(*sshPassword),
},
HostKeyAlgorithms: []string{
"ecdsa-sha2-nistp256",
"ecdsa-sha2-nistp384",
"ecdsa-sha2-nistp521",
"ssh-ed25519",
"rsa-sha2-256",
"rsa-sha2-512",
"ssh-rsa",
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(), //nolint:gosec
}
if *sshPassword == "" {
agentFd, err := net.Dial("unix", *sshSocket)
if err != nil {
panic(err)
}
defer agentFd.Close()
agentSigner := agent.NewClient(agentFd)
sshConfig.Auth = []ssh.AuthMethod{
ssh.PublicKeysCallback(agentSigner.Signers),
}
}
client, err := ssh.Dial("tcp", *sshIP, sshConfig)
if err != nil {
panic(err)
}
sesh, err := client.NewSession()
if err != nil {
panic(err)
}
defer sesh.Close()
pipe, err := sesh.StdoutPipe()
if err != nil {
panic(err)
}
if err = sesh.Start(fmt.Sprintf("cat %s", *evtFile)); err != nil {
panic(err)
}
if *debugEvents {
it := &remouseable.SelectingEvdevIterator{
Wrapped: &remouseable.FileEvdevIterator{
Source: io.NopCloser(pipe),
},
Selection: []uint16{remouseable.EV_ABS},
}
defer it.Close()
fmt.Println("remouseable connected and running.")
for it.Next() {
evt := it.Current()
evtype := remouseable.EVMap[evt.Type]
evcode := remouseable.CodeString(evt.Type, evt.Code)
fmt.Printf(
`{"eventType": %d, "eventTypeName": "%s", "eventCode": %d, "eventCodeName": "%s", "eventValue": %d}`,
evt.Type, evtype, evt.Code, evcode, evt.Value,
)
fmt.Print("\n")
}
if err = it.Close(); err != nil {
panic(err.Error())
}
return
}
it := &remouseable.SelectingEvdevIterator{
Wrapped: &remouseable.FileEvdevIterator{
Source: io.NopCloser(pipe),
},
Selection: []uint16{remouseable.EV_ABS},
}
defer it.Close()
var sm remouseable.StateMachine = &remouseable.DraggingEvdevStateMachine{
EvdevStateMachine: &remouseable.EvdevStateMachine{
Iterator: it,
PressureThreshold: *pressureThreshold,
},
}
if *disableDrag {
sm = &remouseable.EvdevStateMachine{
Iterator: it,
PressureThreshold: *pressureThreshold,
}
}
defer sm.Close()
var sc remouseable.PositionScaler
switch *orientation {
case "right":
sc = &remouseable.RightPositionScaler{
TabletWidth: *tabletWidth,
TabletHeight: *tabletHeight,
ScreenWidth: *screenWidth,
ScreenHeight: *screenHeight,
}
case "left":
sc = &remouseable.LeftPositionScaler{
TabletWidth: *tabletWidth,
TabletHeight: *tabletHeight,
ScreenWidth: *screenWidth,
ScreenHeight: *screenHeight,
}
case "vertical":
sc = &remouseable.VerticalPositionScaler{
TabletWidth: *tabletWidth,
TabletHeight: *tabletHeight,
ScreenWidth: *screenWidth,
ScreenHeight: *screenHeight,
}
default:
panic(fmt.Sprintf("unknown orienation selection %s", *orientation))
}
rt := &remouseable.Runtime{
PositionScaler: sc,
StateMachine: sm,
Driver: driver,
}
fmt.Println("remouseable connected and running.")
for rt.Next() {
}
if err = rt.Close(); err != nil {
panic(err)
}
}
================================================
FILE: pkg/domain.go
================================================
// This file is part of remouseable.
//
// remouseable is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 3 as published
// by the Free Software Foundation.
//
// remouseable is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with remouseable. If not, see <https://www.gnu.org/licenses/>.
package remouseable
import "time"
// EvdevEvent is a container type for raw evdev events. It is structured
// such that it can be used with the encoding/binary package to unmarshal
// raw events from the binary format.
type EvdevEvent struct {
// Time of the event
Time time.Time
// Type is one of the EV_* named constants in evdevcodes.go
Type uint16
// Code is the relevant event constant from evdevcodes.go
Code uint16
// Numeric value of the event. Dependent on the event type.
Value int32
}
// EvdevIterator represents a source of EvdevEvent instances. This is generally
// sourced from a /dev/input/event* file but may have alternative
// implementations for special use cases. For example, alternatives may be
// streaming events from a network source or replaying of static data for
// testing.
type EvdevIterator interface {
// Next progresses the iterator. It returns false when there are no more
// elements to iterate or when the iterator encountered an error.
Next() bool
// Current returns the active element of the iterator. This should only be
// called if Next() returned a true.
Current() EvdevEvent
// Close must be called before discarding the iterator. If the iterator
// exited cleanly then the error is nil. The error is non-nil if either the
// iterator encountered an internal error and stopped early or if it failed
// to close.
Close() error
}
const (
// StateChangeMove represents a move of the x and y for the mouse.
ChangeTypeMove = "MOVE"
// StateChangeDrag represents a move of the x and y for the mouse when clicked.
ChangeTypeDrag = "DRAG"
// ChangeTypeClick indicates that the stylus is touching the tablet.
ChangeTypeClick = "CLICK"
// ChangeTypeUnclick indicates the stylus is no longer touching the tablet.
ChangeTypeUnclick = "UNCLICK"
)
// StateChangeMove contains mouse movement data.
type StateChangeMove struct {
X int
Y int
}
// Type returns the specific change type.
func (*StateChangeMove) Type() string {
return ChangeTypeMove
}
// StateChangeDrag contains mouse movement data when clicked.
type StateChangeDrag struct {
X int
Y int
}
// Type returns the specific change type.
func (*StateChangeDrag) Type() string {
return ChangeTypeDrag
}
// StateChangeClick contains mouse click data.
type StateChangeClick struct{}
// Type returns the specific change type.
func (*StateChangeClick) Type() string {
return ChangeTypeClick
}
// StateChangeUnclick contains mouse click data.
type StateChangeUnclick struct{}
// Type returns the specific change type.
func (*StateChangeUnclick) Type() string {
return ChangeTypeUnclick
}
// StateChange is a type for switching on the kind of change in order to convert
// the generic change type into a specific change type.
type StateChange interface {
Type() string
}
// StateMachine is a specialized version of the EvdevIterator that only emits
// events on significant changes of the machine.
type StateMachine interface {
// Next progresses the iterator. It returns false when there are no more
// elements to iterate or when the iterator encountered an error.
Next() bool
// Current returns the active element of the iterator. This should only be
// called if Next() returned a true.
Current() StateChange
// Close must be called before discarding the iterator. If the iterator
// exited cleanly then the error is nil. The error is non-nil if either the
// iterator encountered an internal error and stopped early or if it failed
// to close.
Close() error
}
// PositionScaler implements scaling rules for converting x/y coordinates
// between differently sized screens.
type PositionScaler interface {
ScalePosition(x int, y int) (int, int)
}
// Driver is used to control a host system.
type Driver interface {
MoveMouse(x int, y int) error
DragMouse(x int, y int) error
Click() error
Unclick() error
GetSize() (width int, height int, err error)
}
================================================
FILE: pkg/driver.go
================================================
// This file is part of remouseable.
//
// remouseable is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 3 as published
// by the Free Software Foundation.
//
// remouseable is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with remouseable. If not, see <https://www.gnu.org/licenses/>.
package remouseable
import "github.com/kevinconway/remouseable/pkg/internal/robotgo"
// RobotgoDriver implements Driver using the robotgo cgo library.
type RobotgoDriver struct{}
// GetSize returns the width and height of the host screen.
func (*RobotgoDriver) GetSize() (int, int, error) {
width, height := robotgo.GetScreenSize()
return width, height, nil
}
// Click and hold the mouse button down.
func (*RobotgoDriver) Click() error {
robotgo.MouseToggle("down", "left")
return nil
}
// Unclick and release the mouse button.
func (*RobotgoDriver) Unclick() error {
robotgo.MouseToggle("up", "left")
return nil
}
// MoveMouse sets the mouse to a specified location.
func (*RobotgoDriver) MoveMouse(x int, y int) error {
// Reversing the x/y due to robotgo seemingly having an opposite
// x/y concept as the typical event source of evdev, etc.
robotgo.MoveMouse(x, y)
return nil
}
// DragMouse sets the mouse to a specified location while dragging a screen element.
func (*RobotgoDriver) DragMouse(x int, y int) error {
// Reversing the x/y due to robotgo seemingly having an opposite
// x/y concept as the typical event source of evdev, etc.
robotgo.DragMouse(x, y)
return nil
}
================================================
FILE: pkg/evdevcodes.go
================================================
package remouseable
// Code generated DO NOT EDIT
// Generated using Linux 5.0.0-31-generic x86_64.
// Generated at 2019-10-17T00:10:35-05:00.
// Generated from /usr/include/linux/input.h, /usr/include/linux/input-event-codes.h.
const (
EV_VERSION = 0x010001
ID_BUS = 0
ID_VENDOR = 1
ID_PRODUCT = 2
ID_VERSION = 3
BUS_PCI = 0x01
BUS_ISAPNP = 0x02
BUS_USB = 0x03
BUS_HIL = 0x04
BUS_BLUETOOTH = 0x05
BUS_VIRTUAL = 0x06
BUS_ISA = 0x10
BUS_I8042 = 0x11
BUS_XTKBD = 0x12
BUS_RS232 = 0x13
BUS_GAMEPORT = 0x14
BUS_PARPORT = 0x15
BUS_AMIGA = 0x16
BUS_ADB = 0x17
BUS_I2C = 0x18
BUS_HOST = 0x19
BUS_GSC = 0x1A
BUS_ATARI = 0x1B
BUS_SPI = 0x1C
BUS_RMI = 0x1D
BUS_CEC = 0x1E
BUS_INTEL_ISHTP = 0x1F
FF_STATUS_STOPPED = 0x00
FF_STATUS_PLAYING = 0x01
FF_STATUS_MAX = 0x01
FF_RUMBLE = 0x50
FF_PERIODIC = 0x51
FF_CONSTANT = 0x52
FF_SPRING = 0x53
FF_FRICTION = 0x54
FF_DAMPER = 0x55
FF_INERTIA = 0x56
FF_RAMP = 0x57
FF_EFFECT_MIN = FF_RUMBLE
FF_EFFECT_MAX = FF_RAMP
FF_SQUARE = 0x58
FF_TRIANGLE = 0x59
FF_SINE = 0x5a
FF_SAW_UP = 0x5b
FF_SAW_DOWN = 0x5c
FF_CUSTOM = 0x5d
FF_WAVEFORM_MIN = FF_SQUARE
FF_WAVEFORM_MAX = FF_CUSTOM
FF_GAIN = 0x60
FF_AUTOCENTER = 0x61
FF_MAX_EFFECTS = FF_GAIN
FF_MAX = 0x7f
EV_SYN = 0x00
EV_KEY = 0x01
EV_REL = 0x02
EV_ABS = 0x03
EV_MSC = 0x04
EV_SW = 0x05
EV_LED = 0x11
EV_SND = 0x12
EV_REP = 0x14
EV_FF = 0x15
EV_PWR = 0x16
EV_FF_STATUS = 0x17
EV_MAX = 0x1f
SYN_REPORT = 0
SYN_CONFIG = 1
SYN_MT_REPORT = 2
SYN_DROPPED = 3
SYN_MAX = 0xf
KEY_RESERVED = 0
KEY_ESC = 1
KEY_1 = 2
KEY_2 = 3
KEY_3 = 4
KEY_4 = 5
KEY_5 = 6
KEY_6 = 7
KEY_7 = 8
KEY_8 = 9
KEY_9 = 10
KEY_0 = 11
KEY_MINUS = 12
KEY_EQUAL = 13
KEY_BACKSPACE = 14
KEY_TAB = 15
KEY_Q = 16
KEY_W = 17
KEY_E = 18
KEY_R = 19
KEY_T = 20
KEY_Y = 21
KEY_U = 22
KEY_I = 23
KEY_O = 24
KEY_P = 25
KEY_LEFTBRACE = 26
KEY_RIGHTBRACE = 27
KEY_ENTER = 28
KEY_LEFTCTRL = 29
KEY_A = 30
KEY_S = 31
KEY_D = 32
KEY_F = 33
KEY_G = 34
KEY_H = 35
KEY_J = 36
KEY_K = 37
KEY_L = 38
KEY_SEMICOLON = 39
KEY_APOSTROPHE = 40
KEY_GRAVE = 41
KEY_LEFTSHIFT = 42
KEY_BACKSLASH = 43
KEY_Z = 44
KEY_X = 45
KEY_C = 46
KEY_V = 47
KEY_B = 48
KEY_N = 49
KEY_M = 50
KEY_COMMA = 51
KEY_DOT = 52
KEY_SLASH = 53
KEY_RIGHTSHIFT = 54
KEY_KPASTERISK = 55
KEY_LEFTALT = 56
KEY_SPACE = 57
KEY_CAPSLOCK = 58
KEY_F1 = 59
KEY_F2 = 60
KEY_F3 = 61
KEY_F4 = 62
KEY_F5 = 63
KEY_F6 = 64
KEY_F7 = 65
KEY_F8 = 66
KEY_F9 = 67
KEY_F10 = 68
KEY_NUMLOCK = 69
KEY_SCROLLLOCK = 70
KEY_KP7 = 71
KEY_KP8 = 72
KEY_KP9 = 73
KEY_KPMINUS = 74
KEY_KP4 = 75
KEY_KP5 = 76
KEY_KP6 = 77
KEY_KPPLUS = 78
KEY_KP1 = 79
KEY_KP2 = 80
KEY_KP3 = 81
KEY_KP0 = 82
KEY_KPDOT = 83
KEY_ZENKAKUHANKAKU = 85
KEY_102ND = 86
KEY_F11 = 87
KEY_F12 = 88
KEY_RO = 89
KEY_KATAKANA = 90
KEY_HIRAGANA = 91
KEY_HENKAN = 92
KEY_KATAKANAHIRAGANA = 93
KEY_MUHENKAN = 94
KEY_KPJPCOMMA = 95
KEY_KPENTER = 96
KEY_RIGHTCTRL = 97
KEY_KPSLASH = 98
KEY_SYSRQ = 99
KEY_RIGHTALT = 100
KEY_LINEFEED = 101
KEY_HOME = 102
KEY_UP = 103
KEY_PAGEUP = 104
KEY_LEFT = 105
KEY_RIGHT = 106
KEY_END = 107
KEY_DOWN = 108
KEY_PAGEDOWN = 109
KEY_INSERT = 110
KEY_DELETE = 111
KEY_MACRO = 112
KEY_MUTE = 113
KEY_VOLUMEDOWN = 114
KEY_VOLUMEUP = 115
KEY_POWER = 116
KEY_KPEQUAL = 117
KEY_KPPLUSMINUS = 118
KEY_PAUSE = 119
KEY_SCALE = 120
KEY_KPCOMMA = 121
KEY_HANGEUL = 122
KEY_HANGUEL = KEY_HANGEUL
KEY_HANJA = 123
KEY_YEN = 124
KEY_LEFTMETA = 125
KEY_RIGHTMETA = 126
KEY_COMPOSE = 127
KEY_STOP = 128
KEY_AGAIN = 129
KEY_PROPS = 130
KEY_UNDO = 131
KEY_FRONT = 132
KEY_COPY = 133
KEY_OPEN = 134
KEY_PASTE = 135
KEY_FIND = 136
KEY_CUT = 137
KEY_HELP = 138
KEY_MENU = 139
KEY_CALC = 140
KEY_SETUP = 141
KEY_SLEEP = 142
KEY_WAKEUP = 143
KEY_FILE = 144
KEY_SENDFILE = 145
KEY_DELETEFILE = 146
KEY_XFER = 147
KEY_PROG1 = 148
KEY_PROG2 = 149
KEY_WWW = 150
KEY_MSDOS = 151
KEY_COFFEE = 152
KEY_SCREENLOCK = KEY_COFFEE
KEY_ROTATE_DISPLAY = 153
KEY_DIRECTION = KEY_ROTATE_DISPLAY
KEY_CYCLEWINDOWS = 154
KEY_MAIL = 155
KEY_BOOKMARKS = 156
KEY_COMPUTER = 157
KEY_BACK = 158
KEY_FORWARD = 159
KEY_CLOSECD = 160
KEY_EJECTCD = 161
KEY_EJECTCLOSECD = 162
KEY_NEXTSONG = 163
KEY_PLAYPAUSE = 164
KEY_PREVIOUSSONG = 165
KEY_STOPCD = 166
KEY_RECORD = 167
KEY_REWIND = 168
KEY_PHONE = 169
KEY_ISO = 170
KEY_CONFIG = 171
KEY_HOMEPAGE = 172
KEY_REFRESH = 173
KEY_EXIT = 174
KEY_MOVE = 175
KEY_EDIT = 176
KEY_SCROLLUP = 177
KEY_SCROLLDOWN = 178
KEY_KPLEFTPAREN = 179
KEY_KPRIGHTPAREN = 180
KEY_NEW = 181
KEY_REDO = 182
KEY_F13 = 183
KEY_F14 = 184
KEY_F15 = 185
KEY_F16 = 186
KEY_F17 = 187
KEY_F18 = 188
KEY_F19 = 189
KEY_F20 = 190
KEY_F21 = 191
KEY_F22 = 192
KEY_F23 = 193
KEY_F24 = 194
KEY_PLAYCD = 200
KEY_PAUSECD = 201
KEY_PROG3 = 202
KEY_PROG4 = 203
KEY_DASHBOARD = 204
KEY_SUSPEND = 205
KEY_CLOSE = 206
KEY_PLAY = 207
KEY_FASTFORWARD = 208
KEY_BASSBOOST = 209
KEY_PRINT = 210
KEY_HP = 211
KEY_CAMERA = 212
KEY_SOUND = 213
KEY_QUESTION = 214
KEY_EMAIL = 215
KEY_CHAT = 216
KEY_SEARCH = 217
KEY_CONNECT = 218
KEY_FINANCE = 219
KEY_SPORT = 220
KEY_SHOP = 221
KEY_ALTERASE = 222
KEY_CANCEL = 223
KEY_BRIGHTNESSDOWN = 224
KEY_BRIGHTNESSUP = 225
KEY_MEDIA = 226
KEY_SWITCHVIDEOMODE = 227
KEY_KBDILLUMTOGGLE = 228
KEY_KBDILLUMDOWN = 229
KEY_KBDILLUMUP = 230
KEY_SEND = 231
KEY_REPLY = 232
KEY_FORWARDMAIL = 233
KEY_SAVE = 234
KEY_DOCUMENTS = 235
KEY_BATTERY = 236
KEY_BLUETOOTH = 237
KEY_WLAN = 238
KEY_UWB = 239
KEY_UNKNOWN = 240
KEY_VIDEO_NEXT = 241
KEY_VIDEO_PREV = 242
KEY_BRIGHTNESS_CYCLE = 243
KEY_BRIGHTNESS_AUTO = 244
KEY_BRIGHTNESS_ZERO = KEY_BRIGHTNESS_AUTO
KEY_DISPLAY_OFF = 245
KEY_WWAN = 246
KEY_WIMAX = KEY_WWAN
KEY_RFKILL = 247
KEY_MICMUTE = 248
BTN_MISC = 0x100
BTN_0 = 0x100
BTN_1 = 0x101
BTN_2 = 0x102
BTN_3 = 0x103
BTN_4 = 0x104
BTN_5 = 0x105
BTN_6 = 0x106
BTN_7 = 0x107
BTN_8 = 0x108
BTN_9 = 0x109
BTN_MOUSE = 0x110
BTN_LEFT = 0x110
BTN_RIGHT = 0x111
BTN_MIDDLE = 0x112
BTN_SIDE = 0x113
BTN_EXTRA = 0x114
BTN_FORWARD = 0x115
BTN_BACK = 0x116
BTN_TASK = 0x117
BTN_JOYSTICK = 0x120
BTN_TRIGGER = 0x120
BTN_THUMB = 0x121
BTN_THUMB2 = 0x122
BTN_TOP = 0x123
BTN_TOP2 = 0x124
BTN_PINKIE = 0x125
BTN_BASE = 0x126
BTN_BASE2 = 0x127
BTN_BASE3 = 0x128
BTN_BASE4 = 0x129
BTN_BASE5 = 0x12a
BTN_BASE6 = 0x12b
BTN_DEAD = 0x12f
BTN_GAMEPAD = 0x130
BTN_SOUTH = 0x130
BTN_A = BTN_SOUTH
BTN_EAST = 0x131
BTN_B = BTN_EAST
BTN_C = 0x132
BTN_NORTH = 0x133
BTN_X = BTN_NORTH
BTN_WEST = 0x134
BTN_Y = BTN_WEST
BTN_Z = 0x135
BTN_TL = 0x136
BTN_TR = 0x137
BTN_TL2 = 0x138
BTN_TR2 = 0x139
BTN_SELECT = 0x13a
BTN_START = 0x13b
BTN_MODE = 0x13c
BTN_THUMBL = 0x13d
BTN_THUMBR = 0x13e
BTN_DIGI = 0x140
BTN_TOOL_PEN = 0x140
BTN_TOOL_RUBBER = 0x141
BTN_TOOL_BRUSH = 0x142
BTN_TOOL_PENCIL = 0x143
BTN_TOOL_AIRBRUSH = 0x144
BTN_TOOL_FINGER = 0x145
BTN_TOOL_MOUSE = 0x146
BTN_TOOL_LENS = 0x147
BTN_TOOL_QUINTTAP = 0x148
BTN_STYLUS3 = 0x149
BTN_TOUCH = 0x14a
BTN_STYLUS = 0x14b
BTN_STYLUS2 = 0x14c
BTN_TOOL_DOUBLETAP = 0x14d
BTN_TOOL_TRIPLETAP = 0x14e
BTN_TOOL_QUADTAP = 0x14f
BTN_WHEEL = 0x150
BTN_GEAR_DOWN = 0x150
BTN_GEAR_UP = 0x151
KEY_OK = 0x160
KEY_SELECT = 0x161
KEY_GOTO = 0x162
KEY_CLEAR = 0x163
KEY_POWER2 = 0x164
KEY_OPTION = 0x165
KEY_INFO = 0x166
KEY_TIME = 0x167
KEY_VENDOR = 0x168
KEY_ARCHIVE = 0x169
KEY_PROGRAM = 0x16a
KEY_CHANNEL = 0x16b
KEY_FAVORITES = 0x16c
KEY_EPG = 0x16d
KEY_PVR = 0x16e
KEY_MHP = 0x16f
KEY_LANGUAGE = 0x170
KEY_TITLE = 0x171
KEY_SUBTITLE = 0x172
KEY_ANGLE = 0x173
KEY_ZOOM = 0x174
KEY_MODE = 0x175
KEY_KEYBOARD = 0x176
KEY_SCREEN = 0x177
KEY_PC = 0x178
KEY_TV = 0x179
KEY_TV2 = 0x17a
KEY_VCR = 0x17b
KEY_VCR2 = 0x17c
KEY_SAT = 0x17d
KEY_SAT2 = 0x17e
KEY_CD = 0x17f
KEY_TAPE = 0x180
KEY_RADIO = 0x181
KEY_TUNER = 0x182
KEY_PLAYER = 0x183
KEY_TEXT = 0x184
KEY_DVD = 0x185
KEY_AUX = 0x186
KEY_MP3 = 0x187
KEY_AUDIO = 0x188
KEY_VIDEO = 0x189
KEY_DIRECTORY = 0x18a
KEY_LIST = 0x18b
KEY_MEMO = 0x18c
KEY_CALENDAR = 0x18d
KEY_RED = 0x18e
KEY_GREEN = 0x18f
KEY_YELLOW = 0x190
KEY_BLUE = 0x191
KEY_CHANNELUP = 0x192
KEY_CHANNELDOWN = 0x193
KEY_FIRST = 0x194
KEY_LAST = 0x195
KEY_AB = 0x196
KEY_NEXT = 0x197
KEY_RESTART = 0x198
KEY_SLOW = 0x199
KEY_SHUFFLE = 0x19a
KEY_BREAK = 0x19b
KEY_PREVIOUS = 0x19c
KEY_DIGITS = 0x19d
KEY_TEEN = 0x19e
KEY_TWEN = 0x19f
KEY_VIDEOPHONE = 0x1a0
KEY_GAMES = 0x1a1
KEY_ZOOMIN = 0x1a2
KEY_ZOOMOUT = 0x1a3
KEY_ZOOMRESET = 0x1a4
KEY_WORDPROCESSOR = 0x1a5
KEY_EDITOR = 0x1a6
KEY_SPREADSHEET = 0x1a7
KEY_GRAPHICSEDITOR = 0x1a8
KEY_PRESENTATION = 0x1a9
KEY_DATABASE = 0x1aa
KEY_NEWS = 0x1ab
KEY_VOICEMAIL = 0x1ac
KEY_ADDRESSBOOK = 0x1ad
KEY_MESSENGER = 0x1ae
KEY_DISPLAYTOGGLE = 0x1af
KEY_BRIGHTNESS_TOGGLE = KEY_DISPLAYTOGGLE
KEY_SPELLCHECK = 0x1b0
KEY_LOGOFF = 0x1b1
KEY_DOLLAR = 0x1b2
KEY_EURO = 0x1b3
KEY_FRAMEBACK = 0x1b4
KEY_FRAMEFORWARD = 0x1b5
KEY_CONTEXT_MENU = 0x1b6
KEY_MEDIA_REPEAT = 0x1b7
KEY_10CHANNELSUP = 0x1b8
KEY_10CHANNELSDOWN = 0x1b9
KEY_IMAGES = 0x1ba
KEY_DEL_EOL = 0x1c0
KEY_DEL_EOS = 0x1c1
KEY_INS_LINE = 0x1c2
KEY_DEL_LINE = 0x1c3
KEY_FN = 0x1d0
KEY_FN_ESC = 0x1d1
KEY_FN_F1 = 0x1d2
KEY_FN_F2 = 0x1d3
KEY_FN_F3 = 0x1d4
KEY_FN_F4 = 0x1d5
KEY_FN_F5 = 0x1d6
KEY_FN_F6 = 0x1d7
KEY_FN_F7 = 0x1d8
KEY_FN_F8 = 0x1d9
KEY_FN_F9 = 0x1da
KEY_FN_F10 = 0x1db
KEY_FN_F11 = 0x1dc
KEY_FN_F12 = 0x1dd
KEY_FN_1 = 0x1de
KEY_FN_2 = 0x1df
KEY_FN_D = 0x1e0
KEY_FN_E = 0x1e1
KEY_FN_F = 0x1e2
KEY_FN_S = 0x1e3
KEY_FN_B = 0x1e4
KEY_BRL_DOT1 = 0x1f1
KEY_BRL_DOT2 = 0x1f2
KEY_BRL_DOT3 = 0x1f3
KEY_BRL_DOT4 = 0x1f4
KEY_BRL_DOT5 = 0x1f5
KEY_BRL_DOT6 = 0x1f6
KEY_BRL_DOT7 = 0x1f7
KEY_BRL_DOT8 = 0x1f8
KEY_BRL_DOT9 = 0x1f9
KEY_BRL_DOT10 = 0x1fa
KEY_NUMERIC_0 = 0x200
KEY_NUMERIC_1 = 0x201
KEY_NUMERIC_2 = 0x202
KEY_NUMERIC_3 = 0x203
KEY_NUMERIC_4 = 0x204
KEY_NUMERIC_5 = 0x205
KEY_NUMERIC_6 = 0x206
KEY_NUMERIC_7 = 0x207
KEY_NUMERIC_8 = 0x208
KEY_NUMERIC_9 = 0x209
KEY_NUMERIC_STAR = 0x20a
KEY_NUMERIC_POUND = 0x20b
KEY_NUMERIC_A = 0x20c
KEY_NUMERIC_B = 0x20d
KEY_NUMERIC_C = 0x20e
KEY_NUMERIC_D = 0x20f
KEY_CAMERA_FOCUS = 0x210
KEY_WPS_BUTTON = 0x211
KEY_TOUCHPAD_TOGGLE = 0x212
KEY_TOUCHPAD_ON = 0x213
KEY_TOUCHPAD_OFF = 0x214
KEY_CAMERA_ZOOMIN = 0x215
KEY_CAMERA_ZOOMOUT = 0x216
KEY_CAMERA_UP = 0x217
KEY_CAMERA_DOWN = 0x218
KEY_CAMERA_LEFT = 0x219
KEY_CAMERA_RIGHT = 0x21a
KEY_ATTENDANT_ON = 0x21b
KEY_ATTENDANT_OFF = 0x21c
KEY_ATTENDANT_TOGGLE = 0x21d
KEY_LIGHTS_TOGGLE = 0x21e
BTN_DPAD_UP = 0x220
BTN_DPAD_DOWN = 0x221
BTN_DPAD_LEFT = 0x222
BTN_DPAD_RIGHT = 0x223
KEY_ALS_TOGGLE = 0x230
KEY_BUTTONCONFIG = 0x240
KEY_TASKMANAGER = 0x241
KEY_JOURNAL = 0x242
KEY_CONTROLPANEL = 0x243
KEY_APPSELECT = 0x244
KEY_SCREENSAVER = 0x245
KEY_VOICECOMMAND = 0x246
KEY_ASSISTANT = 0x247
KEY_BRIGHTNESS_MIN = 0x250
KEY_BRIGHTNESS_MAX = 0x251
KEY_KBDINPUTASSIST_PREV = 0x260
KEY_KBDINPUTASSIST_NEXT = 0x261
KEY_KBDINPUTASSIST_PREVGROUP = 0x262
KEY_KBDINPUTASSIST_NEXTGROUP = 0x263
KEY_KBDINPUTASSIST_ACCEPT = 0x264
KEY_KBDINPUTASSIST_CANCEL = 0x265
KEY_RIGHT_UP = 0x266
KEY_RIGHT_DOWN = 0x267
KEY_LEFT_UP = 0x268
KEY_LEFT_DOWN = 0x269
KEY_ROOT_MENU = 0x26a
KEY_MEDIA_TOP_MENU = 0x26b
KEY_NUMERIC_11 = 0x26c
KEY_NUMERIC_12 = 0x26d
KEY_AUDIO_DESC = 0x26e
KEY_3D_MODE = 0x26f
KEY_NEXT_FAVORITE = 0x270
KEY_STOP_RECORD = 0x271
KEY_PAUSE_RECORD = 0x272
KEY_VOD = 0x273
KEY_UNMUTE = 0x274
KEY_FASTREVERSE = 0x275
KEY_SLOWREVERSE = 0x276
KEY_DATA = 0x277
KEY_ONSCREEN_KEYBOARD = 0x278
BTN_TRIGGER_HAPPY = 0x2c0
BTN_TRIGGER_HAPPY1 = 0x2c0
BTN_TRIGGER_HAPPY2 = 0x2c1
BTN_TRIGGER_HAPPY3 = 0x2c2
BTN_TRIGGER_HAPPY4 = 0x2c3
BTN_TRIGGER_HAPPY5 = 0x2c4
BTN_TRIGGER_HAPPY6 = 0x2c5
BTN_TRIGGER_HAPPY7 = 0x2c6
BTN_TRIGGER_HAPPY8 = 0x2c7
BTN_TRIGGER_HAPPY9 = 0x2c8
BTN_TRIGGER_HAPPY10 = 0x2c9
BTN_TRIGGER_HAPPY11 = 0x2ca
BTN_TRIGGER_HAPPY12 = 0x2cb
BTN_TRIGGER_HAPPY13 = 0x2cc
BTN_TRIGGER_HAPPY14 = 0x2cd
BTN_TRIGGER_HAPPY15 = 0x2ce
BTN_TRIGGER_HAPPY16 = 0x2cf
BTN_TRIGGER_HAPPY17 = 0x2d0
BTN_TRIGGER_HAPPY18 = 0x2d1
BTN_TRIGGER_HAPPY19 = 0x2d2
BTN_TRIGGER_HAPPY20 = 0x2d3
BTN_TRIGGER_HAPPY21 = 0x2d4
BTN_TRIGGER_HAPPY22 = 0x2d5
BTN_TRIGGER_HAPPY23 = 0x2d6
BTN_TRIGGER_HAPPY24 = 0x2d7
BTN_TRIGGER_HAPPY25 = 0x2d8
BTN_TRIGGER_HAPPY26 = 0x2d9
BTN_TRIGGER_HAPPY27 = 0x2da
BTN_TRIGGER_HAPPY28 = 0x2db
BTN_TRIGGER_HAPPY29 = 0x2dc
BTN_TRIGGER_HAPPY30 = 0x2dd
BTN_TRIGGER_HAPPY31 = 0x2de
BTN_TRIGGER_HAPPY32 = 0x2df
BTN_TRIGGER_HAPPY33 = 0x2e0
BTN_TRIGGER_HAPPY34 = 0x2e1
BTN_TRIGGER_HAPPY35 = 0x2e2
BTN_TRIGGER_HAPPY36 = 0x2e3
BTN_TRIGGER_HAPPY37 = 0x2e4
BTN_TRIGGER_HAPPY38 = 0x2e5
BTN_TRIGGER_HAPPY39 = 0x2e6
BTN_TRIGGER_HAPPY40 = 0x2e7
KEY_MIN_INTERESTING = KEY_MUTE
KEY_MAX = 0x2ff
REL_X = 0x00
REL_Y = 0x01
REL_Z = 0x02
REL_RX = 0x03
REL_RY = 0x04
REL_RZ = 0x05
REL_HWHEEL = 0x06
REL_DIAL = 0x07
REL_WHEEL = 0x08
REL_MISC = 0x09
REL_MAX = 0x0f
ABS_X = 0x00
ABS_Y = 0x01
ABS_Z = 0x02
ABS_RX = 0x03
ABS_RY = 0x04
ABS_RZ = 0x05
ABS_THROTTLE = 0x06
ABS_RUDDER = 0x07
ABS_WHEEL = 0x08
ABS_GAS = 0x09
ABS_BRAKE = 0x0a
ABS_HAT0X = 0x10
ABS_HAT0Y = 0x11
ABS_HAT1X = 0x12
ABS_HAT1Y = 0x13
ABS_HAT2X = 0x14
ABS_HAT2Y = 0x15
ABS_HAT3X = 0x16
ABS_HAT3Y = 0x17
ABS_PRESSURE = 0x18
ABS_DISTANCE = 0x19
ABS_TILT_X = 0x1a
ABS_TILT_Y = 0x1b
ABS_TOOL_WIDTH = 0x1c
ABS_VOLUME = 0x20
ABS_MISC = 0x28
ABS_RESERVED = 0x2e
ABS_MT_SLOT = 0x2f
ABS_MT_TOUCH_MAJOR = 0x30
ABS_MT_TOUCH_MINOR = 0x31
ABS_MT_WIDTH_MAJOR = 0x32
ABS_MT_WIDTH_MINOR = 0x33
ABS_MT_ORIENTATION = 0x34
ABS_MT_POSITION_X = 0x35
ABS_MT_POSITION_Y = 0x36
ABS_MT_TOOL_TYPE = 0x37
ABS_MT_BLOB_ID = 0x38
ABS_MT_TRACKING_ID = 0x39
ABS_MT_PRESSURE = 0x3a
ABS_MT_DISTANCE = 0x3b
ABS_MT_TOOL_X = 0x3c
ABS_MT_TOOL_Y = 0x3d
ABS_MAX = 0x3f
SW_LID = 0x00
SW_TABLET_MODE = 0x01
SW_HEADPHONE_INSERT = 0x02
SW_RFKILL_ALL = 0x03
SW_RADIO = SW_RFKILL_ALL
SW_MICROPHONE_INSERT = 0x04
SW_DOCK = 0x05
SW_LINEOUT_INSERT = 0x06
SW_JACK_PHYSICAL_INSERT = 0x07
SW_VIDEOOUT_INSERT = 0x08
SW_CAMERA_LENS_COVER = 0x09
SW_KEYPAD_SLIDE = 0x0a
SW_FRONT_PROXIMITY = 0x0b
SW_ROTATE_LOCK = 0x0c
SW_LINEIN_INSERT = 0x0d
SW_MUTE_DEVICE = 0x0e
SW_PEN_INSERTED = 0x0f
SW_MAX = 0x0f
MSC_SERIAL = 0x00
MSC_PULSELED = 0x01
MSC_GESTURE = 0x02
MSC_RAW = 0x03
MSC_SCAN = 0x04
MSC_TIMESTAMP = 0x05
MSC_MAX = 0x07
LED_NUML = 0x00
LED_CAPSL = 0x01
LED_SCROLLL = 0x02
LED_COMPOSE = 0x03
LED_KANA = 0x04
LED_SLEEP = 0x05
LED_SUSPEND = 0x06
LED_MUTE = 0x07
LED_MISC = 0x08
LED_MAIL = 0x09
LED_CHARGING = 0x0a
LED_MAX = 0x0f
REP_DELAY = 0x00
REP_PERIOD = 0x01
REP_MAX = 0x01
SND_CLICK = 0x00
SND_BELL = 0x01
SND_TONE = 0x02
SND_MAX = 0x07
)
var KEYMap = map[uint16]string{0: "KEY_RESERVED", 1: "KEY_ESC", 2: "KEY_1", 3: "KEY_2", 4: "KEY_3", 5: "KEY_4", 6: "KEY_5", 7: "KEY_6", 8: "KEY_7", 9: "KEY_8", 10: "KEY_9", 11: "KEY_0", 12: "KEY_MINUS", 13: "KEY_EQUAL", 14: "KEY_BACKSPACE", 15: "KEY_TAB", 16: "KEY_Q", 17: "KEY_W", 18: "KEY_E", 19: "KEY_R", 20: "KEY_T", 21: "KEY_Y", 22: "KEY_U", 23: "KEY_I", 24: "KEY_O", 25: "KEY_P", 26: "KEY_LEFTBRACE", 27: "KEY_RIGHTBRACE", 28: "KEY_ENTER", 29: "KEY_LEFTCTRL", 30: "KEY_A", 31: "KEY_S", 32: "KEY_D", 33: "KEY_F", 34: "KEY_G", 35: "KEY_H", 36: "KEY_J", 37: "KEY_K", 38: "KEY_L", 39: "KEY_SEMICOLON", 40: "KEY_APOSTROPHE", 41: "KEY_GRAVE", 42: "KEY_LEFTSHIFT", 43: "KEY_BACKSLASH", 44: "KEY_Z", 45: "KEY_X", 46: "KEY_C", 47: "KEY_V", 48: "KEY_B", 49: "KEY_N", 50: "KEY_M", 51: "KEY_COMMA", 52: "KEY_DOT", 53: "KEY_SLASH", 54: "KEY_RIGHTSHIFT", 55: "KEY_KPASTERISK", 56: "KEY_LEFTALT", 57: "KEY_SPACE", 58: "KEY_CAPSLOCK", 59: "KEY_F1", 60: "KEY_F2", 61: "KEY_F3", 62: "KEY_F4", 63: "KEY_F5", 64: "KEY_F6", 65: "KEY_F7", 66: "KEY_F8", 67: "KEY_F9", 68: "KEY_F10", 69: "KEY_NUMLOCK", 70: "KEY_SCROLLLOCK", 71: "KEY_KP7", 72: "KEY_KP8", 73: "KEY_KP9", 74: "KEY_KPMINUS", 75: "KEY_KP4", 76: "KEY_KP5", 77: "KEY_KP6", 78: "KEY_KPPLUS", 79: "KEY_KP1", 80: "KEY_KP2", 81: "KEY_KP3", 82: "KEY_KP0", 83: "KEY_KPDOT", 85: "KEY_ZENKAKUHANKAKU", 86: "KEY_102ND", 87: "KEY_F11", 88: "KEY_F12", 89: "KEY_RO", 90: "KEY_KATAKANA", 91: "KEY_HIRAGANA", 92: "KEY_HENKAN", 93: "KEY_KATAKANAHIRAGANA", 94: "KEY_MUHENKAN", 95: "KEY_KPJPCOMMA", 96: "KEY_KPENTER", 97: "KEY_RIGHTCTRL", 98: "KEY_KPSLASH", 99: "KEY_SYSRQ", 100: "KEY_RIGHTALT", 101: "KEY_LINEFEED", 102: "KEY_HOME", 103: "KEY_UP", 104: "KEY_PAGEUP", 105: "KEY_LEFT", 106: "KEY_RIGHT", 107: "KEY_END", 108: "KEY_DOWN", 109: "KEY_PAGEDOWN", 110: "KEY_INSERT", 111: "KEY_DELETE", 112: "KEY_MACRO", 113: "KEY_MUTE", 114: "KEY_VOLUMEDOWN", 115: "KEY_VOLUMEUP", 116: "KEY_POWER", 117: "KEY_KPEQUAL", 118: "KEY_KPPLUSMINUS", 119: "KEY_PAUSE", 120: "KEY_SCALE", 121: "KEY_KPCOMMA", 122: "KEY_HANGEUL", 123: "KEY_HANJA", 124: "KEY_YEN", 125: "KEY_LEFTMETA", 126: "KEY_RIGHTMETA", 127: "KEY_COMPOSE", 128: "KEY_STOP", 129: "KEY_AGAIN", 130: "KEY_PROPS", 131: "KEY_UNDO", 132: "KEY_FRONT", 133: "KEY_COPY", 134: "KEY_OPEN", 135: "KEY_PASTE", 136: "KEY_FIND", 137: "KEY_CUT", 138: "KEY_HELP", 139: "KEY_MENU", 140: "KEY_CALC", 141: "KEY_SETUP", 142: "KEY_SLEEP", 143: "KEY_WAKEUP", 144: "KEY_FILE", 145: "KEY_SENDFILE", 146: "KEY_DELETEFILE", 147: "KEY_XFER", 148: "KEY_PROG1", 149: "KEY_PROG2", 150: "KEY_WWW", 151: "KEY_MSDOS", 152: "KEY_COFFEE", 153: "KEY_ROTATE_DISPLAY", 154: "KEY_CYCLEWINDOWS", 155: "KEY_MAIL", 156: "KEY_BOOKMARKS", 157: "KEY_COMPUTER", 158: "KEY_BACK", 159: "KEY_FORWARD", 160: "KEY_CLOSECD", 161: "KEY_EJECTCD", 162: "KEY_EJECTCLOSECD", 163: "KEY_NEXTSONG", 164: "KEY_PLAYPAUSE", 165: "KEY_PREVIOUSSONG", 166: "KEY_STOPCD", 167: "KEY_RECORD", 168: "KEY_REWIND", 169: "KEY_PHONE", 170: "KEY_ISO", 171: "KEY_CONFIG", 172: "KEY_HOMEPAGE", 173: "KEY_REFRESH", 174: "KEY_EXIT", 175: "KEY_MOVE", 176: "KEY_EDIT", 177: "KEY_SCROLLUP", 178: "KEY_SCROLLDOWN", 179: "KEY_KPLEFTPAREN", 180: "KEY_KPRIGHTPAREN", 181: "KEY_NEW", 182: "KEY_REDO", 183: "KEY_F13", 184: "KEY_F14", 185: "KEY_F15", 186: "KEY_F16", 187: "KEY_F17", 188: "KEY_F18", 189: "KEY_F19", 190: "KEY_F20", 191: "KEY_F21", 192: "KEY_F22", 193: "KEY_F23", 194: "KEY_F24", 200: "KEY_PLAYCD", 201: "KEY_PAUSECD", 202: "KEY_PROG3", 203: "KEY_PROG4", 204: "KEY_DASHBOARD", 205: "KEY_SUSPEND", 206: "KEY_CLOSE", 207: "KEY_PLAY", 208: "KEY_FASTFORWARD", 209: "KEY_BASSBOOST", 210: "KEY_PRINT", 211: "KEY_HP", 212: "KEY_CAMERA", 213: "KEY_SOUND", 214: "KEY_QUESTION", 215: "KEY_EMAIL", 216: "KEY_CHAT", 217: "KEY_SEARCH", 218: "KEY_CONNECT", 219: "KEY_FINANCE", 220: "KEY_SPORT", 221: "KEY_SHOP", 222: "KEY_ALTERASE", 223: "KEY_CANCEL", 224: "KEY_BRIGHTNESSDOWN", 225: "KEY_BRIGHTNESSUP", 226: "KEY_MEDIA", 227: "KEY_SWITCHVIDEOMODE", 228: "KEY_KBDILLUMTOGGLE", 229: "KEY_KBDILLUMDOWN", 230: "KEY_KBDILLUMUP", 231: "KEY_SEND", 232: "KEY_REPLY", 233: "KEY_FORWARDMAIL", 234: "KEY_SAVE", 235: "KEY_DOCUMENTS", 236: "KEY_BATTERY", 237: "KEY_BLUETOOTH", 238: "KEY_WLAN", 239: "KEY_UWB", 240: "KEY_UNKNOWN", 241: "KEY_VIDEO_NEXT", 242: "KEY_VIDEO_PREV", 243: "KEY_BRIGHTNESS_CYCLE", 244: "KEY_BRIGHTNESS_AUTO", 245: "KEY_DISPLAY_OFF", 246: "KEY_WWAN", 247: "KEY_RFKILL", 248: "KEY_MICMUTE", 0x160: "KEY_OK", 0x161: "KEY_SELECT", 0x162: "KEY_GOTO", 0x163: "KEY_CLEAR", 0x164: "KEY_POWER2", 0x165: "KEY_OPTION", 0x166: "KEY_INFO", 0x167: "KEY_TIME", 0x168: "KEY_VENDOR", 0x169: "KEY_ARCHIVE", 0x16a: "KEY_PROGRAM", 0x16b: "KEY_CHANNEL", 0x16c: "KEY_FAVORITES", 0x16d: "KEY_EPG", 0x16e: "KEY_PVR", 0x16f: "KEY_MHP", 0x170: "KEY_LANGUAGE", 0x171: "KEY_TITLE", 0x172: "KEY_SUBTITLE", 0x173: "KEY_ANGLE", 0x174: "KEY_ZOOM", 0x175: "KEY_MODE", 0x176: "KEY_KEYBOARD", 0x177: "KEY_SCREEN", 0x178: "KEY_PC", 0x179: "KEY_TV", 0x17a: "KEY_TV2", 0x17b: "KEY_VCR", 0x17c: "KEY_VCR2", 0x17d: "KEY_SAT", 0x17e: "KEY_SAT2", 0x17f: "KEY_CD", 0x180: "KEY_TAPE", 0x181: "KEY_RADIO", 0x182: "KEY_TUNER", 0x183: "KEY_PLAYER", 0x184: "KEY_TEXT", 0x185: "KEY_DVD", 0x186: "KEY_AUX", 0x187: "KEY_MP3", 0x188: "KEY_AUDIO", 0x189: "KEY_VIDEO", 0x18a: "KEY_DIRECTORY", 0x18b: "KEY_LIST", 0x18c: "KEY_MEMO", 0x18d: "KEY_CALENDAR", 0x18e: "KEY_RED", 0x18f: "KEY_GREEN", 0x190: "KEY_YELLOW", 0x191: "KEY_BLUE", 0x192: "KEY_CHANNELUP", 0x193: "KEY_CHANNELDOWN", 0x194: "KEY_FIRST", 0x195: "KEY_LAST", 0x196: "KEY_AB", 0x197: "KEY_NEXT", 0x198: "KEY_RESTART", 0x199: "KEY_SLOW", 0x19a: "KEY_SHUFFLE", 0x19b: "KEY_BREAK", 0x19c: "KEY_PREVIOUS", 0x19d: "KEY_DIGITS", 0x19e: "KEY_TEEN", 0x19f: "KEY_TWEN", 0x1a0: "KEY_VIDEOPHONE", 0x1a1: "KEY_GAMES", 0x1a2: "KEY_ZOOMIN", 0x1a3: "KEY_ZOOMOUT", 0x1a4: "KEY_ZOOMRESET", 0x1a5: "KEY_WORDPROCESSOR", 0x1a6: "KEY_EDITOR", 0x1a7: "KEY_SPREADSHEET", 0x1a8: "KEY_GRAPHICSEDITOR", 0x1a9: "KEY_PRESENTATION", 0x1aa: "KEY_DATABASE", 0x1ab: "KEY_NEWS", 0x1ac: "KEY_VOICEMAIL", 0x1ad: "KEY_ADDRESSBOOK", 0x1ae: "KEY_MESSENGER", 0x1af: "KEY_DISPLAYTOGGLE", 0x1b0: "KEY_SPELLCHECK", 0x1b1: "KEY_LOGOFF", 0x1b2: "KEY_DOLLAR", 0x1b3: "KEY_EURO", 0x1b4: "KEY_FRAMEBACK", 0x1b5: "KEY_FRAMEFORWARD", 0x1b6: "KEY_CONTEXT_MENU", 0x1b7: "KEY_MEDIA_REPEAT", 0x1b8: "KEY_10CHANNELSUP", 0x1b9: "KEY_10CHANNELSDOWN", 0x1ba: "KEY_IMAGES", 0x1c0: "KEY_DEL_EOL", 0x1c1: "KEY_DEL_EOS", 0x1c2: "KEY_INS_LINE", 0x1c3: "KEY_DEL_LINE", 0x1d0: "KEY_FN", 0x1d1: "KEY_FN_ESC", 0x1d2: "KEY_FN_F1", 0x1d3: "KEY_FN_F2", 0x1d4: "KEY_FN_F3", 0x1d5: "KEY_FN_F4", 0x1d6: "KEY_FN_F5", 0x1d7: "KEY_FN_F6", 0x1d8: "KEY_FN_F7", 0x1d9: "KEY_FN_F8", 0x1da: "KEY_FN_F9", 0x1db: "KEY_FN_F10", 0x1dc: "KEY_FN_F11", 0x1dd: "KEY_FN_F12", 0x1de: "KEY_FN_1", 0x1df: "KEY_FN_2", 0x1e0: "KEY_FN_D", 0x1e1: "KEY_FN_E", 0x1e2: "KEY_FN_F", 0x1e3: "KEY_FN_S", 0x1e4: "KEY_FN_B", 0x1f1: "KEY_BRL_DOT1", 0x1f2: "KEY_BRL_DOT2", 0x1f3: "KEY_BRL_DOT3", 0x1f4: "KEY_BRL_DOT4", 0x1f5: "KEY_BRL_DOT5", 0x1f6: "KEY_BRL_DOT6", 0x1f7: "KEY_BRL_DOT7", 0x1f8: "KEY_BRL_DOT8", 0x1f9: "KEY_BRL_DOT9", 0x1fa: "KEY_BRL_DOT10", 0x200: "KEY_NUMERIC_0", 0x201: "KEY_NUMERIC_1", 0x202: "KEY_NUMERIC_2", 0x203: "KEY_NUMERIC_3", 0x204: "KEY_NUMERIC_4", 0x205: "KEY_NUMERIC_5", 0x206: "KEY_NUMERIC_6", 0x207: "KEY_NUMERIC_7", 0x208: "KEY_NUMERIC_8", 0x209: "KEY_NUMERIC_9", 0x20a: "KEY_NUMERIC_STAR", 0x20b: "KEY_NUMERIC_POUND", 0x20c: "KEY_NUMERIC_A", 0x20d: "KEY_NUMERIC_B", 0x20e: "KEY_NUMERIC_C", 0x20f: "KEY_NUMERIC_D", 0x210: "KEY_CAMERA_FOCUS", 0x211: "KEY_WPS_BUTTON", 0x212: "KEY_TOUCHPAD_TOGGLE", 0x213: "KEY_TOUCHPAD_ON", 0x214: "KEY_TOUCHPAD_OFF", 0x215: "KEY_CAMERA_ZOOMIN", 0x216: "KEY_CAMERA_ZOOMOUT", 0x217: "KEY_CAMERA_UP", 0x218: "KEY_CAMERA_DOWN", 0x219: "KEY_CAMERA_LEFT", 0x21a: "KEY_CAMERA_RIGHT", 0x21b: "KEY_ATTENDANT_ON", 0x21c: "KEY_ATTENDANT_OFF", 0x21d: "KEY_ATTENDANT_TOGGLE", 0x21e: "KEY_LIGHTS_TOGGLE", 0x230: "KEY_ALS_TOGGLE", 0x240: "KEY_BUTTONCONFIG", 0x241: "KEY_TASKMANAGER", 0x242: "KEY_JOURNAL", 0x243: "KEY_CONTROLPANEL", 0x244: "KEY_APPSELECT", 0x245: "KEY_SCREENSAVER", 0x246: "KEY_VOICECOMMAND", 0x247: "KEY_ASSISTANT", 0x250: "KEY_BRIGHTNESS_MIN", 0x260: "KEY_KBDINPUTASSIST_PREV", 0x261: "KEY_KBDINPUTASSIST_NEXT", 0x262: "KEY_KBDINPUTASSIST_PREVGROUP", 0x263: "KEY_KBDINPUTASSIST_NEXTGROUP", 0x264: "KEY_KBDINPUTASSIST_ACCEPT", 0x265: "KEY_KBDINPUTASSIST_CANCEL", 0x266: "KEY_RIGHT_UP", 0x267: "KEY_RIGHT_DOWN", 0x268: "KEY_LEFT_UP", 0x269: "KEY_LEFT_DOWN", 0x26a: "KEY_ROOT_MENU", 0x26b: "KEY_MEDIA_TOP_MENU", 0x26c: "KEY_NUMERIC_11", 0x26d: "KEY_NUMERIC_12", 0x26e: "KEY_AUDIO_DESC", 0x26f: "KEY_3D_MODE", 0x270: "KEY_NEXT_FAVORITE", 0x271: "KEY_STOP_RECORD", 0x272: "KEY_PAUSE_RECORD", 0x273: "KEY_VOD", 0x274: "KEY_UNMUTE", 0x275: "KEY_FASTREVERSE", 0x276: "KEY_SLOWREVERSE", 0x277: "KEY_DATA", 0x278: "KEY_ONSCREEN_KEYBOARD"}
var ABSMap = map[uint16]string{0x00: "ABS_X", 0x01: "ABS_Y", 0x02: "ABS_Z", 0x03: "ABS_RX", 0x04: "ABS_RY", 0x05: "ABS_RZ", 0x06: "ABS_THROTTLE", 0x07: "ABS_RUDDER", 0x08: "ABS_WHEEL", 0x09: "ABS_GAS", 0x0a: "ABS_BRAKE", 0x10: "ABS_HAT0X", 0x11: "ABS_HAT0Y", 0x12: "ABS_HAT1X", 0x13: "ABS_HAT1Y", 0x14: "ABS_HAT2X", 0x15: "ABS_HAT2Y", 0x16: "ABS_HAT3X", 0x17: "ABS_HAT3Y", 0x18: "ABS_PRESSURE", 0x19: "ABS_DISTANCE", 0x1a: "ABS_TILT_X", 0x1b: "ABS_TILT_Y", 0x1c: "ABS_TOOL_WIDTH", 0x20: "ABS_VOLUME", 0x28: "ABS_MISC", 0x2e: "ABS_RESERVED", 0x2f: "ABS_MT_SLOT", 0x30: "ABS_MT_TOUCH_MAJOR", 0x31: "ABS_MT_TOUCH_MINOR", 0x32: "ABS_MT_WIDTH_MAJOR", 0x33: "ABS_MT_WIDTH_MINOR", 0x34: "ABS_MT_ORIENTATION", 0x35: "ABS_MT_POSITION_X", 0x36: "ABS_MT_POSITION_Y", 0x37: "ABS_MT_TOOL_TYPE", 0x38: "ABS_MT_BLOB_ID", 0x39: "ABS_MT_TRACKING_ID", 0x3a: "ABS_MT_PRESSURE", 0x3b: "ABS_MT_DISTANCE", 0x3c: "ABS_MT_TOOL_X", 0x3d: "ABS_MT_TOOL_Y"}
var RELMap = map[uint16]string{0x00: "REL_X", 0x01: "REL_Y", 0x02: "REL_Z", 0x03: "REL_RX", 0x04: "REL_RY", 0x05: "REL_RZ", 0x06: "REL_HWHEEL", 0x07: "REL_DIAL", 0x08: "REL_WHEEL", 0x09: "REL_MISC"}
var SWMap = map[uint16]string{0x00: "SW_LID", 0x01: "SW_TABLET_MODE", 0x02: "SW_HEADPHONE_INSERT", 0x03: "SW_RFKILL_ALL", 0x04: "SW_MICROPHONE_INSERT", 0x05: "SW_DOCK", 0x06: "SW_LINEOUT_INSERT", 0x07: "SW_JACK_PHYSICAL_INSERT", 0x08: "SW_VIDEOOUT_INSERT", 0x09: "SW_CAMERA_LENS_COVER", 0x0a: "SW_KEYPAD_SLIDE", 0x0b: "SW_FRONT_PROXIMITY", 0x0c: "SW_ROTATE_LOCK", 0x0d: "SW_LINEIN_INSERT", 0x0e: "SW_MUTE_DEVICE", 0x0f: "SW_PEN_INSERTED"}
var MSCMap = map[uint16]string{0x00: "MSC_SERIAL", 0x01: "MSC_PULSELED", 0x02: "MSC_GESTURE", 0x03: "MSC_RAW", 0x04: "MSC_SCAN", 0x05: "MSC_TIMESTAMP"}
var LEDMap = map[uint16]string{0x00: "LED_NUML", 0x01: "LED_CAPSL", 0x02: "LED_SCROLLL", 0x03: "LED_COMPOSE", 0x04: "LED_KANA", 0x05: "LED_SLEEP", 0x06: "LED_SUSPEND", 0x07: "LED_MUTE", 0x08: "LED_MISC", 0x09: "LED_MAIL", 0x0a: "LED_CHARGING"}
var BTNMap = map[uint16]string{0x100: "BTN_0", 0x101: "BTN_1", 0x102: "BTN_2", 0x103: "BTN_3", 0x104: "BTN_4", 0x105: "BTN_5", 0x106: "BTN_6", 0x107: "BTN_7", 0x108: "BTN_8", 0x109: "BTN_9", 0x110: "BTN_LEFT", 0x111: "BTN_RIGHT", 0x112: "BTN_MIDDLE", 0x113: "BTN_SIDE", 0x114: "BTN_EXTRA", 0x115: "BTN_FORWARD", 0x116: "BTN_BACK", 0x117: "BTN_TASK", 0x120: "BTN_JOYSTICK", 0x121: "BTN_THUMB", 0x122: "BTN_THUMB2", 0x123: "BTN_TOP", 0x124: "BTN_TOP2", 0x125: "BTN_PINKIE", 0x126: "BTN_BASE", 0x127: "BTN_BASE2", 0x128: "BTN_BASE3", 0x129: "BTN_BASE4", 0x12a: "BTN_BASE5", 0x12b: "BTN_BASE6", 0x12f: "BTN_DEAD", 0x130: "BTN_GAMEPAD", 0x131: "BTN_EAST", 0x132: "BTN_C", 0x133: "BTN_NORTH", 0x134: "BTN_WEST", 0x135: "BTN_Z", 0x136: "BTN_TL", 0x137: "BTN_TR", 0x138: "BTN_TL2", 0x139: "BTN_TR2", 0x13a: "BTN_SELECT", 0x13b: "BTN_START", 0x13c: "BTN_MODE", 0x13d: "BTN_THUMBL", 0x13e: "BTN_THUMBR", 0x140: "BTN_TOOL_PEN", 0x141: "BTN_TOOL_RUBBER", 0x142: "BTN_TOOL_BRUSH", 0x143: "BTN_TOOL_PENCIL", 0x144: "BTN_TOOL_AIRBRUSH", 0x145: "BTN_TOOL_FINGER", 0x146: "BTN_TOOL_MOUSE", 0x147: "BTN_TOOL_LENS", 0x148: "BTN_TOOL_QUINTTAP", 0x149: "BTN_STYLUS3", 0x14a: "BTN_TOUCH", 0x14b: "BTN_STYLUS", 0x14c: "BTN_STYLUS2", 0x14d: "BTN_TOOL_DOUBLETAP", 0x14e: "BTN_TOOL_TRIPLETAP", 0x14f: "BTN_TOOL_QUADTAP", 0x150: "BTN_GEAR_DOWN", 0x151: "BTN_GEAR_UP", 0x220: "BTN_DPAD_UP", 0x221: "BTN_DPAD_DOWN", 0x222: "BTN_DPAD_LEFT", 0x223: "BTN_DPAD_RIGHT", 0x2c0: "BTN_TRIGGER_HAPPY1", 0x2c1: "BTN_TRIGGER_HAPPY2", 0x2c2: "BTN_TRIGGER_HAPPY3", 0x2c3: "BTN_TRIGGER_HAPPY4", 0x2c4: "BTN_TRIGGER_HAPPY5", 0x2c5: "BTN_TRIGGER_HAPPY6", 0x2c6: "BTN_TRIGGER_HAPPY7", 0x2c7: "BTN_TRIGGER_HAPPY8", 0x2c8: "BTN_TRIGGER_HAPPY9", 0x2c9: "BTN_TRIGGER_HAPPY10", 0x2ca: "BTN_TRIGGER_HAPPY11", 0x2cb: "BTN_TRIGGER_HAPPY12", 0x2cc: "BTN_TRIGGER_HAPPY13", 0x2cd: "BTN_TRIGGER_HAPPY14", 0x2ce: "BTN_TRIGGER_HAPPY15", 0x2cf: "BTN_TRIGGER_HAPPY16", 0x2d0: "BTN_TRIGGER_HAPPY17", 0x2d1: "BTN_TRIGGER_HAPPY18", 0x2d2: "BTN_TRIGGER_HAPPY19", 0x2d3: "BTN_TRIGGER_HAPPY20", 0x2d4: "BTN_TRIGGER_HAPPY21", 0x2d5: "BTN_TRIGGER_HAPPY22", 0x2d6: "BTN_TRIGGER_HAPPY23", 0x2d7: "BTN_TRIGGER_HAPPY24", 0x2d8: "BTN_TRIGGER_HAPPY25", 0x2d9: "BTN_TRIGGER_HAPPY26", 0x2da: "BTN_TRIGGER_HAPPY27", 0x2db: "BTN_TRIGGER_HAPPY28", 0x2dc: "BTN_TRIGGER_HAPPY29", 0x2dd: "BTN_TRIGGER_HAPPY30", 0x2de: "BTN_TRIGGER_HAPPY31", 0x2df: "BTN_TRIGGER_HAPPY32", 0x2e0: "BTN_TRIGGER_HAPPY33", 0x2e1: "BTN_TRIGGER_HAPPY34", 0x2e2: "BTN_TRIGGER_HAPPY35", 0x2e3: "BTN_TRIGGER_HAPPY36", 0x2e4: "BTN_TRIGGER_HAPPY37", 0x2e5: "BTN_TRIGGER_HAPPY38", 0x2e6: "BTN_TRIGGER_HAPPY39", 0x2e7: "BTN_TRIGGER_HAPPY40"}
var REPMap = map[uint16]string{0x00: "REP_DELAY", 0x01: "REP_PERIOD"}
var SNDMap = map[uint16]string{0x00: "SND_CLICK", 0x01: "SND_BELL", 0x02: "SND_TONE"}
var IDMap = map[uint16]string{0: "ID_BUS", 1: "ID_VENDOR", 2: "ID_PRODUCT", 3: "ID_VERSION"}
var EVMap = map[uint16]string{0x00: "EV_SYN", 0x01: "EV_KEY", 0x02: "EV_REL", 0x03: "EV_ABS", 0x04: "EV_MSC", 0x05: "EV_SW", 0x11: "EV_LED", 0x12: "EV_SND", 0x14: "EV_REP", 0x15: "EV_FF", 0x16: "EV_PWR", 0x17: "EV_FF_STATUS"}
var BUSMap = map[uint16]string{0x01: "BUS_PCI", 0x02: "BUS_ISAPNP", 0x03: "BUS_USB", 0x04: "BUS_HIL", 0x05: "BUS_BLUETOOTH", 0x06: "BUS_VIRTUAL", 0x10: "BUS_ISA", 0x11: "BUS_I8042", 0x12: "BUS_XTKBD", 0x13: "BUS_RS232", 0x14: "BUS_GAMEPORT", 0x15: "BUS_PARPORT", 0x16: "BUS_AMIGA", 0x17: "BUS_ADB", 0x18: "BUS_I2C", 0x19: "BUS_HOST", 0x1A: "BUS_GSC", 0x1B: "BUS_ATARI", 0x1C: "BUS_SPI", 0x1D: "BUS_RMI", 0x1E: "BUS_CEC", 0x1F: "BUS_INTEL_ISHTP"}
var SYNMap = map[uint16]string{0: "SYN_REPORT", 1: "SYN_CONFIG", 2: "SYN_MT_REPORT", 3: "SYN_DROPPED"}
var FFMap = map[uint16]string{0x00: "FF_STATUS_STOPPED", 0x01: "FF_STATUS_PLAYING", 0x50: "FF_RUMBLE", 0x51: "FF_PERIODIC", 0x52: "FF_CONSTANT", 0x53: "FF_SPRING", 0x54: "FF_FRICTION", 0x55: "FF_DAMPER", 0x56: "FF_INERTIA", 0x57: "FF_RAMP", 0x58: "FF_SQUARE", 0x59: "FF_TRIANGLE", 0x5a: "FF_SINE", 0x5b: "FF_SAW_UP", 0x5c: "FF_SAW_DOWN", 0x5d: "FF_CUSTOM", 0x60: "FF_GAIN", 0x61: "FF_AUTOCENTER"}
func CodeString(etype uint16, code uint16) string {
var stype = EVMap[etype]
switch stype {
case "EV_SYN":
return SYNMap[code]
case "EV_KEY":
return KEYMap[code]
case "EV_ABS":
return ABSMap[code]
case "EV_REL":
return RELMap[code]
case "EV_SW":
return SWMap[code]
case "EV_MSC":
return MSCMap[code]
case "EV_LED":
return LEDMap[code]
case "EV_SND":
return SNDMap[code]
case "EV_REP":
return REPMap[code]
case "EV_FF":
return FFMap[code]
default:
return ""
}
}
================================================
FILE: pkg/evdeviterator.go
================================================
// This file is part of remouseable.
//
// remouseable is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 3 as published
// by the Free Software Foundation.
//
// remouseable is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with remouseable. If not, see <https://www.gnu.org/licenses/>.
package remouseable
import (
"bytes"
"encoding/binary"
"io"
"time"
)
type rawEvent struct {
// The time values must be uint32 to work with the tablet build. The default
// syscall.Timeval uses uint64 on a 64bit platform so we must adapt here.
Sec uint32
Usec uint32
Type uint16
Code uint16
Value int32
}
// FileEvdevIterator implements the EvdevIterator interface by consuming from
// an io.ReadCloser.
type FileEvdevIterator struct {
Source io.ReadCloser
err error
current EvdevEvent
}
// Next reads an event from the file source.
func (it *FileEvdevIterator) Next() bool {
if it.err != nil {
// Prevent re-entry after an error.
return false
}
evt := rawEvent{}
size := binary.Size(evt)
buf := make([]byte, size)
if _, err := it.Source.Read(buf); err != nil {
it.err = err
return false
}
if err := binary.Read(bytes.NewReader(buf), binary.LittleEndian, &evt); err != nil {
it.err = err
return false
}
it.current = EvdevEvent{
Time: time.Unix(int64(evt.Sec), int64(evt.Usec)),
Type: evt.Type,
Code: evt.Code,
Value: evt.Value,
}
return true
}
// Current returns the iterator value.
func (it *FileEvdevIterator) Current() EvdevEvent {
return it.current
}
// Close the underlying source and return any errors.
func (it *FileEvdevIterator) Close() error {
err := it.Source.Close()
if it.err == nil {
return err
}
return it.err
}
// SelectingEvdevIterator reduces an iterator output to a selection of top-level
// event types.
type SelectingEvdevIterator struct {
Wrapped EvdevIterator
Selection []uint16
current EvdevEvent
}
// Next continually calls the wrapped Next() until it either returns a value
// that matches the selection criteria or it returns a false.
func (it *SelectingEvdevIterator) Next() bool {
for it.Wrapped.Next() {
c := it.Wrapped.Current()
for _, selection := range it.Selection {
if c.Type == selection {
it.current = c
return true
}
}
}
return false
}
// Current returns the active element.
func (it *SelectingEvdevIterator) Current() EvdevEvent {
return it.current
}
// Close proxies to the wrapped instance.
func (it *SelectingEvdevIterator) Close() error {
return it.Wrapped.Close()
}
// FilteringEvdevIterator reduces an iterator output to all but a selection of
// top-level event types.
type FilteringEvdevIterator struct {
Wrapped EvdevIterator
Filter []uint16
current EvdevEvent
}
// Next continually calls the wrapped Next() until it either returns a value
// that matches the filter criteria or it returns a false.
func (it *FilteringEvdevIterator) Next() bool {
for it.Wrapped.Next() {
c := it.Wrapped.Current()
ok := true
for _, filter := range it.Filter {
if c.Type == filter {
ok = false
break
}
}
if ok {
it.current = c
return true
}
}
return false
}
// Current returns the active element.
func (it *FilteringEvdevIterator) Current() EvdevEvent {
return it.current
}
// Close proxies to the wrapped instance.
func (it *FilteringEvdevIterator) Close() error {
return it.Wrapped.Close()
}
================================================
FILE: pkg/evdeviterator_test.go
================================================
// This file is part of remouseable.
//
// remouseable is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 3 as published
// by the Free Software Foundation.
//
// remouseable is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with remouseable. If not, see <https://www.gnu.org/licenses/>.
package remouseable
import (
"fmt"
"testing"
gomock "github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
)
func TestFileEvdevIterator_Next(t *testing.T) {
sentinelErr := fmt.Errorf("test")
tests := []struct {
name string
want bool
wantErr bool
expectedErr error
wantRead bool
readBytes []byte
readErr error
closeErr error
}{
{
name: "read error",
want: false,
wantErr: true,
expectedErr: sentinelErr,
wantRead: true,
readBytes: nil,
readErr: sentinelErr,
closeErr: nil,
},
{
name: "read data",
want: true,
wantErr: false,
expectedErr: nil,
wantRead: true,
readBytes: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
readErr: nil,
closeErr: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
src := NewMockReadCloser(ctrl)
it := &FileEvdevIterator{
Source: src,
}
if tt.wantRead {
src.EXPECT().Read(gomock.Any()).Do(func(b []byte) {
copy(b, tt.readBytes)
}).Return(0, tt.readErr)
}
src.EXPECT().Close().Return(tt.closeErr).AnyTimes()
require.Equal(t, tt.want, it.Next())
if tt.wantErr {
require.Equal(t, tt.expectedErr, it.Close())
require.Equal(t, false, it.Next())
}
})
}
}
func TestSelectingEvdevIterator_Next(t *testing.T) {
type fields struct {
Selection []uint16
}
tests := []struct {
name string
fields fields
source []EvdevEvent
expected []EvdevEvent
}{
{
name: "empty source",
fields: fields{Selection: []uint16{0}},
source: []EvdevEvent{},
expected: []EvdevEvent{},
},
{
name: "full set",
fields: fields{Selection: []uint16{0}},
source: []EvdevEvent{{}, {}, {}},
expected: []EvdevEvent{{}, {}, {}},
},
{
name: "partial set",
fields: fields{Selection: []uint16{0}},
source: []EvdevEvent{{Type: 1}, {Type: 1}, {Type: 0}},
expected: []EvdevEvent{{Type: 0}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
wrapped := NewMockEvdevIterator(ctrl)
it := &SelectingEvdevIterator{
Wrapped: wrapped,
Selection: tt.fields.Selection,
}
for _, s := range tt.source {
wrapped.EXPECT().Next().Return(true)
wrapped.EXPECT().Current().Return(s)
}
wrapped.EXPECT().Next().Return(false)
wrapped.EXPECT().Close().Return(nil)
results := make([]EvdevEvent, 0, len(tt.expected))
for it.Next() {
results = append(results, it.Current())
}
require.Equal(t, nil, it.Close())
require.ElementsMatch(t, tt.expected, results)
})
}
}
func TestFilteringEvdevIterator_Next(t *testing.T) {
type fields struct {
Filter []uint16
}
tests := []struct {
name string
fields fields
source []EvdevEvent
expected []EvdevEvent
}{
{
name: "empty source",
fields: fields{Filter: []uint16{0}},
source: []EvdevEvent{},
expected: []EvdevEvent{},
},
{
name: "all filtered",
fields: fields{Filter: []uint16{0}},
source: []EvdevEvent{{}, {}, {}},
expected: []EvdevEvent{},
},
{
name: "partial filter",
fields: fields{Filter: []uint16{0}},
source: []EvdevEvent{{Type: 1}, {Type: 1}, {Type: 0}},
expected: []EvdevEvent{{Type: 1}, {Type: 1}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
wrapped := NewMockEvdevIterator(ctrl)
it := &FilteringEvdevIterator{
Wrapped: wrapped,
Filter: tt.fields.Filter,
}
for _, s := range tt.source {
wrapped.EXPECT().Next().Return(true)
wrapped.EXPECT().Current().Return(s)
}
wrapped.EXPECT().Next().Return(false)
wrapped.EXPECT().Close().Return(nil)
results := make([]EvdevEvent, 0, len(tt.expected))
for it.Next() {
results = append(results, it.Current())
}
require.Equal(t, nil, it.Close())
require.ElementsMatch(t, tt.expected, results)
})
}
}
================================================
FILE: pkg/gen.go
================================================
package remouseable
//go:generate mockgen -destination mock_driver_test.go -package remouseable -self_package github.com/kevinconway/remouseable/pkg github.com/kevinconway/remouseable/pkg Driver
//go:generate mockgen -destination mock_positionscaler_test.go -package remouseable -self_package github.com/kevinconway/remouseable/pkg github.com/kevinconway/remouseable/pkg PositionScaler
//go:generate mockgen -destination mock_statemachine_test.go -package remouseable -self_package github.com/kevinconway/remouseable/pkg github.com/kevinconway/remouseable/pkg StateMachine
//go:generate mockgen -destination mock_evdeviterator_test.go -package remouseable -self_package github.com/kevinconway/remouseable/pkg github.com/kevinconway/remouseable/pkg EvdevIterator
//go:generate mockgen -destination mock_readcloser_test.go -package remouseable -self_package github.com/kevinconway/remouseable/pkg io ReadCloser
================================================
FILE: pkg/internal/gen.go
================================================
package internal
import (
// Force a nimport of mock so that it guarantees that the mock package
// will be included in vendor.
_ "github.com/golang/mock/mockgen/model"
)
//go:generate go run ./gencodes --destination=../evdevcodes.go
================================================
FILE: pkg/internal/gencodes/main.go
================================================
// This file is part of remouseable.
//
// remouseable is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 3 as published
// by the Free Software Foundation.
//
// remouseable is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with remouseable. If not, see <https://www.gnu.org/licenses/>.
// Package main generates a Go source file that contains a mapping of all
// evdev codes by extracting them from the linux source code files.
package main
import (
"bufio"
"bytes"
"fmt"
"os"
"regexp"
"strings"
"time"
"github.com/dave/jennifer/jen"
flag "github.com/spf13/pflag"
sys "golang.org/x/sys/unix"
)
var sourceFiles = []string{
"/usr/include/linux/input.h",
"/usr/include/linux/input-event-codes.h",
}
// pattern is copied from github.com/gvalkov/golang-evdev
const pattern = `#define +((?:KEY|ABS|REL|SW|MSC|LED|BTN|REP|SND|ID|EV|BUS|SYN|FF)_\w+)\s+(\w+)`
func main() {
fs := flag.NewFlagSet("gencodes", flag.ExitOnError)
srcs := fs.StringArray("sources", sourceFiles, "Linux header source files to process.")
dst := fs.String("destination", "evdevcodes.go", "The destination file path. Use - for stdout.")
_ = fs.Parse(os.Args[1:])
reg, err := regexp.Compile(pattern)
if err != nil {
panic(err)
}
codes := make([][]string, 0)
for _, src := range *srcs {
f, fErr := os.Open(src)
if fErr != nil {
panic(fErr)
}
defer f.Close()
bf := bufio.NewScanner(f)
for bf.Scan() {
line := bf.Text()
matches := reg.FindAllStringSubmatch(line, -1)
for _, match := range matches {
codes = append(codes, match[1:])
}
}
if bf.Err() != nil {
panic(bf.Err())
}
}
un := &sys.Utsname{}
if err = sys.Uname(un); err != nil {
panic(err)
}
f := jen.NewFile("remouseable")
f.Comment("// Code generated DO NOT EDIT").Line()
f.Comment(
fmt.Sprintf(
"// Generated using %s %s %s.",
string(bytes.Trim(un.Sysname[:], "\x00")),
string(bytes.Trim(un.Release[:], "\x00")),
string(bytes.Trim(un.Machine[:], "\x00")),
),
)
f.Comment(
fmt.Sprintf(
"// Generated at %s.",
time.Now().Format(time.RFC3339),
),
)
f.Comment(
fmt.Sprintf(
"// Generated from %s.",
strings.Join(*srcs, ", "),
),
)
keyMaps := make([]jen.Code, 0)
absMaps := make([]jen.Code, 0)
relMaps := make([]jen.Code, 0)
swMaps := make([]jen.Code, 0)
mscMaps := make([]jen.Code, 0)
ledMaps := make([]jen.Code, 0)
btnMaps := make([]jen.Code, 0)
repMaps := make([]jen.Code, 0)
sndMaps := make([]jen.Code, 0)
idMaps := make([]jen.Code, 0)
evMaps := make([]jen.Code, 0)
busMaps := make([]jen.Code, 0)
synMaps := make([]jen.Code, 0)
ffMaps := make([]jen.Code, 0)
defs := make([]jen.Code, 0, len(codes))
for _, code := range codes {
name := code[0]
value := code[1]
defs = append(defs, jen.Id(name).Op("=").Id(value))
if name == "EV_VERSION" || strings.HasSuffix(name, "_MAX") {
// EV_VERSION is not a uint16 value and is also not an event type.
// *_MAX are often duplicated by other named values.
continue
}
if name == "BTN_TRIGGER" || name == "BTN_SOUTH" || name == "BTN_DIGI" || name == "BTN_WHEEL" || name == "BTN_TRIGGER_HAPPY" || name == "BTN_MISC" || name == "BTN_MOUSE" {
// BTN_TRIGGER is a duplicate of BTN_TASK
// BTN_SOUTH is a duplicate of BTN_GAMEPAD
// BTN_DIGI is a duplicate of BTN_TOOL_PEN
// BTN_WHEEL is a duplicate of BTN_GEAR_DOWN
// BTN_TRIGGER_HAPPY is a duplicate of BTN_TRIGGER_HAPPY1
// BTN_MISC is a duplicate of BTN_0
// BTN_MOUSE is a duplicate of BTN_LEFT
continue
}
switch {
case strings.HasPrefix(name, "KEY") && !strings.HasPrefix(value, "KEY"):
keyMaps = append(keyMaps, jen.Id(value).Op(":").Lit(name))
case strings.HasPrefix(name, "ABS") && !strings.HasPrefix(value, "ABS"):
absMaps = append(absMaps, jen.Id(value).Op(":").Lit(name))
case strings.HasPrefix(name, "REL") && !strings.HasPrefix(value, "REL"):
relMaps = append(relMaps, jen.Id(value).Op(":").Lit(name))
case strings.HasPrefix(name, "SW") && !strings.HasPrefix(value, "SW"):
swMaps = append(swMaps, jen.Id(value).Op(":").Lit(name))
case strings.HasPrefix(name, "MSC") && !strings.HasPrefix(value, "MSC"):
mscMaps = append(mscMaps, jen.Id(value).Op(":").Lit(name))
case strings.HasPrefix(name, "LED") && !strings.HasPrefix(value, "LED"):
ledMaps = append(ledMaps, jen.Id(value).Op(":").Lit(name))
case strings.HasPrefix(name, "BTN") && !strings.HasPrefix(value, "BTN"):
btnMaps = append(btnMaps, jen.Id(value).Op(":").Lit(name))
case strings.HasPrefix(name, "REP") && !strings.HasPrefix(value, "REP"):
repMaps = append(repMaps, jen.Id(value).Op(":").Lit(name))
case strings.HasPrefix(name, "SND") && !strings.HasPrefix(value, "SND"):
sndMaps = append(sndMaps, jen.Id(value).Op(":").Lit(name))
case strings.HasPrefix(name, "ID") && !strings.HasPrefix(value, "ID"):
idMaps = append(idMaps, jen.Id(value).Op(":").Lit(name))
case strings.HasPrefix(name, "EV") && !strings.HasPrefix(value, "EV"):
evMaps = append(evMaps, jen.Id(value).Op(":").Lit(name))
case strings.HasPrefix(name, "BUS") && !strings.HasPrefix(value, "BUS"):
busMaps = append(busMaps, jen.Id(value).Op(":").Lit(name))
case strings.HasPrefix(name, "SYN") && !strings.HasPrefix(value, "SYN"):
synMaps = append(synMaps, jen.Id(value).Op(":").Lit(name))
case strings.HasPrefix(name, "FF") && !strings.HasPrefix(value, "FF"):
ffMaps = append(ffMaps, jen.Id(value).Op(":").Lit(name))
}
}
f.Const().Defs(defs...)
f.Var().Id("KEYMap").Op("=").Map(jen.Uint16()).String().Values(keyMaps...)
f.Var().Id("ABSMap").Op("=").Map(jen.Uint16()).String().Values(absMaps...)
f.Var().Id("RELMap").Op("=").Map(jen.Uint16()).String().Values(relMaps...)
f.Var().Id("SWMap").Op("=").Map(jen.Uint16()).String().Values(swMaps...)
f.Var().Id("MSCMap").Op("=").Map(jen.Uint16()).String().Values(mscMaps...)
f.Var().Id("LEDMap").Op("=").Map(jen.Uint16()).String().Values(ledMaps...)
f.Var().Id("BTNMap").Op("=").Map(jen.Uint16()).String().Values(btnMaps...)
f.Var().Id("REPMap").Op("=").Map(jen.Uint16()).String().Values(repMaps...)
f.Var().Id("SNDMap").Op("=").Map(jen.Uint16()).String().Values(sndMaps...)
f.Var().Id("IDMap").Op("=").Map(jen.Uint16()).String().Values(idMaps...)
f.Var().Id("EVMap").Op("=").Map(jen.Uint16()).String().Values(evMaps...)
f.Var().Id("BUSMap").Op("=").Map(jen.Uint16()).String().Values(busMaps...)
f.Var().Id("SYNMap").Op("=").Map(jen.Uint16()).String().Values(synMaps...)
f.Var().Id("FFMap").Op("=").Map(jen.Uint16()).String().Values(ffMaps...)
f.Func().Id("CodeString").Params(jen.Id("etype").Uint16(), jen.Id("code").Uint16()).String().Block(
jen.Var().Id("stype").Op("=").Id("EVMap").Index(jen.Id("etype")),
jen.Switch(jen.Id("stype")).Block(
jen.Case(jen.Lit("EV_SYN")).Block(
jen.Return(jen.Id("SYNMap").Index(jen.Id("code"))),
),
jen.Case(jen.Lit("EV_KEY")).Block(
jen.Return(jen.Id("KEYMap").Index(jen.Id("code"))),
),
jen.Case(jen.Lit("EV_ABS")).Block(
jen.Return(jen.Id("ABSMap").Index(jen.Id("code"))),
),
jen.Case(jen.Lit("EV_REL")).Block(
jen.Return(jen.Id("RELMap").Index(jen.Id("code"))),
),
jen.Case(jen.Lit("EV_SW")).Block(
jen.Return(jen.Id("SWMap").Index(jen.Id("code"))),
),
jen.Case(jen.Lit("EV_MSC")).Block(
jen.Return(jen.Id("MSCMap").Index(jen.Id("code"))),
),
jen.Case(jen.Lit("EV_LED")).Block(
jen.Return(jen.Id("LEDMap").Index(jen.Id("code"))),
),
jen.Case(jen.Lit("EV_SND")).Block(
jen.Return(jen.Id("SNDMap").Index(jen.Id("code"))),
),
jen.Case(jen.Lit("EV_REP")).Block(
jen.Return(jen.Id("REPMap").Index(jen.Id("code"))),
),
jen.Case(jen.Lit("EV_FF")).Block(
jen.Return(jen.Id("FFMap").Index(jen.Id("code"))),
),
jen.Default().Block(
jen.Return(jen.Lit("")),
),
),
)
if *dst == "-" {
if err = f.Render(os.Stdout); err != nil {
panic(err)
}
return
}
if err = f.Save(*dst); err != nil {
panic(err)
}
}
================================================
FILE: pkg/internal/robotgo/base/LICENSE
================================================
The software is licensed under the terms of the MIT license.
Copyright 2010 Michael Sanders, AE and the go-vgo Project Developers.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: pkg/internal/robotgo/base/MMBitmap.h
================================================
#pragma once
#ifndef MMBITMAP_H
#define MMBITMAP_H
#include "types.h"
#include "rgb.h"
#include <assert.h>
// #include <stdint.h>
#if defined(_MSC_VER)
#include "ms_stdint.h"
#else
#include <stdint.h>
#endif
#ifdef __cplusplus
extern "C"
{
#endif
struct _MMBitmap {
uint8_t *imageBuffer; /* Pixels stored in Quad I format; i.e., origin is in
* top left. Length should be height * bytewidth. */
size_t width; /* Never 0, unless image is NULL. */
size_t height; /* Never 0, unless image is NULL. */
size_t bytewidth; /* The aligned width (width + padding). */
uint8_t bitsPerPixel; /* Should be either 24 or 32. */
uint8_t bytesPerPixel; /* For convenience; should be bitsPerPixel / 8. */
};
typedef struct _MMBitmap MMBitmap;
typedef MMBitmap *MMBitmapRef;
// MMBitmapRef bitmap;
/* Creates new MMBitmap with the given values.
* Follows the Create Rule (caller is responsible for destroy()'ing object). */
MMBitmapRef createMMBitmap(uint8_t *buffer, size_t width, size_t height,
size_t bytewidth, uint8_t bitsPerPixel,
uint8_t bytesPerPixel);
/* Releases memory occupied by MMBitmap. */
void destroyMMBitmap(MMBitmapRef bitmap);
/* Releases memory occupied by MMBitmap. Acts via CallBack method*/
void destroyMMBitmapBuffer(char * bitmapBuffer, void * hint);
/* Returns copy of MMBitmap, to be destroy()'d by caller. */
MMBitmapRef copyMMBitmap(MMBitmapRef bitmap);
/* Returns copy of one MMBitmap juxtaposed in another (to be destroy()'d
* by the caller.), or NULL on error. */
MMBitmapRef copyMMBitmapFromPortion(MMBitmapRef source, MMRect rect);
#define MMBitmapPointInBounds(image, p) ((p).x < (image)->width && \
(p).y < (image)->height)
#define MMBitmapRectInBounds(image, r) \
(((r).origin.x + (r).size.width <= (image)->width) && \
((r).origin.y + (r).size.height <= (image)->height))
#define MMBitmapGetBounds(image) MMRectMake(0, 0, image->width, image->height)
/* Get pointer to pixel of MMBitmapRef. No bounds checking is performed (check
* yourself before calling this with MMBitmapPointInBounds(). */
#define MMRGBColorRefAtPoint(image, x, y) \
(MMRGBColor *)(assert(MMBitmapPointInBounds(image, MMPointMake(x, y))), \
((image)->imageBuffer) + (((image)->bytewidth * (y)) \
+ ((x) * (image)->bytesPerPixel)))
/* Dereference pixel of MMBitmapRef. Again, no bounds checking is performed. */
#define MMRGBColorAtPoint(image, x, y) *MMRGBColorRefAtPoint(image, x, y)
/* Hex/integer value of color at point. */
#define MMRGBHexAtPoint(image, x, y) \
hexFromMMRGB(MMRGBColorAtPoint(image, x, y))
/* Increment either point.x or point.y depending on the position of point.x.
* That is, if x + 1 is >= width, increment y and start x at the beginning.
* Otherwise, increment x.
*
* This is used as a convenience macro to scan rows when calling functions such
* as findColorInRectAt() and findBitmapInBitmapAt(). */
#define ITER_NEXT_POINT(pixel, width, start_x) \
do { \
if (++(pixel).x >= (width)) { \
(pixel).x = start_x; \
++(point).y; \
} \
} while (0);
#ifdef __cplusplus
}
#endif
#endif /* MMBITMAP_H */
================================================
FILE: pkg/internal/robotgo/base/MMBitmap_c.h
================================================
#include "MMBitmap.h"
#include <assert.h>
#include <string.h>
//MMBitmapRef createMMBitmap()
MMBitmapRef createMMBitmap(
uint8_t *buffer,
size_t width,
size_t height,
size_t bytewidth,
uint8_t bitsPerPixel,
uint8_t bytesPerPixel
){
MMBitmapRef bitmap = malloc(sizeof(MMBitmap));
if (bitmap == NULL) return NULL;
bitmap->imageBuffer = buffer;
bitmap->width = width;
bitmap->height = height;
bitmap->bytewidth = bytewidth;
bitmap->bitsPerPixel = bitsPerPixel;
bitmap->bytesPerPixel = bytesPerPixel;
return bitmap;
}
void destroyMMBitmap(MMBitmapRef bitmap)
{
assert(bitmap != NULL);
if (bitmap->imageBuffer != NULL) {
free(bitmap->imageBuffer);
bitmap->imageBuffer = NULL;
}
free(bitmap);
}
void destroyMMBitmapBuffer(char * bitmapBuffer, void * hint)
{
if (bitmapBuffer != NULL)
{
free(bitmapBuffer);
}
}
MMBitmapRef copyMMBitmap(MMBitmapRef bitmap)
{
uint8_t *copiedBuf = NULL;
assert(bitmap != NULL);
if (bitmap->imageBuffer != NULL) {
const size_t bufsize = bitmap->height * bitmap->bytewidth;
copiedBuf = malloc(bufsize);
if (copiedBuf == NULL) return NULL;
memcpy(copiedBuf, bitmap->imageBuffer, bufsize);
}
return createMMBitmap(copiedBuf,
bitmap->width,
bitmap->height,
bitmap->bytewidth,
bitmap->bitsPerPixel,
bitmap->bytesPerPixel);
}
MMBitmapRef copyMMBitmapFromPortion(MMBitmapRef source, MMRect rect)
{
assert(source != NULL);
if (source->imageBuffer == NULL || !MMBitmapRectInBounds(source, rect)) {
return NULL;
} else {
uint8_t *copiedBuf = NULL;
const size_t bufsize = rect.size.height * source->bytewidth;
const size_t offset = (source->bytewidth * rect.origin.y) +
(rect.origin.x * source->bytesPerPixel);
/* Don't go over the bounds, programmer! */
assert((bufsize + offset) <= (source->bytewidth * source->height));
copiedBuf = malloc(bufsize);
if (copiedBuf == NULL) return NULL;
memcpy(copiedBuf, source->imageBuffer + offset, bufsize);
return createMMBitmap(copiedBuf,
rect.size.width,
rect.size.height,
source->bytewidth,
source->bitsPerPixel,
source->bytesPerPixel);
}
}
================================================
FILE: pkg/internal/robotgo/base/MMPointArray.h
================================================
#pragma once
#ifndef MMARRAY_H
#define MMARRAY_H
#include "types.h"
struct _MMPointArray {
MMPoint *array; /* Pointer to actual data. */
size_t count; /* Number of elements in array. */
size_t _allocedCount; /* Private; do not use outside of MMPointArray.c. */
};
typedef struct _MMPointArray MMPointArray;
typedef MMPointArray *MMPointArrayRef;
/* Creates array of an initial size (the maximum size is still limitless).
* This follows the "Create" Rule; i.e., responsibility for "destroying" the
* array is given to the caller. */
MMPointArrayRef createMMPointArray(size_t initialCount);
/* Frees memory occupied by |pointArray|. Does not accept NULL. */
void destroyMMPointArray(MMPointArrayRef pointArray);
/* Appends a point to an array, increasing the internal size if necessary. */
void MMPointArrayAppendPoint(MMPointArrayRef pointArray, MMPoint point);
/* Retrieve point from array. */
#define MMPointArrayGetItem(a, i) ((a)->array)[i]
/* Set point in array. */
#define MMPointArraySetItem(a, i, item) ((a)->array[i] = item)
#endif /* MMARRAY_H */
================================================
FILE: pkg/internal/robotgo/base/MMPointArray_c.h
================================================
#include "MMPointArray.h"
#include <stdlib.h>
MMPointArrayRef createMMPointArray(size_t initialCount)
{
MMPointArrayRef pointArray = calloc(1, sizeof(MMPointArray));
if (initialCount == 0) initialCount = 1;
pointArray->_allocedCount = initialCount;
pointArray->array = malloc(pointArray->_allocedCount * sizeof(MMPoint));
if (pointArray->array == NULL) return NULL;
return pointArray;
}
void destroyMMPointArray(MMPointArrayRef pointArray)
{
if (pointArray->array != NULL) {
free(pointArray->array);
pointArray->array = NULL;
}
free(pointArray);
}
void MMPointArrayAppendPoint(MMPointArrayRef pointArray, MMPoint point)
{
const size_t newCount = ++(pointArray->count);
if (pointArray->_allocedCount < newCount) {
do {
/* Double size each time to avoid calls to realloc(). */
pointArray->_allocedCount <<= 1;
} while (pointArray->_allocedCount < newCount);
pointArray->array = realloc(pointArray->array,
sizeof(point) *
pointArray->_allocedCount);
}
pointArray->array[pointArray->count - 1] = point;
}
================================================
FILE: pkg/internal/robotgo/base/UTHashTable.h
================================================
#pragma once
#ifndef UTHASHTABLE_H
#define UTHASHTABLE_H
#include <stddef.h>
#include "uthash.h"
/* All node structs must begin with this (note that there is NO semicolon). */
#define UTHashNode_HEAD UT_hash_handle hh;
/* This file contains convenience macros and a standard struct for working with
* uthash hash tables.
*
* The main purpose of this is for convenience of creating/freeing nodes. */
struct _UTHashTable {
void *uttable; /* The uthash table -- must start out as NULL. */
void *nodes; /* Contiguous array of nodes. */
size_t allocedNodeCount; /* Node count currently allocated for. */
size_t nodeCount; /* Current node count. */
size_t nodeSize; /* Size of each node. */
};
typedef struct _UTHashTable UTHashTable;
/* Initiates a hash table to the default values. |table| should point to an
* already allocated UTHashTable struct.
*
* If the |initialCount| argument in initHashTable is given, |nodes| is
* allocated immediately to the maximum size and new nodes are simply slices of
* that array. This can save calls to malloc if many nodes are to be added, and
* the a reasonable maximum number is known ahead of time.
*
* If the node count goes over this maximum, or if |initialCount| is 0, the
* array is dynamically reallocated to fit the size.
*/
void initHashTable(UTHashTable *table, size_t initialCount, size_t nodeSize);
/* Frees memory occupied by a UTHashTable's members.
*
* Note that this does NOT free memory for the UTHashTable pointed to by
* |table| itself; if that was allocated on the heap, you must free() it
* yourself after calling this. */
void destroyHashTable(UTHashTable *table);
/* Returns memory allocated for a new node. Responsibility for freeing this is
* up to the destroyHashTable() macro; this should NOT be freed by the caller.
*
* This is intended to be used with a HASH_ADD() macro, e.g.:
* {%
* struct myNode *uttable = utHashTable->uttable;
* struct myNode *node = getNewNode(utHashTable);
* node->key = 42;
* node->value = someValue;
* HASH_ADD_INT(uttable, key, node);
* utHashTable->uttable = uttable;
* %}
*
* Or, use the UTHASHTABLE_ADD_INT or UTHASHTABLE_ADD_STR macros
* for convenience (they are exactly equivalent):
* {%
* struct myNode *node = getNewNode(utHashTable);
* node->key = 42;
* node->value = someValue;
* UTHASHTABLE_ADD_INT(utHashTable, key, node, struct myNode);
* %}
*/
void *getNewNode(UTHashTable *table);
#define UTHASHTABLE_ADD_INT(tablePtr, keyName, node, nodeType) \
do { \
nodeType *uttable = (tablePtr)->uttable; \
HASH_ADD_INT(uttable, keyName, node); \
(tablePtr)->uttable = uttable; \
} while (0)
#define UTHASHTABLE_ADD_STR(tablePtr, keyName, node, nodeType) \
do { \
nodeType *uttable = (tablePtr)->uttable; \
HASH_ADD_STR(uttable, keyName, node); \
(tablePtr)->uttable = uttable; \
} while (0)
#endif /* MMHASHTABLE_H */
================================================
FILE: pkg/internal/robotgo/base/UTHashTable_c.h
================================================
#include "UTHashTable.h"
#include <stdlib.h>
#include <assert.h>
/* Base struct class (all nodes must contain at least the elements in
* this struct). */
struct _UTHashNode {
UTHashNode_HEAD
};
typedef struct _UTHashNode UTHashNode;
void initHashTable(UTHashTable *table, size_t initialCount, size_t nodeSize)
{
assert(table != NULL);
assert(nodeSize >= sizeof(UTHashNode));
table->uttable = NULL; /* Must be set to NULL for uthash. */
table->allocedNodeCount = (initialCount == 0) ? 1 : initialCount;
table->nodeCount = 0;
table->nodeSize = nodeSize;
table->nodes = calloc(table->nodeSize, nodeSize * table->allocedNodeCount);
}
void destroyHashTable(UTHashTable *table)
{
UTHashNode *uttable = table->uttable;
UTHashNode *node;
/* Let uthash do its magic. */
while (uttable != NULL) {
node = uttable; /* Grab pointer to first item. */
HASH_DEL(uttable, node); /* Delete it (table advances to next). */
}
/* Only giant malloc'd block containing each node must be freed. */
if (table->nodes != NULL) free(table->nodes);
table->uttable = table->nodes = NULL;
}
void *getNewNode(UTHashTable *table)
{
/* Increment node count, resizing table if necessary. */
const size_t newNodeCount = ++(table->nodeCount);
if (table->allocedNodeCount < newNodeCount) {
do {
/* Double size each time to avoid calls to realloc(). */
table->allocedNodeCount <<= 1;
} while (table->allocedNodeCount < newNodeCount);
table->nodes = realloc(table->nodes, table->nodeSize *
table->allocedNodeCount);
}
return (char *)table->nodes + (table->nodeSize * (table->nodeCount - 1));
}
================================================
FILE: pkg/internal/robotgo/base/base64.c
================================================
#include "base64.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
/* Encoding table as described in RFC1113. */
const static uint8_t b64_encode_table[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz0123456789+/";
/* Decoding table. */
const static int8_t b64_decode_table[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00-0F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10-1F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 20-2F */
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 30-3F */
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 40-4F */
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 50-5F */
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 60-6F */
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 70-7F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80-8F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90-9F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A0-AF */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* B0-BF */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* C0-CF */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* D0-DF */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* E0-EF */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* F0-FF */
};
uint8_t *base64decode(const uint8_t *src, const size_t buflen, size_t *retlen){
int8_t digit, lastdigit;
size_t i, j;
uint8_t *decoded;
const size_t maxlen = ((buflen + 3) / 4) * 3;
/* Sanity check */
assert(src != NULL);
digit = lastdigit = j = 0;
decoded = malloc(maxlen + 1);
if (decoded == NULL) return NULL;
for (i = 0; i < buflen; ++i) {
if ((digit = b64_decode_table[src[i]]) != -1) {
/* Decode block */
switch (i % 4) {
case 1:
decoded[j++] = ((lastdigit << 2) | ((digit & 0x30) >> 4));
break;
case 2:
decoded[j++] = (((lastdigit & 0xF) << 4) | ((digit & 0x3C) >> 2));
break;
case 3:
decoded[j++] = (((lastdigit & 0x03) << 6) | digit);
break;
}
lastdigit = digit;
}
}
if (retlen != NULL) *retlen = j;
decoded[j] = '\0';
return decoded; /* Must be free()'d by caller */
}
uint8_t *base64encode(const uint8_t *src, const size_t buflen, size_t *retlen){
size_t i, j;
const size_t maxlen = (((buflen + 3) & ~3)) * 4;
uint8_t *encoded = malloc(maxlen + 1);
if (encoded == NULL) return NULL;
/* Sanity check */
assert(src != NULL);
assert(buflen > 0);
j = 0;
for (i = 0; i < buflen + 1; ++i) {
/* Encode block */
switch (i % 3) {
case 0:
encoded[j++] = b64_encode_table[src[i] >> 2];
encoded[j++] = b64_encode_table[((src[i] & 0x03) << 4) |
((src[i + 1] & 0xF0) >> 4)];
break;
case 1:
encoded[j++] = b64_encode_table[((src[i] & 0x0F) << 2) |
((src[i + 1] & 0xC0) >> 6)];
break;
case 2:
encoded[j++] = b64_encode_table[(src[i] & 0x3F)];
break;
}
}
/* Add padding if necessary */
if ((j % 4) != 0) {
const size_t with_padding = ((j + 3) & ~3); /* Align to 4 bytes */
do {
encoded[j++] = '=';
} while (j < with_padding);
}
assert(j <= maxlen);
if (retlen != NULL) *retlen = j;
encoded[j] = '\0';
return encoded; /* Must be free()'d by caller */
}
================================================
FILE: pkg/internal/robotgo/base/base64.h
================================================
#pragma once
#ifndef BASE64_H
#define BASE64_H
#include <stddef.h>
#if defined(_MSC_VER)
#include "ms_stdint.h"
#else
#include <stdint.h>
#endif
/* Decode a base64 encoded string discarding line breaks and noise.
*
* Returns a new string to be free()'d by caller, or NULL on error.
* Returned string is guaranteed to be NUL-terminated.
*
* If |retlen| is not NULL, it is set to the length of the returned string
* (minus the NUL-terminator) on successful return. */
uint8_t *base64decode(const uint8_t *buf, const size_t buflen, size_t *retlen);
/* Encode a base64 encoded string without line breaks or noise.
*
* Returns a new string to be free()'d by caller, or NULL on error.
* Returned string is guaranteed to be NUL-terminated with the correct padding.
*
* If |retlen| is not NULL, it is set to the length of the returned string
* (minus the NUL-terminator) on successful return. */
uint8_t *base64encode(const uint8_t *buf, const size_t buflen, size_t *retlen);
#endif /* BASE64_H */
================================================
FILE: pkg/internal/robotgo/base/base64_c.h
================================================
#include "base64.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
/* Encoding table as described in RFC1113. */
const static uint8_t b64_encode_table[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz0123456789+/";
/* Decoding table. */
const static int8_t b64_decode_table[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00-0F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10-1F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 20-2F */
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 30-3F */
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 40-4F */
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 50-5F */
-1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 60-6F */
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 70-7F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80-8F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90-9F */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A0-AF */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* B0-BF */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* C0-CF */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* D0-DF */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* E0-EF */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* F0-FF */
};
uint8_t *base64decode(const uint8_t *src, const size_t buflen, size_t *retlen)
{
int8_t digit, lastdigit;
size_t i, j;
uint8_t *decoded;
const size_t maxlen = ((buflen + 3) / 4) * 3;
/* Sanity check */
assert(src != NULL);
digit = lastdigit = j = 0;
decoded = malloc(maxlen + 1);
if (decoded == NULL) return NULL;
for (i = 0; i < buflen; ++i) {
if ((digit = b64_decode_table[src[i]]) != -1) {
/* Decode block */
switch (i % 4) {
case 1:
decoded[j++] = ((lastdigit << 2) | ((digit & 0x30) >> 4));
break;
case 2:
decoded[j++] = (((lastdigit & 0xF) << 4) | ((digit & 0x3C) >> 2));
break;
case 3:
decoded[j++] = (((lastdigit & 0x03) << 6) | digit);
break;
}
lastdigit = digit;
}
}
if (retlen != NULL) *retlen = j;
decoded[j] = '\0';
return decoded; /* Must be free()'d by caller */
}
uint8_t *base64encode(const uint8_t *src, const size_t buflen, size_t *retlen)
{
size_t i, j;
const size_t maxlen = (((buflen + 3) & ~3)) * 4;
uint8_t *encoded = malloc(maxlen + 1);
if (encoded == NULL) return NULL;
/* Sanity check */
assert(src != NULL);
assert(buflen > 0);
j = 0;
for (i = 0; i < buflen + 1; ++i) {
/* Encode block */
switch (i % 3) {
case 0:
encoded[j++] = b64_encode_table[src[i] >> 2];
encoded[j++] = b64_encode_table[((src[i] & 0x03) << 4) |
((src[i + 1] & 0xF0) >> 4)];
break;
case 1:
encoded[j++] = b64_encode_table[((src[i] & 0x0F) << 2) |
((src[i + 1] & 0xC0) >> 6)];
break;
case 2:
encoded[j++] = b64_encode_table[(src[i] & 0x3F)];
break;
}
}
/* Add padding if necessary */
if ((j % 4) != 0) {
const size_t with_padding = ((j + 3) & ~3); /* Align to 4 bytes */
do {
encoded[j++] = '=';
} while (j < with_padding);
}
assert(j <= maxlen);
if (retlen != NULL) *retlen = j;
encoded[j] = '\0';
return encoded; /* Must be free()'d by caller */
}
================================================
FILE: pkg/internal/robotgo/base/bmp_io.h
================================================
#pragma once
#ifndef BMP_IO_H
#define BMP_IO_H
#include "MMBitmap.h"
#include "file_io.h"
enum _BMPReadError {
kBMPGenericError = 0,
kBMPAccessError,
kBMPInvalidKeyError,
kBMPUnsupportedHeaderError,
kBMPInvalidColorPanesError,
kBMPUnsupportedColorDepthError,
kBMPUnsupportedCompressionError,
kBMPInvalidPixelDataError
};
typedef MMIOError MMBMPReadError;
/* Returns description of given MMBMPReadError.
* Returned string is constant and hence should not be freed. */
const char *MMBMPReadErrorString(MMIOError error);
/* Attempts to read bitmap file at path; returns new MMBitmap on success, or
* NULL on error. If |error| is non-NULL, it will be set to the error code
* on return.
*
* Currently supports:
* - Uncompressed Windows v3/v4/v5 24-bit or 32-bit BMP.
* - OS/2 v1 or v2 24-bit BMP.
* - Does NOT yet support: 1-bit, 4-bit, 8-bit, 16-bit, compressed bitmaps,
* or PNGs/JPEGs disguised as BMPs (and returns NULL if those are given).
*
* Responsibility for destroy()'ing returned MMBitmap is left up to caller. */
MMBitmapRef newMMBitmapFromBMP(const char *path, MMBMPReadError *error);
/* Returns a buffer containing the raw BMP file data in Windows v3 BMP format,
* ready to be saved to a file. If |len| is not NULL, it will be set to the
* number of bytes allocated in the returned buffer.
*
* Responsibility for free()'ing data is left up to the caller. */
uint8_t *createBitmapData(MMBitmapRef bitmap, size_t *len);
/* Saves bitmap to file in Windows v3 BMP format.
* Returns 0 on success, -1 on error. */
int saveMMBitmapAsBMP(MMBitmapRef bitmap, const char *path);
/* Swaps bitmap from Quadrant 1 to Quadran III format, or vice versa
* (upside-down Cartesian/PostScript/GL <-> right side up QD/CG raster format).
*/
void flipBitmapData(void *data, size_t width, size_t height, size_t bytewidth);
#endif /* BMP_IO_H */
================================================
FILE: pkg/internal/robotgo/base/bmp_io_c.h
================================================
#include "bmp_io.h"
#include "os.h"
#include "endian.h"
#include <stdio.h> /* fopen() */
#include <string.h> /* memcpy() */
#if defined(_MSC_VER)
#include "ms_stdbool.h"
#include "ms_stdint.h"
#else
#include <stdbool.h>
#include <stdint.h>
#endif
#pragma pack(push, 1) /* The following structs should be continguous, so we can
* copy them in one read. */
/*
* Standard, initial BMP Header
*/
struct BITMAP_FILE_HEADER {
uint16_t magic; /* First two byes of the file; should be 0x4D42. */
uint32_t fileSize; /* Size of the BMP file in bytes (unreliable). */
uint32_t reserved; /* Application-specific. */
uint32_t imageOffset; /* Offset to bitmap data. */
};
#define BMP_MAGIC 0x4D42 /* The starting key that marks the file as a BMP. */
enum _BMP_COMPRESSION {
kBMP_RGB = 0, /* No compression. */
kBMP_RLE8 = 1, /* Can only be used with 8-bit bitmaps. */
kBMP_RLE4 = 2, /* Can only be used with 4-bit bitmaps. */
kBMP_BITFIELDS = 3, /* Can only be used with 16/32-bit bitmaps. */
kBMP_JPEG = 4, /* Bitmap contains a JPEG image. */
kBMP_PNG = 5 /* Bitmap contains a PNG image. */
};
typedef uint32_t BMP_COMPRESSION;
/*
* Windows 3 Header
*/
struct BITMAP_INFO_HEADER {
uint32_t headerSize; /* The size of this header (40 bytes). */
int32_t width; /* The bitmap width in pixels. */
int32_t height; /* The bitmap height in pixels. */
/* (A negative value denotes that the image
* is flipped.) */
uint16_t colorPlanes; /* The number of color planes; must be 1. */
uint16_t bitsPerPixel; /* The color depth of the image (1, 4, 8, 16,
* 24, or 32). */
BMP_COMPRESSION compression; /* The compression method being used. */
uint32_t imageSize; /* Size of the bitmap in bytes (unreliable).*/
int32_t xRes; /* The horizontal resolution (unreliable). */
int32_t yRes; /* The vertical resolution (unreliable). */
uint32_t colorsUsed; /* The number of colors in the color table,
* or 0 to default to 2^n. */
uint32_t colorsImportant; /* Colors important for displaying bitmap,
* or 0 when every color is equally important;
* ignored. */
};
/*
* OS/2 v1 Header
*/
struct BITMAP_CORE_HEADER {
uint32_t headerSize; /* The size of this header (12 bytes). */
uint16_t width; /* The bitmap width in pixels. */
uint16_t height; /* The bitmap height in pixels. */
uint16_t colorPlanes; /* The number of color planes; must be 1. */
uint16_t bitsPerPixel; /* Color depth of the image (1, 4, 8, or 24). */
};
#pragma pack(pop) /* Let the compiler do what it wants now. */
/* BMP files are always saved in little endian format (x86), so we need to
* convert them if we're not on a little endian machine (e.g., ARM & ppc). */
#if __BYTE_ORDER == __BIG_ENDIAN
/* Converts bitmap file header from to and from little endian, if and only if
* host is big endian. */
static void convertBitmapFileHeader(struct BITMAP_FILE_HEADER *header)
{
header->magic = swapLittleAndHost16(header->magic);
swapLittleAndHost32(header->fileSize);
swapLittleAndHost32(header->reserved);
swapLittleAndHost32(header->imageOffset);
}
/* Converts bitmap info header from to and from little endian, if and only if
* host is big endian. */
static void convertBitmapInfoHeader(struct BITMAP_INFO_HEADER *header)
{
header->headerSize = swapLittleAndHost32(header->headerSize);
header->width = swapLittleAndHost32(header->width);
header->height = swapLittleAndHost32(header->height);
header->colorPlanes = swapLittleAndHost16(header->colorPlanes);
header->bitsPerPixel = swapLittleAndHost16(header->bitsPerPixel);
header->compression = swapLittleAndHost32(header->compression);
header->imageSize = swapLittleAndHost32(header->imageSize);
header->xRes = swapLittleAndHost32(header->xRes);
header->yRes = swapLittleAndHost32(header->yRes);
header->colorsUsed = swapLittleAndHost32(header->col
gitextract_q6gejt6e/
├── .devcontainer/
│ ├── Containerfile
│ └── devcontainer.json
├── .github/
│ └── workflows/
│ ├── pr-workflow.yaml
│ └── tag-workflow.yaml
├── .gitignore
├── .golangci.errcheck.ignore
├── .golangci.yaml
├── .travis.yml
├── LICENSE
├── Makefile
├── README.md
├── go.mod
├── go.sum
├── main.go
├── pkg/
│ ├── domain.go
│ ├── driver.go
│ ├── evdevcodes.go
│ ├── evdeviterator.go
│ ├── evdeviterator_test.go
│ ├── gen.go
│ ├── internal/
│ │ ├── gen.go
│ │ ├── gencodes/
│ │ │ └── main.go
│ │ └── robotgo/
│ │ ├── base/
│ │ │ ├── LICENSE
│ │ │ ├── MMBitmap.h
│ │ │ ├── MMBitmap_c.h
│ │ │ ├── MMPointArray.h
│ │ │ ├── MMPointArray_c.h
│ │ │ ├── UTHashTable.h
│ │ │ ├── UTHashTable_c.h
│ │ │ ├── base64.c
│ │ │ ├── base64.h
│ │ │ ├── base64_c.h
│ │ │ ├── bmp_io.h
│ │ │ ├── bmp_io_c.h
│ │ │ ├── color_find.h
│ │ │ ├── color_find_c.h
│ │ │ ├── deadbeef_rand.h
│ │ │ ├── deadbeef_rand_c.h
│ │ │ ├── endian.h
│ │ │ ├── file_io.h
│ │ │ ├── file_io_c.h
│ │ │ ├── inline_keywords.h
│ │ │ ├── io.c
│ │ │ ├── microsleep.h
│ │ │ ├── ms_stdbool.h
│ │ │ ├── ms_stdint.h
│ │ │ ├── os.h
│ │ │ ├── pasteboard.h
│ │ │ ├── pasteboard_c.h
│ │ │ ├── png_io.h
│ │ │ ├── png_io_c.h
│ │ │ ├── rgb.h
│ │ │ ├── snprintf.h
│ │ │ ├── snprintf_c.h
│ │ │ ├── str_io.h
│ │ │ ├── str_io_c.h
│ │ │ ├── types.h
│ │ │ ├── uthash.h
│ │ │ ├── xdisplay.h
│ │ │ ├── xdisplay_c.h
│ │ │ ├── zlib_util.h
│ │ │ └── zlib_util_c.h
│ │ ├── mouse/
│ │ │ ├── goMouse.h
│ │ │ ├── mouse.h
│ │ │ └── mouse_c.h
│ │ ├── robotgo.go
│ │ ├── screen/
│ │ │ ├── goScreen.h
│ │ │ ├── screen.h
│ │ │ └── screen_c.h
│ │ └── window/
│ │ ├── arr.h
│ │ ├── goWindow.h
│ │ ├── process.h
│ │ ├── pub.h
│ │ ├── win32.h
│ │ ├── win_sys.h
│ │ └── window.h
│ ├── mock_driver_test.go
│ ├── mock_evdeviterator_test.go
│ ├── mock_positionscaler_test.go
│ ├── mock_readcloser_test.go
│ ├── mock_statemachine_test.go
│ ├── positionscaler.go
│ ├── positionscaler_test.go
│ ├── runtime.go
│ ├── runtime_test.go
│ ├── statemachine.go
│ └── statemachine_test.go
├── technical-documentation/
│ ├── README.md
│ └── static-assets/
│ └── diagrams.puml
└── tools/
├── go.mod
├── go.sum
└── tools.go
SYMBOL INDEX (1118 symbols across 57 files)
FILE: main.go
function main (line 32) | func main() {
FILE: pkg/domain.go
type EvdevEvent (line 22) | type EvdevEvent struct
type EvdevIterator (line 38) | type EvdevIterator interface
constant ChangeTypeMove (line 54) | ChangeTypeMove = "MOVE"
constant ChangeTypeDrag (line 56) | ChangeTypeDrag = "DRAG"
constant ChangeTypeClick (line 58) | ChangeTypeClick = "CLICK"
constant ChangeTypeUnclick (line 60) | ChangeTypeUnclick = "UNCLICK"
type StateChangeMove (line 64) | type StateChangeMove struct
method Type (line 70) | func (*StateChangeMove) Type() string {
type StateChangeDrag (line 75) | type StateChangeDrag struct
method Type (line 81) | func (*StateChangeDrag) Type() string {
type StateChangeClick (line 86) | type StateChangeClick struct
method Type (line 89) | func (*StateChangeClick) Type() string {
type StateChangeUnclick (line 94) | type StateChangeUnclick struct
method Type (line 97) | func (*StateChangeUnclick) Type() string {
type StateChange (line 103) | type StateChange interface
type StateMachine (line 109) | type StateMachine interface
type PositionScaler (line 125) | type PositionScaler interface
type Driver (line 130) | type Driver interface
FILE: pkg/driver.go
type RobotgoDriver (line 20) | type RobotgoDriver struct
method GetSize (line 23) | func (*RobotgoDriver) GetSize() (int, int, error) {
method Click (line 29) | func (*RobotgoDriver) Click() error {
method Unclick (line 35) | func (*RobotgoDriver) Unclick() error {
method MoveMouse (line 41) | func (*RobotgoDriver) MoveMouse(x int, y int) error {
method DragMouse (line 49) | func (*RobotgoDriver) DragMouse(x int, y int) error {
FILE: pkg/evdevcodes.go
constant EV_VERSION (line 9) | EV_VERSION = 0x010001
constant ID_BUS (line 10) | ID_BUS = 0
constant ID_VENDOR (line 11) | ID_VENDOR = 1
constant ID_PRODUCT (line 12) | ID_PRODUCT = 2
constant ID_VERSION (line 13) | ID_VERSION = 3
constant BUS_PCI (line 14) | BUS_PCI = 0x01
constant BUS_ISAPNP (line 15) | BUS_ISAPNP = 0x02
constant BUS_USB (line 16) | BUS_USB = 0x03
constant BUS_HIL (line 17) | BUS_HIL = 0x04
constant BUS_BLUETOOTH (line 18) | BUS_BLUETOOTH = 0x05
constant BUS_VIRTUAL (line 19) | BUS_VIRTUAL = 0x06
constant BUS_ISA (line 20) | BUS_ISA = 0x10
constant BUS_I8042 (line 21) | BUS_I8042 = 0x11
constant BUS_XTKBD (line 22) | BUS_XTKBD = 0x12
constant BUS_RS232 (line 23) | BUS_RS232 = 0x13
constant BUS_GAMEPORT (line 24) | BUS_GAMEPORT = 0x14
constant BUS_PARPORT (line 25) | BUS_PARPORT = 0x15
constant BUS_AMIGA (line 26) | BUS_AMIGA = 0x16
constant BUS_ADB (line 27) | BUS_ADB = 0x17
constant BUS_I2C (line 28) | BUS_I2C = 0x18
constant BUS_HOST (line 29) | BUS_HOST = 0x19
constant BUS_GSC (line 30) | BUS_GSC = 0x1A
constant BUS_ATARI (line 31) | BUS_ATARI = 0x1B
constant BUS_SPI (line 32) | BUS_SPI = 0x1C
constant BUS_RMI (line 33) | BUS_RMI = 0x1D
constant BUS_CEC (line 34) | BUS_CEC = 0x1E
constant BUS_INTEL_ISHTP (line 35) | BUS_INTEL_ISHTP = 0x1F
constant FF_STATUS_STOPPED (line 36) | FF_STATUS_STOPPED = 0x00
constant FF_STATUS_PLAYING (line 37) | FF_STATUS_PLAYING = 0x01
constant FF_STATUS_MAX (line 38) | FF_STATUS_MAX = 0x01
constant FF_RUMBLE (line 39) | FF_RUMBLE = 0x50
constant FF_PERIODIC (line 40) | FF_PERIODIC = 0x51
constant FF_CONSTANT (line 41) | FF_CONSTANT = 0x52
constant FF_SPRING (line 42) | FF_SPRING = 0x53
constant FF_FRICTION (line 43) | FF_FRICTION = 0x54
constant FF_DAMPER (line 44) | FF_DAMPER = 0x55
constant FF_INERTIA (line 45) | FF_INERTIA = 0x56
constant FF_RAMP (line 46) | FF_RAMP = 0x57
constant FF_EFFECT_MIN (line 47) | FF_EFFECT_MIN = FF_RUMBLE
constant FF_EFFECT_MAX (line 48) | FF_EFFECT_MAX = FF_RAMP
constant FF_SQUARE (line 49) | FF_SQUARE = 0x58
constant FF_TRIANGLE (line 50) | FF_TRIANGLE = 0x59
constant FF_SINE (line 51) | FF_SINE = 0x5a
constant FF_SAW_UP (line 52) | FF_SAW_UP = 0x5b
constant FF_SAW_DOWN (line 53) | FF_SAW_DOWN = 0x5c
constant FF_CUSTOM (line 54) | FF_CUSTOM = 0x5d
constant FF_WAVEFORM_MIN (line 55) | FF_WAVEFORM_MIN = FF_SQUARE
constant FF_WAVEFORM_MAX (line 56) | FF_WAVEFORM_MAX = FF_CUSTOM
constant FF_GAIN (line 57) | FF_GAIN = 0x60
constant FF_AUTOCENTER (line 58) | FF_AUTOCENTER = 0x61
constant FF_MAX_EFFECTS (line 59) | FF_MAX_EFFECTS = FF_GAIN
constant FF_MAX (line 60) | FF_MAX = 0x7f
constant EV_SYN (line 61) | EV_SYN = 0x00
constant EV_KEY (line 62) | EV_KEY = 0x01
constant EV_REL (line 63) | EV_REL = 0x02
constant EV_ABS (line 64) | EV_ABS = 0x03
constant EV_MSC (line 65) | EV_MSC = 0x04
constant EV_SW (line 66) | EV_SW = 0x05
constant EV_LED (line 67) | EV_LED = 0x11
constant EV_SND (line 68) | EV_SND = 0x12
constant EV_REP (line 69) | EV_REP = 0x14
constant EV_FF (line 70) | EV_FF = 0x15
constant EV_PWR (line 71) | EV_PWR = 0x16
constant EV_FF_STATUS (line 72) | EV_FF_STATUS = 0x17
constant EV_MAX (line 73) | EV_MAX = 0x1f
constant SYN_REPORT (line 74) | SYN_REPORT = 0
constant SYN_CONFIG (line 75) | SYN_CONFIG = 1
constant SYN_MT_REPORT (line 76) | SYN_MT_REPORT = 2
constant SYN_DROPPED (line 77) | SYN_DROPPED = 3
constant SYN_MAX (line 78) | SYN_MAX = 0xf
constant KEY_RESERVED (line 79) | KEY_RESERVED = 0
constant KEY_ESC (line 80) | KEY_ESC = 1
constant KEY_1 (line 81) | KEY_1 = 2
constant KEY_2 (line 82) | KEY_2 = 3
constant KEY_3 (line 83) | KEY_3 = 4
constant KEY_4 (line 84) | KEY_4 = 5
constant KEY_5 (line 85) | KEY_5 = 6
constant KEY_6 (line 86) | KEY_6 = 7
constant KEY_7 (line 87) | KEY_7 = 8
constant KEY_8 (line 88) | KEY_8 = 9
constant KEY_9 (line 89) | KEY_9 = 10
constant KEY_0 (line 90) | KEY_0 = 11
constant KEY_MINUS (line 91) | KEY_MINUS = 12
constant KEY_EQUAL (line 92) | KEY_EQUAL = 13
constant KEY_BACKSPACE (line 93) | KEY_BACKSPACE = 14
constant KEY_TAB (line 94) | KEY_TAB = 15
constant KEY_Q (line 95) | KEY_Q = 16
constant KEY_W (line 96) | KEY_W = 17
constant KEY_E (line 97) | KEY_E = 18
constant KEY_R (line 98) | KEY_R = 19
constant KEY_T (line 99) | KEY_T = 20
constant KEY_Y (line 100) | KEY_Y = 21
constant KEY_U (line 101) | KEY_U = 22
constant KEY_I (line 102) | KEY_I = 23
constant KEY_O (line 103) | KEY_O = 24
constant KEY_P (line 104) | KEY_P = 25
constant KEY_LEFTBRACE (line 105) | KEY_LEFTBRACE = 26
constant KEY_RIGHTBRACE (line 106) | KEY_RIGHTBRACE = 27
constant KEY_ENTER (line 107) | KEY_ENTER = 28
constant KEY_LEFTCTRL (line 108) | KEY_LEFTCTRL = 29
constant KEY_A (line 109) | KEY_A = 30
constant KEY_S (line 110) | KEY_S = 31
constant KEY_D (line 111) | KEY_D = 32
constant KEY_F (line 112) | KEY_F = 33
constant KEY_G (line 113) | KEY_G = 34
constant KEY_H (line 114) | KEY_H = 35
constant KEY_J (line 115) | KEY_J = 36
constant KEY_K (line 116) | KEY_K = 37
constant KEY_L (line 117) | KEY_L = 38
constant KEY_SEMICOLON (line 118) | KEY_SEMICOLON = 39
constant KEY_APOSTROPHE (line 119) | KEY_APOSTROPHE = 40
constant KEY_GRAVE (line 120) | KEY_GRAVE = 41
constant KEY_LEFTSHIFT (line 121) | KEY_LEFTSHIFT = 42
constant KEY_BACKSLASH (line 122) | KEY_BACKSLASH = 43
constant KEY_Z (line 123) | KEY_Z = 44
constant KEY_X (line 124) | KEY_X = 45
constant KEY_C (line 125) | KEY_C = 46
constant KEY_V (line 126) | KEY_V = 47
constant KEY_B (line 127) | KEY_B = 48
constant KEY_N (line 128) | KEY_N = 49
constant KEY_M (line 129) | KEY_M = 50
constant KEY_COMMA (line 130) | KEY_COMMA = 51
constant KEY_DOT (line 131) | KEY_DOT = 52
constant KEY_SLASH (line 132) | KEY_SLASH = 53
constant KEY_RIGHTSHIFT (line 133) | KEY_RIGHTSHIFT = 54
constant KEY_KPASTERISK (line 134) | KEY_KPASTERISK = 55
constant KEY_LEFTALT (line 135) | KEY_LEFTALT = 56
constant KEY_SPACE (line 136) | KEY_SPACE = 57
constant KEY_CAPSLOCK (line 137) | KEY_CAPSLOCK = 58
constant KEY_F1 (line 138) | KEY_F1 = 59
constant KEY_F2 (line 139) | KEY_F2 = 60
constant KEY_F3 (line 140) | KEY_F3 = 61
constant KEY_F4 (line 141) | KEY_F4 = 62
constant KEY_F5 (line 142) | KEY_F5 = 63
constant KEY_F6 (line 143) | KEY_F6 = 64
constant KEY_F7 (line 144) | KEY_F7 = 65
constant KEY_F8 (line 145) | KEY_F8 = 66
constant KEY_F9 (line 146) | KEY_F9 = 67
constant KEY_F10 (line 147) | KEY_F10 = 68
constant KEY_NUMLOCK (line 148) | KEY_NUMLOCK = 69
constant KEY_SCROLLLOCK (line 149) | KEY_SCROLLLOCK = 70
constant KEY_KP7 (line 150) | KEY_KP7 = 71
constant KEY_KP8 (line 151) | KEY_KP8 = 72
constant KEY_KP9 (line 152) | KEY_KP9 = 73
constant KEY_KPMINUS (line 153) | KEY_KPMINUS = 74
constant KEY_KP4 (line 154) | KEY_KP4 = 75
constant KEY_KP5 (line 155) | KEY_KP5 = 76
constant KEY_KP6 (line 156) | KEY_KP6 = 77
constant KEY_KPPLUS (line 157) | KEY_KPPLUS = 78
constant KEY_KP1 (line 158) | KEY_KP1 = 79
constant KEY_KP2 (line 159) | KEY_KP2 = 80
constant KEY_KP3 (line 160) | KEY_KP3 = 81
constant KEY_KP0 (line 161) | KEY_KP0 = 82
constant KEY_KPDOT (line 162) | KEY_KPDOT = 83
constant KEY_ZENKAKUHANKAKU (line 163) | KEY_ZENKAKUHANKAKU = 85
constant KEY_102ND (line 164) | KEY_102ND = 86
constant KEY_F11 (line 165) | KEY_F11 = 87
constant KEY_F12 (line 166) | KEY_F12 = 88
constant KEY_RO (line 167) | KEY_RO = 89
constant KEY_KATAKANA (line 168) | KEY_KATAKANA = 90
constant KEY_HIRAGANA (line 169) | KEY_HIRAGANA = 91
constant KEY_HENKAN (line 170) | KEY_HENKAN = 92
constant KEY_KATAKANAHIRAGANA (line 171) | KEY_KATAKANAHIRAGANA = 93
constant KEY_MUHENKAN (line 172) | KEY_MUHENKAN = 94
constant KEY_KPJPCOMMA (line 173) | KEY_KPJPCOMMA = 95
constant KEY_KPENTER (line 174) | KEY_KPENTER = 96
constant KEY_RIGHTCTRL (line 175) | KEY_RIGHTCTRL = 97
constant KEY_KPSLASH (line 176) | KEY_KPSLASH = 98
constant KEY_SYSRQ (line 177) | KEY_SYSRQ = 99
constant KEY_RIGHTALT (line 178) | KEY_RIGHTALT = 100
constant KEY_LINEFEED (line 179) | KEY_LINEFEED = 101
constant KEY_HOME (line 180) | KEY_HOME = 102
constant KEY_UP (line 181) | KEY_UP = 103
constant KEY_PAGEUP (line 182) | KEY_PAGEUP = 104
constant KEY_LEFT (line 183) | KEY_LEFT = 105
constant KEY_RIGHT (line 184) | KEY_RIGHT = 106
constant KEY_END (line 185) | KEY_END = 107
constant KEY_DOWN (line 186) | KEY_DOWN = 108
constant KEY_PAGEDOWN (line 187) | KEY_PAGEDOWN = 109
constant KEY_INSERT (line 188) | KEY_INSERT = 110
constant KEY_DELETE (line 189) | KEY_DELETE = 111
constant KEY_MACRO (line 190) | KEY_MACRO = 112
constant KEY_MUTE (line 191) | KEY_MUTE = 113
constant KEY_VOLUMEDOWN (line 192) | KEY_VOLUMEDOWN = 114
constant KEY_VOLUMEUP (line 193) | KEY_VOLUMEUP = 115
constant KEY_POWER (line 194) | KEY_POWER = 116
constant KEY_KPEQUAL (line 195) | KEY_KPEQUAL = 117
constant KEY_KPPLUSMINUS (line 196) | KEY_KPPLUSMINUS = 118
constant KEY_PAUSE (line 197) | KEY_PAUSE = 119
constant KEY_SCALE (line 198) | KEY_SCALE = 120
constant KEY_KPCOMMA (line 199) | KEY_KPCOMMA = 121
constant KEY_HANGEUL (line 200) | KEY_HANGEUL = 122
constant KEY_HANGUEL (line 201) | KEY_HANGUEL = KEY_HANGEUL
constant KEY_HANJA (line 202) | KEY_HANJA = 123
constant KEY_YEN (line 203) | KEY_YEN = 124
constant KEY_LEFTMETA (line 204) | KEY_LEFTMETA = 125
constant KEY_RIGHTMETA (line 205) | KEY_RIGHTMETA = 126
constant KEY_COMPOSE (line 206) | KEY_COMPOSE = 127
constant KEY_STOP (line 207) | KEY_STOP = 128
constant KEY_AGAIN (line 208) | KEY_AGAIN = 129
constant KEY_PROPS (line 209) | KEY_PROPS = 130
constant KEY_UNDO (line 210) | KEY_UNDO = 131
constant KEY_FRONT (line 211) | KEY_FRONT = 132
constant KEY_COPY (line 212) | KEY_COPY = 133
constant KEY_OPEN (line 213) | KEY_OPEN = 134
constant KEY_PASTE (line 214) | KEY_PASTE = 135
constant KEY_FIND (line 215) | KEY_FIND = 136
constant KEY_CUT (line 216) | KEY_CUT = 137
constant KEY_HELP (line 217) | KEY_HELP = 138
constant KEY_MENU (line 218) | KEY_MENU = 139
constant KEY_CALC (line 219) | KEY_CALC = 140
constant KEY_SETUP (line 220) | KEY_SETUP = 141
constant KEY_SLEEP (line 221) | KEY_SLEEP = 142
constant KEY_WAKEUP (line 222) | KEY_WAKEUP = 143
constant KEY_FILE (line 223) | KEY_FILE = 144
constant KEY_SENDFILE (line 224) | KEY_SENDFILE = 145
constant KEY_DELETEFILE (line 225) | KEY_DELETEFILE = 146
constant KEY_XFER (line 226) | KEY_XFER = 147
constant KEY_PROG1 (line 227) | KEY_PROG1 = 148
constant KEY_PROG2 (line 228) | KEY_PROG2 = 149
constant KEY_WWW (line 229) | KEY_WWW = 150
constant KEY_MSDOS (line 230) | KEY_MSDOS = 151
constant KEY_COFFEE (line 231) | KEY_COFFEE = 152
constant KEY_SCREENLOCK (line 232) | KEY_SCREENLOCK = KEY_COFFEE
constant KEY_ROTATE_DISPLAY (line 233) | KEY_ROTATE_DISPLAY = 153
constant KEY_DIRECTION (line 234) | KEY_DIRECTION = KEY_ROTATE_DISPLAY
constant KEY_CYCLEWINDOWS (line 235) | KEY_CYCLEWINDOWS = 154
constant KEY_MAIL (line 236) | KEY_MAIL = 155
constant KEY_BOOKMARKS (line 237) | KEY_BOOKMARKS = 156
constant KEY_COMPUTER (line 238) | KEY_COMPUTER = 157
constant KEY_BACK (line 239) | KEY_BACK = 158
constant KEY_FORWARD (line 240) | KEY_FORWARD = 159
constant KEY_CLOSECD (line 241) | KEY_CLOSECD = 160
constant KEY_EJECTCD (line 242) | KEY_EJECTCD = 161
constant KEY_EJECTCLOSECD (line 243) | KEY_EJECTCLOSECD = 162
constant KEY_NEXTSONG (line 244) | KEY_NEXTSONG = 163
constant KEY_PLAYPAUSE (line 245) | KEY_PLAYPAUSE = 164
constant KEY_PREVIOUSSONG (line 246) | KEY_PREVIOUSSONG = 165
constant KEY_STOPCD (line 247) | KEY_STOPCD = 166
constant KEY_RECORD (line 248) | KEY_RECORD = 167
constant KEY_REWIND (line 249) | KEY_REWIND = 168
constant KEY_PHONE (line 250) | KEY_PHONE = 169
constant KEY_ISO (line 251) | KEY_ISO = 170
constant KEY_CONFIG (line 252) | KEY_CONFIG = 171
constant KEY_HOMEPAGE (line 253) | KEY_HOMEPAGE = 172
constant KEY_REFRESH (line 254) | KEY_REFRESH = 173
constant KEY_EXIT (line 255) | KEY_EXIT = 174
constant KEY_MOVE (line 256) | KEY_MOVE = 175
constant KEY_EDIT (line 257) | KEY_EDIT = 176
constant KEY_SCROLLUP (line 258) | KEY_SCROLLUP = 177
constant KEY_SCROLLDOWN (line 259) | KEY_SCROLLDOWN = 178
constant KEY_KPLEFTPAREN (line 260) | KEY_KPLEFTPAREN = 179
constant KEY_KPRIGHTPAREN (line 261) | KEY_KPRIGHTPAREN = 180
constant KEY_NEW (line 262) | KEY_NEW = 181
constant KEY_REDO (line 263) | KEY_REDO = 182
constant KEY_F13 (line 264) | KEY_F13 = 183
constant KEY_F14 (line 265) | KEY_F14 = 184
constant KEY_F15 (line 266) | KEY_F15 = 185
constant KEY_F16 (line 267) | KEY_F16 = 186
constant KEY_F17 (line 268) | KEY_F17 = 187
constant KEY_F18 (line 269) | KEY_F18 = 188
constant KEY_F19 (line 270) | KEY_F19 = 189
constant KEY_F20 (line 271) | KEY_F20 = 190
constant KEY_F21 (line 272) | KEY_F21 = 191
constant KEY_F22 (line 273) | KEY_F22 = 192
constant KEY_F23 (line 274) | KEY_F23 = 193
constant KEY_F24 (line 275) | KEY_F24 = 194
constant KEY_PLAYCD (line 276) | KEY_PLAYCD = 200
constant KEY_PAUSECD (line 277) | KEY_PAUSECD = 201
constant KEY_PROG3 (line 278) | KEY_PROG3 = 202
constant KEY_PROG4 (line 279) | KEY_PROG4 = 203
constant KEY_DASHBOARD (line 280) | KEY_DASHBOARD = 204
constant KEY_SUSPEND (line 281) | KEY_SUSPEND = 205
constant KEY_CLOSE (line 282) | KEY_CLOSE = 206
constant KEY_PLAY (line 283) | KEY_PLAY = 207
constant KEY_FASTFORWARD (line 284) | KEY_FASTFORWARD = 208
constant KEY_BASSBOOST (line 285) | KEY_BASSBOOST = 209
constant KEY_PRINT (line 286) | KEY_PRINT = 210
constant KEY_HP (line 287) | KEY_HP = 211
constant KEY_CAMERA (line 288) | KEY_CAMERA = 212
constant KEY_SOUND (line 289) | KEY_SOUND = 213
constant KEY_QUESTION (line 290) | KEY_QUESTION = 214
constant KEY_EMAIL (line 291) | KEY_EMAIL = 215
constant KEY_CHAT (line 292) | KEY_CHAT = 216
constant KEY_SEARCH (line 293) | KEY_SEARCH = 217
constant KEY_CONNECT (line 294) | KEY_CONNECT = 218
constant KEY_FINANCE (line 295) | KEY_FINANCE = 219
constant KEY_SPORT (line 296) | KEY_SPORT = 220
constant KEY_SHOP (line 297) | KEY_SHOP = 221
constant KEY_ALTERASE (line 298) | KEY_ALTERASE = 222
constant KEY_CANCEL (line 299) | KEY_CANCEL = 223
constant KEY_BRIGHTNESSDOWN (line 300) | KEY_BRIGHTNESSDOWN = 224
constant KEY_BRIGHTNESSUP (line 301) | KEY_BRIGHTNESSUP = 225
constant KEY_MEDIA (line 302) | KEY_MEDIA = 226
constant KEY_SWITCHVIDEOMODE (line 303) | KEY_SWITCHVIDEOMODE = 227
constant KEY_KBDILLUMTOGGLE (line 304) | KEY_KBDILLUMTOGGLE = 228
constant KEY_KBDILLUMDOWN (line 305) | KEY_KBDILLUMDOWN = 229
constant KEY_KBDILLUMUP (line 306) | KEY_KBDILLUMUP = 230
constant KEY_SEND (line 307) | KEY_SEND = 231
constant KEY_REPLY (line 308) | KEY_REPLY = 232
constant KEY_FORWARDMAIL (line 309) | KEY_FORWARDMAIL = 233
constant KEY_SAVE (line 310) | KEY_SAVE = 234
constant KEY_DOCUMENTS (line 311) | KEY_DOCUMENTS = 235
constant KEY_BATTERY (line 312) | KEY_BATTERY = 236
constant KEY_BLUETOOTH (line 313) | KEY_BLUETOOTH = 237
constant KEY_WLAN (line 314) | KEY_WLAN = 238
constant KEY_UWB (line 315) | KEY_UWB = 239
constant KEY_UNKNOWN (line 316) | KEY_UNKNOWN = 240
constant KEY_VIDEO_NEXT (line 317) | KEY_VIDEO_NEXT = 241
constant KEY_VIDEO_PREV (line 318) | KEY_VIDEO_PREV = 242
constant KEY_BRIGHTNESS_CYCLE (line 319) | KEY_BRIGHTNESS_CYCLE = 243
constant KEY_BRIGHTNESS_AUTO (line 320) | KEY_BRIGHTNESS_AUTO = 244
constant KEY_BRIGHTNESS_ZERO (line 321) | KEY_BRIGHTNESS_ZERO = KEY_BRIGHTNESS_AUTO
constant KEY_DISPLAY_OFF (line 322) | KEY_DISPLAY_OFF = 245
constant KEY_WWAN (line 323) | KEY_WWAN = 246
constant KEY_WIMAX (line 324) | KEY_WIMAX = KEY_WWAN
constant KEY_RFKILL (line 325) | KEY_RFKILL = 247
constant KEY_MICMUTE (line 326) | KEY_MICMUTE = 248
constant BTN_MISC (line 327) | BTN_MISC = 0x100
constant BTN_0 (line 328) | BTN_0 = 0x100
constant BTN_1 (line 329) | BTN_1 = 0x101
constant BTN_2 (line 330) | BTN_2 = 0x102
constant BTN_3 (line 331) | BTN_3 = 0x103
constant BTN_4 (line 332) | BTN_4 = 0x104
constant BTN_5 (line 333) | BTN_5 = 0x105
constant BTN_6 (line 334) | BTN_6 = 0x106
constant BTN_7 (line 335) | BTN_7 = 0x107
constant BTN_8 (line 336) | BTN_8 = 0x108
constant BTN_9 (line 337) | BTN_9 = 0x109
constant BTN_MOUSE (line 338) | BTN_MOUSE = 0x110
constant BTN_LEFT (line 339) | BTN_LEFT = 0x110
constant BTN_RIGHT (line 340) | BTN_RIGHT = 0x111
constant BTN_MIDDLE (line 341) | BTN_MIDDLE = 0x112
constant BTN_SIDE (line 342) | BTN_SIDE = 0x113
constant BTN_EXTRA (line 343) | BTN_EXTRA = 0x114
constant BTN_FORWARD (line 344) | BTN_FORWARD = 0x115
constant BTN_BACK (line 345) | BTN_BACK = 0x116
constant BTN_TASK (line 346) | BTN_TASK = 0x117
constant BTN_JOYSTICK (line 347) | BTN_JOYSTICK = 0x120
constant BTN_TRIGGER (line 348) | BTN_TRIGGER = 0x120
constant BTN_THUMB (line 349) | BTN_THUMB = 0x121
constant BTN_THUMB2 (line 350) | BTN_THUMB2 = 0x122
constant BTN_TOP (line 351) | BTN_TOP = 0x123
constant BTN_TOP2 (line 352) | BTN_TOP2 = 0x124
constant BTN_PINKIE (line 353) | BTN_PINKIE = 0x125
constant BTN_BASE (line 354) | BTN_BASE = 0x126
constant BTN_BASE2 (line 355) | BTN_BASE2 = 0x127
constant BTN_BASE3 (line 356) | BTN_BASE3 = 0x128
constant BTN_BASE4 (line 357) | BTN_BASE4 = 0x129
constant BTN_BASE5 (line 358) | BTN_BASE5 = 0x12a
constant BTN_BASE6 (line 359) | BTN_BASE6 = 0x12b
constant BTN_DEAD (line 360) | BTN_DEAD = 0x12f
constant BTN_GAMEPAD (line 361) | BTN_GAMEPAD = 0x130
constant BTN_SOUTH (line 362) | BTN_SOUTH = 0x130
constant BTN_A (line 363) | BTN_A = BTN_SOUTH
constant BTN_EAST (line 364) | BTN_EAST = 0x131
constant BTN_B (line 365) | BTN_B = BTN_EAST
constant BTN_C (line 366) | BTN_C = 0x132
constant BTN_NORTH (line 367) | BTN_NORTH = 0x133
constant BTN_X (line 368) | BTN_X = BTN_NORTH
constant BTN_WEST (line 369) | BTN_WEST = 0x134
constant BTN_Y (line 370) | BTN_Y = BTN_WEST
constant BTN_Z (line 371) | BTN_Z = 0x135
constant BTN_TL (line 372) | BTN_TL = 0x136
constant BTN_TR (line 373) | BTN_TR = 0x137
constant BTN_TL2 (line 374) | BTN_TL2 = 0x138
constant BTN_TR2 (line 375) | BTN_TR2 = 0x139
constant BTN_SELECT (line 376) | BTN_SELECT = 0x13a
constant BTN_START (line 377) | BTN_START = 0x13b
constant BTN_MODE (line 378) | BTN_MODE = 0x13c
constant BTN_THUMBL (line 379) | BTN_THUMBL = 0x13d
constant BTN_THUMBR (line 380) | BTN_THUMBR = 0x13e
constant BTN_DIGI (line 381) | BTN_DIGI = 0x140
constant BTN_TOOL_PEN (line 382) | BTN_TOOL_PEN = 0x140
constant BTN_TOOL_RUBBER (line 383) | BTN_TOOL_RUBBER = 0x141
constant BTN_TOOL_BRUSH (line 384) | BTN_TOOL_BRUSH = 0x142
constant BTN_TOOL_PENCIL (line 385) | BTN_TOOL_PENCIL = 0x143
constant BTN_TOOL_AIRBRUSH (line 386) | BTN_TOOL_AIRBRUSH = 0x144
constant BTN_TOOL_FINGER (line 387) | BTN_TOOL_FINGER = 0x145
constant BTN_TOOL_MOUSE (line 388) | BTN_TOOL_MOUSE = 0x146
constant BTN_TOOL_LENS (line 389) | BTN_TOOL_LENS = 0x147
constant BTN_TOOL_QUINTTAP (line 390) | BTN_TOOL_QUINTTAP = 0x148
constant BTN_STYLUS3 (line 391) | BTN_STYLUS3 = 0x149
constant BTN_TOUCH (line 392) | BTN_TOUCH = 0x14a
constant BTN_STYLUS (line 393) | BTN_STYLUS = 0x14b
constant BTN_STYLUS2 (line 394) | BTN_STYLUS2 = 0x14c
constant BTN_TOOL_DOUBLETAP (line 395) | BTN_TOOL_DOUBLETAP = 0x14d
constant BTN_TOOL_TRIPLETAP (line 396) | BTN_TOOL_TRIPLETAP = 0x14e
constant BTN_TOOL_QUADTAP (line 397) | BTN_TOOL_QUADTAP = 0x14f
constant BTN_WHEEL (line 398) | BTN_WHEEL = 0x150
constant BTN_GEAR_DOWN (line 399) | BTN_GEAR_DOWN = 0x150
constant BTN_GEAR_UP (line 400) | BTN_GEAR_UP = 0x151
constant KEY_OK (line 401) | KEY_OK = 0x160
constant KEY_SELECT (line 402) | KEY_SELECT = 0x161
constant KEY_GOTO (line 403) | KEY_GOTO = 0x162
constant KEY_CLEAR (line 404) | KEY_CLEAR = 0x163
constant KEY_POWER2 (line 405) | KEY_POWER2 = 0x164
constant KEY_OPTION (line 406) | KEY_OPTION = 0x165
constant KEY_INFO (line 407) | KEY_INFO = 0x166
constant KEY_TIME (line 408) | KEY_TIME = 0x167
constant KEY_VENDOR (line 409) | KEY_VENDOR = 0x168
constant KEY_ARCHIVE (line 410) | KEY_ARCHIVE = 0x169
constant KEY_PROGRAM (line 411) | KEY_PROGRAM = 0x16a
constant KEY_CHANNEL (line 412) | KEY_CHANNEL = 0x16b
constant KEY_FAVORITES (line 413) | KEY_FAVORITES = 0x16c
constant KEY_EPG (line 414) | KEY_EPG = 0x16d
constant KEY_PVR (line 415) | KEY_PVR = 0x16e
constant KEY_MHP (line 416) | KEY_MHP = 0x16f
constant KEY_LANGUAGE (line 417) | KEY_LANGUAGE = 0x170
constant KEY_TITLE (line 418) | KEY_TITLE = 0x171
constant KEY_SUBTITLE (line 419) | KEY_SUBTITLE = 0x172
constant KEY_ANGLE (line 420) | KEY_ANGLE = 0x173
constant KEY_ZOOM (line 421) | KEY_ZOOM = 0x174
constant KEY_MODE (line 422) | KEY_MODE = 0x175
constant KEY_KEYBOARD (line 423) | KEY_KEYBOARD = 0x176
constant KEY_SCREEN (line 424) | KEY_SCREEN = 0x177
constant KEY_PC (line 425) | KEY_PC = 0x178
constant KEY_TV (line 426) | KEY_TV = 0x179
constant KEY_TV2 (line 427) | KEY_TV2 = 0x17a
constant KEY_VCR (line 428) | KEY_VCR = 0x17b
constant KEY_VCR2 (line 429) | KEY_VCR2 = 0x17c
constant KEY_SAT (line 430) | KEY_SAT = 0x17d
constant KEY_SAT2 (line 431) | KEY_SAT2 = 0x17e
constant KEY_CD (line 432) | KEY_CD = 0x17f
constant KEY_TAPE (line 433) | KEY_TAPE = 0x180
constant KEY_RADIO (line 434) | KEY_RADIO = 0x181
constant KEY_TUNER (line 435) | KEY_TUNER = 0x182
constant KEY_PLAYER (line 436) | KEY_PLAYER = 0x183
constant KEY_TEXT (line 437) | KEY_TEXT = 0x184
constant KEY_DVD (line 438) | KEY_DVD = 0x185
constant KEY_AUX (line 439) | KEY_AUX = 0x186
constant KEY_MP3 (line 440) | KEY_MP3 = 0x187
constant KEY_AUDIO (line 441) | KEY_AUDIO = 0x188
constant KEY_VIDEO (line 442) | KEY_VIDEO = 0x189
constant KEY_DIRECTORY (line 443) | KEY_DIRECTORY = 0x18a
constant KEY_LIST (line 444) | KEY_LIST = 0x18b
constant KEY_MEMO (line 445) | KEY_MEMO = 0x18c
constant KEY_CALENDAR (line 446) | KEY_CALENDAR = 0x18d
constant KEY_RED (line 447) | KEY_RED = 0x18e
constant KEY_GREEN (line 448) | KEY_GREEN = 0x18f
constant KEY_YELLOW (line 449) | KEY_YELLOW = 0x190
constant KEY_BLUE (line 450) | KEY_BLUE = 0x191
constant KEY_CHANNELUP (line 451) | KEY_CHANNELUP = 0x192
constant KEY_CHANNELDOWN (line 452) | KEY_CHANNELDOWN = 0x193
constant KEY_FIRST (line 453) | KEY_FIRST = 0x194
constant KEY_LAST (line 454) | KEY_LAST = 0x195
constant KEY_AB (line 455) | KEY_AB = 0x196
constant KEY_NEXT (line 456) | KEY_NEXT = 0x197
constant KEY_RESTART (line 457) | KEY_RESTART = 0x198
constant KEY_SLOW (line 458) | KEY_SLOW = 0x199
constant KEY_SHUFFLE (line 459) | KEY_SHUFFLE = 0x19a
constant KEY_BREAK (line 460) | KEY_BREAK = 0x19b
constant KEY_PREVIOUS (line 461) | KEY_PREVIOUS = 0x19c
constant KEY_DIGITS (line 462) | KEY_DIGITS = 0x19d
constant KEY_TEEN (line 463) | KEY_TEEN = 0x19e
constant KEY_TWEN (line 464) | KEY_TWEN = 0x19f
constant KEY_VIDEOPHONE (line 465) | KEY_VIDEOPHONE = 0x1a0
constant KEY_GAMES (line 466) | KEY_GAMES = 0x1a1
constant KEY_ZOOMIN (line 467) | KEY_ZOOMIN = 0x1a2
constant KEY_ZOOMOUT (line 468) | KEY_ZOOMOUT = 0x1a3
constant KEY_ZOOMRESET (line 469) | KEY_ZOOMRESET = 0x1a4
constant KEY_WORDPROCESSOR (line 470) | KEY_WORDPROCESSOR = 0x1a5
constant KEY_EDITOR (line 471) | KEY_EDITOR = 0x1a6
constant KEY_SPREADSHEET (line 472) | KEY_SPREADSHEET = 0x1a7
constant KEY_GRAPHICSEDITOR (line 473) | KEY_GRAPHICSEDITOR = 0x1a8
constant KEY_PRESENTATION (line 474) | KEY_PRESENTATION = 0x1a9
constant KEY_DATABASE (line 475) | KEY_DATABASE = 0x1aa
constant KEY_NEWS (line 476) | KEY_NEWS = 0x1ab
constant KEY_VOICEMAIL (line 477) | KEY_VOICEMAIL = 0x1ac
constant KEY_ADDRESSBOOK (line 478) | KEY_ADDRESSBOOK = 0x1ad
constant KEY_MESSENGER (line 479) | KEY_MESSENGER = 0x1ae
constant KEY_DISPLAYTOGGLE (line 480) | KEY_DISPLAYTOGGLE = 0x1af
constant KEY_BRIGHTNESS_TOGGLE (line 481) | KEY_BRIGHTNESS_TOGGLE = KEY_DISPLAYTOGGLE
constant KEY_SPELLCHECK (line 482) | KEY_SPELLCHECK = 0x1b0
constant KEY_LOGOFF (line 483) | KEY_LOGOFF = 0x1b1
constant KEY_DOLLAR (line 484) | KEY_DOLLAR = 0x1b2
constant KEY_EURO (line 485) | KEY_EURO = 0x1b3
constant KEY_FRAMEBACK (line 486) | KEY_FRAMEBACK = 0x1b4
constant KEY_FRAMEFORWARD (line 487) | KEY_FRAMEFORWARD = 0x1b5
constant KEY_CONTEXT_MENU (line 488) | KEY_CONTEXT_MENU = 0x1b6
constant KEY_MEDIA_REPEAT (line 489) | KEY_MEDIA_REPEAT = 0x1b7
constant KEY_10CHANNELSUP (line 490) | KEY_10CHANNELSUP = 0x1b8
constant KEY_10CHANNELSDOWN (line 491) | KEY_10CHANNELSDOWN = 0x1b9
constant KEY_IMAGES (line 492) | KEY_IMAGES = 0x1ba
constant KEY_DEL_EOL (line 493) | KEY_DEL_EOL = 0x1c0
constant KEY_DEL_EOS (line 494) | KEY_DEL_EOS = 0x1c1
constant KEY_INS_LINE (line 495) | KEY_INS_LINE = 0x1c2
constant KEY_DEL_LINE (line 496) | KEY_DEL_LINE = 0x1c3
constant KEY_FN (line 497) | KEY_FN = 0x1d0
constant KEY_FN_ESC (line 498) | KEY_FN_ESC = 0x1d1
constant KEY_FN_F1 (line 499) | KEY_FN_F1 = 0x1d2
constant KEY_FN_F2 (line 500) | KEY_FN_F2 = 0x1d3
constant KEY_FN_F3 (line 501) | KEY_FN_F3 = 0x1d4
constant KEY_FN_F4 (line 502) | KEY_FN_F4 = 0x1d5
constant KEY_FN_F5 (line 503) | KEY_FN_F5 = 0x1d6
constant KEY_FN_F6 (line 504) | KEY_FN_F6 = 0x1d7
constant KEY_FN_F7 (line 505) | KEY_FN_F7 = 0x1d8
constant KEY_FN_F8 (line 506) | KEY_FN_F8 = 0x1d9
constant KEY_FN_F9 (line 507) | KEY_FN_F9 = 0x1da
constant KEY_FN_F10 (line 508) | KEY_FN_F10 = 0x1db
constant KEY_FN_F11 (line 509) | KEY_FN_F11 = 0x1dc
constant KEY_FN_F12 (line 510) | KEY_FN_F12 = 0x1dd
constant KEY_FN_1 (line 511) | KEY_FN_1 = 0x1de
constant KEY_FN_2 (line 512) | KEY_FN_2 = 0x1df
constant KEY_FN_D (line 513) | KEY_FN_D = 0x1e0
constant KEY_FN_E (line 514) | KEY_FN_E = 0x1e1
constant KEY_FN_F (line 515) | KEY_FN_F = 0x1e2
constant KEY_FN_S (line 516) | KEY_FN_S = 0x1e3
constant KEY_FN_B (line 517) | KEY_FN_B = 0x1e4
constant KEY_BRL_DOT1 (line 518) | KEY_BRL_DOT1 = 0x1f1
constant KEY_BRL_DOT2 (line 519) | KEY_BRL_DOT2 = 0x1f2
constant KEY_BRL_DOT3 (line 520) | KEY_BRL_DOT3 = 0x1f3
constant KEY_BRL_DOT4 (line 521) | KEY_BRL_DOT4 = 0x1f4
constant KEY_BRL_DOT5 (line 522) | KEY_BRL_DOT5 = 0x1f5
constant KEY_BRL_DOT6 (line 523) | KEY_BRL_DOT6 = 0x1f6
constant KEY_BRL_DOT7 (line 524) | KEY_BRL_DOT7 = 0x1f7
constant KEY_BRL_DOT8 (line 525) | KEY_BRL_DOT8 = 0x1f8
constant KEY_BRL_DOT9 (line 526) | KEY_BRL_DOT9 = 0x1f9
constant KEY_BRL_DOT10 (line 527) | KEY_BRL_DOT10 = 0x1fa
constant KEY_NUMERIC_0 (line 528) | KEY_NUMERIC_0 = 0x200
constant KEY_NUMERIC_1 (line 529) | KEY_NUMERIC_1 = 0x201
constant KEY_NUMERIC_2 (line 530) | KEY_NUMERIC_2 = 0x202
constant KEY_NUMERIC_3 (line 531) | KEY_NUMERIC_3 = 0x203
constant KEY_NUMERIC_4 (line 532) | KEY_NUMERIC_4 = 0x204
constant KEY_NUMERIC_5 (line 533) | KEY_NUMERIC_5 = 0x205
constant KEY_NUMERIC_6 (line 534) | KEY_NUMERIC_6 = 0x206
constant KEY_NUMERIC_7 (line 535) | KEY_NUMERIC_7 = 0x207
constant KEY_NUMERIC_8 (line 536) | KEY_NUMERIC_8 = 0x208
constant KEY_NUMERIC_9 (line 537) | KEY_NUMERIC_9 = 0x209
constant KEY_NUMERIC_STAR (line 538) | KEY_NUMERIC_STAR = 0x20a
constant KEY_NUMERIC_POUND (line 539) | KEY_NUMERIC_POUND = 0x20b
constant KEY_NUMERIC_A (line 540) | KEY_NUMERIC_A = 0x20c
constant KEY_NUMERIC_B (line 541) | KEY_NUMERIC_B = 0x20d
constant KEY_NUMERIC_C (line 542) | KEY_NUMERIC_C = 0x20e
constant KEY_NUMERIC_D (line 543) | KEY_NUMERIC_D = 0x20f
constant KEY_CAMERA_FOCUS (line 544) | KEY_CAMERA_FOCUS = 0x210
constant KEY_WPS_BUTTON (line 545) | KEY_WPS_BUTTON = 0x211
constant KEY_TOUCHPAD_TOGGLE (line 546) | KEY_TOUCHPAD_TOGGLE = 0x212
constant KEY_TOUCHPAD_ON (line 547) | KEY_TOUCHPAD_ON = 0x213
constant KEY_TOUCHPAD_OFF (line 548) | KEY_TOUCHPAD_OFF = 0x214
constant KEY_CAMERA_ZOOMIN (line 549) | KEY_CAMERA_ZOOMIN = 0x215
constant KEY_CAMERA_ZOOMOUT (line 550) | KEY_CAMERA_ZOOMOUT = 0x216
constant KEY_CAMERA_UP (line 551) | KEY_CAMERA_UP = 0x217
constant KEY_CAMERA_DOWN (line 552) | KEY_CAMERA_DOWN = 0x218
constant KEY_CAMERA_LEFT (line 553) | KEY_CAMERA_LEFT = 0x219
constant KEY_CAMERA_RIGHT (line 554) | KEY_CAMERA_RIGHT = 0x21a
constant KEY_ATTENDANT_ON (line 555) | KEY_ATTENDANT_ON = 0x21b
constant KEY_ATTENDANT_OFF (line 556) | KEY_ATTENDANT_OFF = 0x21c
constant KEY_ATTENDANT_TOGGLE (line 557) | KEY_ATTENDANT_TOGGLE = 0x21d
constant KEY_LIGHTS_TOGGLE (line 558) | KEY_LIGHTS_TOGGLE = 0x21e
constant BTN_DPAD_UP (line 559) | BTN_DPAD_UP = 0x220
constant BTN_DPAD_DOWN (line 560) | BTN_DPAD_DOWN = 0x221
constant BTN_DPAD_LEFT (line 561) | BTN_DPAD_LEFT = 0x222
constant BTN_DPAD_RIGHT (line 562) | BTN_DPAD_RIGHT = 0x223
constant KEY_ALS_TOGGLE (line 563) | KEY_ALS_TOGGLE = 0x230
constant KEY_BUTTONCONFIG (line 564) | KEY_BUTTONCONFIG = 0x240
constant KEY_TASKMANAGER (line 565) | KEY_TASKMANAGER = 0x241
constant KEY_JOURNAL (line 566) | KEY_JOURNAL = 0x242
constant KEY_CONTROLPANEL (line 567) | KEY_CONTROLPANEL = 0x243
constant KEY_APPSELECT (line 568) | KEY_APPSELECT = 0x244
constant KEY_SCREENSAVER (line 569) | KEY_SCREENSAVER = 0x245
constant KEY_VOICECOMMAND (line 570) | KEY_VOICECOMMAND = 0x246
constant KEY_ASSISTANT (line 571) | KEY_ASSISTANT = 0x247
constant KEY_BRIGHTNESS_MIN (line 572) | KEY_BRIGHTNESS_MIN = 0x250
constant KEY_BRIGHTNESS_MAX (line 573) | KEY_BRIGHTNESS_MAX = 0x251
constant KEY_KBDINPUTASSIST_PREV (line 574) | KEY_KBDINPUTASSIST_PREV = 0x260
constant KEY_KBDINPUTASSIST_NEXT (line 575) | KEY_KBDINPUTASSIST_NEXT = 0x261
constant KEY_KBDINPUTASSIST_PREVGROUP (line 576) | KEY_KBDINPUTASSIST_PREVGROUP = 0x262
constant KEY_KBDINPUTASSIST_NEXTGROUP (line 577) | KEY_KBDINPUTASSIST_NEXTGROUP = 0x263
constant KEY_KBDINPUTASSIST_ACCEPT (line 578) | KEY_KBDINPUTASSIST_ACCEPT = 0x264
constant KEY_KBDINPUTASSIST_CANCEL (line 579) | KEY_KBDINPUTASSIST_CANCEL = 0x265
constant KEY_RIGHT_UP (line 580) | KEY_RIGHT_UP = 0x266
constant KEY_RIGHT_DOWN (line 581) | KEY_RIGHT_DOWN = 0x267
constant KEY_LEFT_UP (line 582) | KEY_LEFT_UP = 0x268
constant KEY_LEFT_DOWN (line 583) | KEY_LEFT_DOWN = 0x269
constant KEY_ROOT_MENU (line 584) | KEY_ROOT_MENU = 0x26a
constant KEY_MEDIA_TOP_MENU (line 585) | KEY_MEDIA_TOP_MENU = 0x26b
constant KEY_NUMERIC_11 (line 586) | KEY_NUMERIC_11 = 0x26c
constant KEY_NUMERIC_12 (line 587) | KEY_NUMERIC_12 = 0x26d
constant KEY_AUDIO_DESC (line 588) | KEY_AUDIO_DESC = 0x26e
constant KEY_3D_MODE (line 589) | KEY_3D_MODE = 0x26f
constant KEY_NEXT_FAVORITE (line 590) | KEY_NEXT_FAVORITE = 0x270
constant KEY_STOP_RECORD (line 591) | KEY_STOP_RECORD = 0x271
constant KEY_PAUSE_RECORD (line 592) | KEY_PAUSE_RECORD = 0x272
constant KEY_VOD (line 593) | KEY_VOD = 0x273
constant KEY_UNMUTE (line 594) | KEY_UNMUTE = 0x274
constant KEY_FASTREVERSE (line 595) | KEY_FASTREVERSE = 0x275
constant KEY_SLOWREVERSE (line 596) | KEY_SLOWREVERSE = 0x276
constant KEY_DATA (line 597) | KEY_DATA = 0x277
constant KEY_ONSCREEN_KEYBOARD (line 598) | KEY_ONSCREEN_KEYBOARD = 0x278
constant BTN_TRIGGER_HAPPY (line 599) | BTN_TRIGGER_HAPPY = 0x2c0
constant BTN_TRIGGER_HAPPY1 (line 600) | BTN_TRIGGER_HAPPY1 = 0x2c0
constant BTN_TRIGGER_HAPPY2 (line 601) | BTN_TRIGGER_HAPPY2 = 0x2c1
constant BTN_TRIGGER_HAPPY3 (line 602) | BTN_TRIGGER_HAPPY3 = 0x2c2
constant BTN_TRIGGER_HAPPY4 (line 603) | BTN_TRIGGER_HAPPY4 = 0x2c3
constant BTN_TRIGGER_HAPPY5 (line 604) | BTN_TRIGGER_HAPPY5 = 0x2c4
constant BTN_TRIGGER_HAPPY6 (line 605) | BTN_TRIGGER_HAPPY6 = 0x2c5
constant BTN_TRIGGER_HAPPY7 (line 606) | BTN_TRIGGER_HAPPY7 = 0x2c6
constant BTN_TRIGGER_HAPPY8 (line 607) | BTN_TRIGGER_HAPPY8 = 0x2c7
constant BTN_TRIGGER_HAPPY9 (line 608) | BTN_TRIGGER_HAPPY9 = 0x2c8
constant BTN_TRIGGER_HAPPY10 (line 609) | BTN_TRIGGER_HAPPY10 = 0x2c9
constant BTN_TRIGGER_HAPPY11 (line 610) | BTN_TRIGGER_HAPPY11 = 0x2ca
constant BTN_TRIGGER_HAPPY12 (line 611) | BTN_TRIGGER_HAPPY12 = 0x2cb
constant BTN_TRIGGER_HAPPY13 (line 612) | BTN_TRIGGER_HAPPY13 = 0x2cc
constant BTN_TRIGGER_HAPPY14 (line 613) | BTN_TRIGGER_HAPPY14 = 0x2cd
constant BTN_TRIGGER_HAPPY15 (line 614) | BTN_TRIGGER_HAPPY15 = 0x2ce
constant BTN_TRIGGER_HAPPY16 (line 615) | BTN_TRIGGER_HAPPY16 = 0x2cf
constant BTN_TRIGGER_HAPPY17 (line 616) | BTN_TRIGGER_HAPPY17 = 0x2d0
constant BTN_TRIGGER_HAPPY18 (line 617) | BTN_TRIGGER_HAPPY18 = 0x2d1
constant BTN_TRIGGER_HAPPY19 (line 618) | BTN_TRIGGER_HAPPY19 = 0x2d2
constant BTN_TRIGGER_HAPPY20 (line 619) | BTN_TRIGGER_HAPPY20 = 0x2d3
constant BTN_TRIGGER_HAPPY21 (line 620) | BTN_TRIGGER_HAPPY21 = 0x2d4
constant BTN_TRIGGER_HAPPY22 (line 621) | BTN_TRIGGER_HAPPY22 = 0x2d5
constant BTN_TRIGGER_HAPPY23 (line 622) | BTN_TRIGGER_HAPPY23 = 0x2d6
constant BTN_TRIGGER_HAPPY24 (line 623) | BTN_TRIGGER_HAPPY24 = 0x2d7
constant BTN_TRIGGER_HAPPY25 (line 624) | BTN_TRIGGER_HAPPY25 = 0x2d8
constant BTN_TRIGGER_HAPPY26 (line 625) | BTN_TRIGGER_HAPPY26 = 0x2d9
constant BTN_TRIGGER_HAPPY27 (line 626) | BTN_TRIGGER_HAPPY27 = 0x2da
constant BTN_TRIGGER_HAPPY28 (line 627) | BTN_TRIGGER_HAPPY28 = 0x2db
constant BTN_TRIGGER_HAPPY29 (line 628) | BTN_TRIGGER_HAPPY29 = 0x2dc
constant BTN_TRIGGER_HAPPY30 (line 629) | BTN_TRIGGER_HAPPY30 = 0x2dd
constant BTN_TRIGGER_HAPPY31 (line 630) | BTN_TRIGGER_HAPPY31 = 0x2de
constant BTN_TRIGGER_HAPPY32 (line 631) | BTN_TRIGGER_HAPPY32 = 0x2df
constant BTN_TRIGGER_HAPPY33 (line 632) | BTN_TRIGGER_HAPPY33 = 0x2e0
constant BTN_TRIGGER_HAPPY34 (line 633) | BTN_TRIGGER_HAPPY34 = 0x2e1
constant BTN_TRIGGER_HAPPY35 (line 634) | BTN_TRIGGER_HAPPY35 = 0x2e2
constant BTN_TRIGGER_HAPPY36 (line 635) | BTN_TRIGGER_HAPPY36 = 0x2e3
constant BTN_TRIGGER_HAPPY37 (line 636) | BTN_TRIGGER_HAPPY37 = 0x2e4
constant BTN_TRIGGER_HAPPY38 (line 637) | BTN_TRIGGER_HAPPY38 = 0x2e5
constant BTN_TRIGGER_HAPPY39 (line 638) | BTN_TRIGGER_HAPPY39 = 0x2e6
constant BTN_TRIGGER_HAPPY40 (line 639) | BTN_TRIGGER_HAPPY40 = 0x2e7
constant KEY_MIN_INTERESTING (line 640) | KEY_MIN_INTERESTING = KEY_MUTE
constant KEY_MAX (line 641) | KEY_MAX = 0x2ff
constant REL_X (line 642) | REL_X = 0x00
constant REL_Y (line 643) | REL_Y = 0x01
constant REL_Z (line 644) | REL_Z = 0x02
constant REL_RX (line 645) | REL_RX = 0x03
constant REL_RY (line 646) | REL_RY = 0x04
constant REL_RZ (line 647) | REL_RZ = 0x05
constant REL_HWHEEL (line 648) | REL_HWHEEL = 0x06
constant REL_DIAL (line 649) | REL_DIAL = 0x07
constant REL_WHEEL (line 650) | REL_WHEEL = 0x08
constant REL_MISC (line 651) | REL_MISC = 0x09
constant REL_MAX (line 652) | REL_MAX = 0x0f
constant ABS_X (line 653) | ABS_X = 0x00
constant ABS_Y (line 654) | ABS_Y = 0x01
constant ABS_Z (line 655) | ABS_Z = 0x02
constant ABS_RX (line 656) | ABS_RX = 0x03
constant ABS_RY (line 657) | ABS_RY = 0x04
constant ABS_RZ (line 658) | ABS_RZ = 0x05
constant ABS_THROTTLE (line 659) | ABS_THROTTLE = 0x06
constant ABS_RUDDER (line 660) | ABS_RUDDER = 0x07
constant ABS_WHEEL (line 661) | ABS_WHEEL = 0x08
constant ABS_GAS (line 662) | ABS_GAS = 0x09
constant ABS_BRAKE (line 663) | ABS_BRAKE = 0x0a
constant ABS_HAT0X (line 664) | ABS_HAT0X = 0x10
constant ABS_HAT0Y (line 665) | ABS_HAT0Y = 0x11
constant ABS_HAT1X (line 666) | ABS_HAT1X = 0x12
constant ABS_HAT1Y (line 667) | ABS_HAT1Y = 0x13
constant ABS_HAT2X (line 668) | ABS_HAT2X = 0x14
constant ABS_HAT2Y (line 669) | ABS_HAT2Y = 0x15
constant ABS_HAT3X (line 670) | ABS_HAT3X = 0x16
constant ABS_HAT3Y (line 671) | ABS_HAT3Y = 0x17
constant ABS_PRESSURE (line 672) | ABS_PRESSURE = 0x18
constant ABS_DISTANCE (line 673) | ABS_DISTANCE = 0x19
constant ABS_TILT_X (line 674) | ABS_TILT_X = 0x1a
constant ABS_TILT_Y (line 675) | ABS_TILT_Y = 0x1b
constant ABS_TOOL_WIDTH (line 676) | ABS_TOOL_WIDTH = 0x1c
constant ABS_VOLUME (line 677) | ABS_VOLUME = 0x20
constant ABS_MISC (line 678) | ABS_MISC = 0x28
constant ABS_RESERVED (line 679) | ABS_RESERVED = 0x2e
constant ABS_MT_SLOT (line 680) | ABS_MT_SLOT = 0x2f
constant ABS_MT_TOUCH_MAJOR (line 681) | ABS_MT_TOUCH_MAJOR = 0x30
constant ABS_MT_TOUCH_MINOR (line 682) | ABS_MT_TOUCH_MINOR = 0x31
constant ABS_MT_WIDTH_MAJOR (line 683) | ABS_MT_WIDTH_MAJOR = 0x32
constant ABS_MT_WIDTH_MINOR (line 684) | ABS_MT_WIDTH_MINOR = 0x33
constant ABS_MT_ORIENTATION (line 685) | ABS_MT_ORIENTATION = 0x34
constant ABS_MT_POSITION_X (line 686) | ABS_MT_POSITION_X = 0x35
constant ABS_MT_POSITION_Y (line 687) | ABS_MT_POSITION_Y = 0x36
constant ABS_MT_TOOL_TYPE (line 688) | ABS_MT_TOOL_TYPE = 0x37
constant ABS_MT_BLOB_ID (line 689) | ABS_MT_BLOB_ID = 0x38
constant ABS_MT_TRACKING_ID (line 690) | ABS_MT_TRACKING_ID = 0x39
constant ABS_MT_PRESSURE (line 691) | ABS_MT_PRESSURE = 0x3a
constant ABS_MT_DISTANCE (line 692) | ABS_MT_DISTANCE = 0x3b
constant ABS_MT_TOOL_X (line 693) | ABS_MT_TOOL_X = 0x3c
constant ABS_MT_TOOL_Y (line 694) | ABS_MT_TOOL_Y = 0x3d
constant ABS_MAX (line 695) | ABS_MAX = 0x3f
constant SW_LID (line 696) | SW_LID = 0x00
constant SW_TABLET_MODE (line 697) | SW_TABLET_MODE = 0x01
constant SW_HEADPHONE_INSERT (line 698) | SW_HEADPHONE_INSERT = 0x02
constant SW_RFKILL_ALL (line 699) | SW_RFKILL_ALL = 0x03
constant SW_RADIO (line 700) | SW_RADIO = SW_RFKILL_ALL
constant SW_MICROPHONE_INSERT (line 701) | SW_MICROPHONE_INSERT = 0x04
constant SW_DOCK (line 702) | SW_DOCK = 0x05
constant SW_LINEOUT_INSERT (line 703) | SW_LINEOUT_INSERT = 0x06
constant SW_JACK_PHYSICAL_INSERT (line 704) | SW_JACK_PHYSICAL_INSERT = 0x07
constant SW_VIDEOOUT_INSERT (line 705) | SW_VIDEOOUT_INSERT = 0x08
constant SW_CAMERA_LENS_COVER (line 706) | SW_CAMERA_LENS_COVER = 0x09
constant SW_KEYPAD_SLIDE (line 707) | SW_KEYPAD_SLIDE = 0x0a
constant SW_FRONT_PROXIMITY (line 708) | SW_FRONT_PROXIMITY = 0x0b
constant SW_ROTATE_LOCK (line 709) | SW_ROTATE_LOCK = 0x0c
constant SW_LINEIN_INSERT (line 710) | SW_LINEIN_INSERT = 0x0d
constant SW_MUTE_DEVICE (line 711) | SW_MUTE_DEVICE = 0x0e
constant SW_PEN_INSERTED (line 712) | SW_PEN_INSERTED = 0x0f
constant SW_MAX (line 713) | SW_MAX = 0x0f
constant MSC_SERIAL (line 714) | MSC_SERIAL = 0x00
constant MSC_PULSELED (line 715) | MSC_PULSELED = 0x01
constant MSC_GESTURE (line 716) | MSC_GESTURE = 0x02
constant MSC_RAW (line 717) | MSC_RAW = 0x03
constant MSC_SCAN (line 718) | MSC_SCAN = 0x04
constant MSC_TIMESTAMP (line 719) | MSC_TIMESTAMP = 0x05
constant MSC_MAX (line 720) | MSC_MAX = 0x07
constant LED_NUML (line 721) | LED_NUML = 0x00
constant LED_CAPSL (line 722) | LED_CAPSL = 0x01
constant LED_SCROLLL (line 723) | LED_SCROLLL = 0x02
constant LED_COMPOSE (line 724) | LED_COMPOSE = 0x03
constant LED_KANA (line 725) | LED_KANA = 0x04
constant LED_SLEEP (line 726) | LED_SLEEP = 0x05
constant LED_SUSPEND (line 727) | LED_SUSPEND = 0x06
constant LED_MUTE (line 728) | LED_MUTE = 0x07
constant LED_MISC (line 729) | LED_MISC = 0x08
constant LED_MAIL (line 730) | LED_MAIL = 0x09
constant LED_CHARGING (line 731) | LED_CHARGING = 0x0a
constant LED_MAX (line 732) | LED_MAX = 0x0f
constant REP_DELAY (line 733) | REP_DELAY = 0x00
constant REP_PERIOD (line 734) | REP_PERIOD = 0x01
constant REP_MAX (line 735) | REP_MAX = 0x01
constant SND_CLICK (line 736) | SND_CLICK = 0x00
constant SND_BELL (line 737) | SND_BELL = 0x01
constant SND_TONE (line 738) | SND_TONE = 0x02
constant SND_MAX (line 739) | SND_MAX = 0x07
function CodeString (line 757) | func CodeString(etype uint16, code uint16) string {
FILE: pkg/evdeviterator.go
type rawEvent (line 24) | type rawEvent struct
type FileEvdevIterator (line 36) | type FileEvdevIterator struct
method Next (line 43) | func (it *FileEvdevIterator) Next() bool {
method Current (line 73) | func (it *FileEvdevIterator) Current() EvdevEvent {
method Close (line 78) | func (it *FileEvdevIterator) Close() error {
type SelectingEvdevIterator (line 88) | type SelectingEvdevIterator struct
method Next (line 96) | func (it *SelectingEvdevIterator) Next() bool {
method Current (line 110) | func (it *SelectingEvdevIterator) Current() EvdevEvent {
method Close (line 115) | func (it *SelectingEvdevIterator) Close() error {
type FilteringEvdevIterator (line 121) | type FilteringEvdevIterator struct
method Next (line 129) | func (it *FilteringEvdevIterator) Next() bool {
method Current (line 148) | func (it *FilteringEvdevIterator) Current() EvdevEvent {
method Close (line 153) | func (it *FilteringEvdevIterator) Close() error {
FILE: pkg/evdeviterator_test.go
function TestFileEvdevIterator_Next (line 25) | func TestFileEvdevIterator_Next(t *testing.T) {
function TestSelectingEvdevIterator_Next (line 82) | func TestSelectingEvdevIterator_Next(t *testing.T) {
function TestFilteringEvdevIterator_Next (line 137) | func TestFilteringEvdevIterator_Next(t *testing.T) {
FILE: pkg/internal/gencodes/main.go
constant pattern (line 39) | pattern = `#define +((?:KEY|ABS|REL|SW|MSC|LED|BTN|REP|SND|ID|EV|BUS|SYN...
function main (line 41) | func main() {
FILE: pkg/internal/robotgo/base/MMBitmap.h
type _MMBitmap (line 20) | struct _MMBitmap {
type MMBitmap (line 30) | typedef struct _MMBitmap MMBitmap;
type MMBitmap (line 31) | typedef MMBitmap *MMBitmapRef;
FILE: pkg/internal/robotgo/base/MMBitmap_c.h
function MMBitmapRef (line 7) | MMBitmapRef createMMBitmap(
function destroyMMBitmap (line 28) | void destroyMMBitmap(MMBitmapRef bitmap)
function destroyMMBitmapBuffer (line 40) | void destroyMMBitmapBuffer(char * bitmapBuffer, void * hint)
function MMBitmapRef (line 48) | MMBitmapRef copyMMBitmap(MMBitmapRef bitmap)
function MMBitmapRef (line 69) | MMBitmapRef copyMMBitmapFromPortion(MMBitmapRef source, MMRect rect)
FILE: pkg/internal/robotgo/base/MMPointArray.h
type _MMPointArray (line 7) | struct _MMPointArray {
type MMPointArray (line 13) | typedef struct _MMPointArray MMPointArray;
type MMPointArray (line 14) | typedef MMPointArray *MMPointArrayRef;
FILE: pkg/internal/robotgo/base/MMPointArray_c.h
function MMPointArrayRef (line 4) | MMPointArrayRef createMMPointArray(size_t initialCount)
function destroyMMPointArray (line 17) | void destroyMMPointArray(MMPointArrayRef pointArray)
function MMPointArrayAppendPoint (line 27) | void MMPointArrayAppendPoint(MMPointArrayRef pointArray, MMPoint point)
FILE: pkg/internal/robotgo/base/UTHashTable.h
type _UTHashTable (line 15) | struct _UTHashTable {
type UTHashTable (line 23) | typedef struct _UTHashTable UTHashTable;
FILE: pkg/internal/robotgo/base/UTHashTable_c.h
type _UTHashNode (line 7) | struct _UTHashNode {
type UTHashNode (line 11) | typedef struct _UTHashNode UTHashNode;
function initHashTable (line 13) | void initHashTable(UTHashTable *table, size_t initialCount, size_t nodeS...
function destroyHashTable (line 25) | void destroyHashTable(UTHashTable *table)
FILE: pkg/internal/robotgo/base/bmp_io.h
type _BMPReadError (line 8) | enum _BMPReadError {
type MMIOError (line 19) | typedef MMIOError MMBMPReadError;
FILE: pkg/internal/robotgo/base/bmp_io_c.h
type BITMAP_FILE_HEADER (line 20) | struct BITMAP_FILE_HEADER {
type _BMP_COMPRESSION (line 29) | enum _BMP_COMPRESSION {
type BMP_COMPRESSION (line 38) | typedef uint32_t BMP_COMPRESSION;
type BITMAP_INFO_HEADER (line 43) | struct BITMAP_INFO_HEADER {
type BITMAP_CORE_HEADER (line 66) | struct BITMAP_CORE_HEADER {
function convertBitmapFileHeader (line 83) | static void convertBitmapFileHeader(struct BITMAP_FILE_HEADER *header)
function convertBitmapInfoHeader (line 93) | static void convertBitmapInfoHeader(struct BITMAP_INFO_HEADER *header)
function MMBitmapRef (line 144) | MMBitmapRef newMMBitmapFromBMP(const char *path, MMBMPReadError *err)
type BITMAP_FILE_HEADER (line 259) | struct BITMAP_FILE_HEADER
type BITMAP_INFO_HEADER (line 260) | struct BITMAP_INFO_HEADER
type BITMAP_FILE_HEADER (line 271) | struct BITMAP_FILE_HEADER
type BITMAP_INFO_HEADER (line 281) | struct BITMAP_INFO_HEADER
function saveMMBitmapAsBMP (line 299) | int saveMMBitmapAsBMP(MMBitmapRef bitmap, const char *path)
function copyBGRDataFromMMBitmap (line 382) | static void copyBGRDataFromMMBitmap(MMBitmapRef bitmap, uint8_t *dest)
function flipBitmapData (line 413) | void flipBitmapData(void *data, size_t width, size_t height, size_t byte...
FILE: pkg/internal/robotgo/base/color_find_c.h
function findColorInRectAt (line 6) | static int findColorInRectAt(MMBitmapRef image, MMRGBHex color, MMPoint ...
function findColorInRect (line 26) | int findColorInRect(MMBitmapRef image, MMRGBHex color,
function MMPointArrayRef (line 32) | MMPointArrayRef findAllColorInRect(MMBitmapRef image, MMRGBHex color,
function countOfColorsInRect (line 46) | size_t countOfColorsInRect(MMBitmapRef image, MMRGBHex color, MMRect rect,
FILE: pkg/internal/robotgo/base/deadbeef_rand_c.h
function deadbeef_rand (line 7) | uint32_t deadbeef_rand(void)
function deadbeef_srand (line 14) | void deadbeef_srand(uint32_t x)
function deadbeef_generate_seed (line 22) | uint32_t deadbeef_generate_seed(void)
FILE: pkg/internal/robotgo/base/file_io.h
type _MMImageType (line 10) | enum _MMImageType {
type MMImageType (line 16) | typedef uint16_t MMImageType;
type _MMIOError (line 18) | enum _MMIOError {
type MMIOError (line 22) | typedef uint16_t MMIOError;
FILE: pkg/internal/robotgo/base/file_io_c.h
function MMImageType (line 18) | MMImageType imageTypeFromExtension(const char *extension){
function MMBitmapRef (line 38) | MMBitmapRef newMMBitmapFromFile(const char *path, MMImageType type, MMIO...
function saveMMBitmapToFile (line 50) | int saveMMBitmapToFile(MMBitmapRef bitmap, const char *path, MMImageType...
FILE: pkg/internal/robotgo/base/io.c
function MMImageType (line 18) | MMImageType imageTypeFromExtension(const char *extension){
function MMBitmapRef (line 38) | MMBitmapRef newMMBitmapFromFile(const char *path, MMImageType type, MMIO...
function saveMMBitmapToFile (line 50) | int saveMMBitmapToFile(MMBitmapRef bitmap, const char *path, MMImageType...
FILE: pkg/internal/robotgo/base/microsleep.h
function H_INLINE (line 23) | H_INLINE void microsleep(double milliseconds)
FILE: pkg/internal/robotgo/base/ms_stdint.h
type int_least8_t (line 91) | typedef int8_t int_least8_t;
type int_least16_t (line 92) | typedef int16_t int_least16_t;
type int_least32_t (line 93) | typedef int32_t int_least32_t;
type int_least64_t (line 94) | typedef int64_t int_least64_t;
type uint_least8_t (line 95) | typedef uint8_t uint_least8_t;
type uint_least16_t (line 96) | typedef uint16_t uint_least16_t;
type uint_least32_t (line 97) | typedef uint32_t uint_least32_t;
type uint_least64_t (line 98) | typedef uint64_t uint_least64_t;
type int_fast8_t (line 101) | typedef int8_t int_fast8_t;
type int_fast16_t (line 102) | typedef int16_t int_fast16_t;
type int_fast32_t (line 103) | typedef int32_t int_fast32_t;
type int_fast64_t (line 104) | typedef int64_t int_fast64_t;
type uint_fast8_t (line 105) | typedef uint8_t uint_fast8_t;
type uint_fast16_t (line 106) | typedef uint16_t uint_fast16_t;
type uint_fast32_t (line 107) | typedef uint32_t uint_fast32_t;
type uint_fast64_t (line 108) | typedef uint64_t uint_fast64_t;
type intmax_t (line 120) | typedef int64_t intmax_t;
type uintmax_t (line 121) | typedef uint64_t uintmax_t;
FILE: pkg/internal/robotgo/base/pasteboard.h
type _MMBitmapPasteError (line 8) | enum _MMBitmapPasteError {
type MMIOError (line 18) | typedef MMIOError MMPasteError;
FILE: pkg/internal/robotgo/base/pasteboard_c.h
function MMPasteError (line 11) | MMPasteError copyMMBitmapToPasteboard(MMBitmapRef bitmap)
FILE: pkg/internal/robotgo/base/png_io.h
type _PNGReadError (line 8) | enum _PNGReadError {
type MMIOError (line 15) | typedef MMIOError MMPNGReadError;
FILE: pkg/internal/robotgo/base/png_io_c.h
function MMBitmapRef (line 42) | MMBitmapRef newMMBitmapFromPNG(const char *path, MMPNGReadError *err)
type _PNGWriteInfo (line 161) | struct _PNGWriteInfo {
type PNGWriteInfo (line 169) | typedef struct _PNGWriteInfo PNGWriteInfo;
type PNGWriteInfo (line 170) | typedef PNGWriteInfo *PNGWriteInfoRef;
function PNGWriteInfoRef (line 177) | static PNGWriteInfoRef createPNGWriteInfo(MMBitmapRef bitmap)
function destroyPNGWriteInfo (line 263) | static void destroyPNGWriteInfo(PNGWriteInfoRef info)
function saveMMBitmapAsPNG (line 280) | int saveMMBitmapAsPNG(MMBitmapRef bitmap, const char *path)
type io_data (line 300) | struct io_data
function png_append_data (line 308) | void png_append_data(png_struct *png_ptr,
type io_data (line 336) | struct io_data
FILE: pkg/internal/robotgo/base/rgb.h
type _MMRGBColor (line 27) | struct _MMRGBColor {
type MMRGBColor (line 33) | typedef struct _MMRGBColor MMRGBColor;
type MMRGBHex (line 38) | typedef uint32_t MMRGBHex;
function H_INLINE (line 49) | H_INLINE MMRGBHex hexFromMMRGB(MMRGBColor rgb)
function H_INLINE (line 59) | H_INLINE MMRGBColor MMRGBFromHex(MMRGBHex hex)
function H_INLINE (line 76) | H_INLINE int MMRGBColorSimilarToColor(MMRGBColor c1, MMRGBColor c2,
function H_INLINE (line 94) | H_INLINE int MMRGBHexSimilarToColor(MMRGBHex h1, MMRGBHex h2, float tole...
FILE: pkg/internal/robotgo/base/snprintf_c.h
function asprintf (line 414) | int asprintf(char **ptr, const char *fmt, /*args*/ ...) {
function vasprintf (line 438) | int vasprintf(char **ptr, const char *fmt, va_list ap) {
function asnprintf (line 460) | int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...) {
function vasnprintf (line 488) | int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap) {
function portable_snprintf (line 520) | int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/...
FILE: pkg/internal/robotgo/base/str_io.h
type _MMBMPStringError (line 10) | enum _MMBMPStringError {
type MMIOError (line 20) | typedef MMIOError MMBMPStringError;
FILE: pkg/internal/robotgo/base/str_io_c.h
function MMBitmapRef (line 53) | MMBitmapRef createMMBitmapFromString(const uint8_t *buffer, size_t buflen,
function getSizeFromString (line 143) | static bool getSizeFromString(const uint8_t *buf, size_t buflen,
function parseDimension (line 167) | static uint32_t parseDimension(const uint8_t *buf,
FILE: pkg/internal/robotgo/base/types.h
type _MMPoint (line 12) | struct _MMPoint {
type MMPoint (line 17) | typedef struct _MMPoint MMPoint;
type _MMPointInt32 (line 19) | struct _MMPointInt32 {
type MMPointInt32 (line 24) | typedef struct _MMPointInt32 MMPointInt32;
type _MMSize (line 26) | struct _MMSize {
type MMSize (line 31) | typedef struct _MMSize MMSize;
type _MMSizeInt32 (line 33) | struct _MMSizeInt32 {
type MMSizeInt32 (line 38) | typedef struct _MMSizeInt32 MMSizeInt32;
type _MMRect (line 41) | struct _MMRect {
type MMRect (line 46) | typedef struct _MMRect MMRect;
type _MMRectInt32 (line 48) | struct _MMRectInt32 {
type MMRectInt32 (line 53) | typedef struct _MMRectInt32 MMRectInt32;
function H_INLINE (line 55) | H_INLINE MMPoint MMPointMake(size_t x, size_t y)
function H_INLINE (line 63) | H_INLINE MMPointInt32 MMPointInt32Make(int32_t x, int32_t y)
function H_INLINE (line 71) | H_INLINE MMSize MMSizeMake(size_t width, size_t height)
function H_INLINE (line 79) | H_INLINE MMSizeInt32 MMSizeInt32Make(int32_t w, int32_t h)
function H_INLINE (line 87) | H_INLINE MMRect MMRectMake(size_t x, size_t y, size_t width, size_t height)
function H_INLINE (line 95) | H_INLINE MMRectInt32 MMRectInt32Make(int32_t x, int32_t y, int32_t w, in...
FILE: pkg/internal/robotgo/base/uthash.h
type UT_hash_bucket (line 861) | typedef struct UT_hash_bucket {
type UT_hash_table (line 885) | typedef struct UT_hash_table {
type UT_hash_handle (line 918) | typedef struct UT_hash_handle {
FILE: pkg/internal/robotgo/base/xdisplay_c.h
function Display (line 10) | Display *XGetMainDisplay(void)
function XCloseMainDisplay (line 38) | void XCloseMainDisplay(void)
function setXDisplay (line 46) | void setXDisplay(char *name)
FILE: pkg/internal/robotgo/mouse/goMouse.h
function move_mouse (line 17) | int move_mouse(int32_t x, int32_t y)
function drag_mouse (line 26) | int drag_mouse(int32_t x, int32_t y, MMMouseButton button)
function move_mouse_smooth (line 35) | bool move_mouse_smooth(int32_t x, int32_t y, double lowSpeed,
function MMPointInt32 (line 47) | MMPointInt32 get_mouse_pos()
function mouse_click (line 54) | int mouse_click(MMMouseButton button, bool doubleC)
function mouse_toggle (line 70) | int mouse_toggle(char *d, MMMouseButton button)
function set_mouse_delay (line 92) | int set_mouse_delay(size_t val)
function scroll (line 99) | int scroll(int x, int y, int msDelay)
function scroll_mouse (line 107) | int scroll_mouse(size_t scrollMagnitude, char *s)
FILE: pkg/internal/robotgo/mouse/mouse.h
type MMMouseButton (line 24) | typedef enum
type _MMMouseButton (line 33) | enum _MMMouseButton
type MMMouseButton (line 39) | typedef unsigned int MMMouseButton;
type _MMMouseButton (line 43) | enum _MMMouseButton
type MMMouseButton (line 49) | typedef unsigned int MMMouseButton;
type __MMMouseWheelDirection (line 59) | enum __MMMouseWheelDirection
type MMMouseWheelDirection (line 64) | typedef int MMMouseWheelDirection;
FILE: pkg/internal/robotgo/mouse/mouse_c.h
function calculateDeltas (line 63) | void calculateDeltas(CGEventRef *event, MMPointInt32 point)
function moveMouse (line 88) | void moveMouse(MMPointInt32 point)
function dragMouse (line 127) | void dragMouse(MMPointInt32 point, const MMMouseButton button)
function MMPointInt32 (line 143) | MMPointInt32 getMousePos()
function toggleMouse (line 175) | void toggleMouse(bool down, MMMouseButton button)
function clickMouse (line 205) | void clickMouse(MMMouseButton button)
function doubleClick (line 215) | void doubleClick(MMMouseButton button)
function scrollMouse (line 252) | void scrollMouse(int scrollMagnitude, MMMouseWheelDirection scrollDirect...
function scrollMouseXY (line 316) | void scrollMouseXY(int x, int y)
function crude_hypot (line 401) | static double crude_hypot(double x, double y)
function smoothlyMoveMouse (line 416) | bool smoothlyMoveMouse(MMPointInt32 endPoint, double lowSpeed, double hi...
FILE: pkg/internal/robotgo/robotgo.go
constant Version (line 49) | Version = "v0.90.0.940, Sierra Nevada!"
function GetVersion (line 53) | func GetVersion() string {
type Map (line 59) | type Map
function Try (line 63) | func Try(fun func(), handler func(interface{})) {
function MilliSleep (line 73) | func MilliSleep(tm int) {
function Sleep (line 78) | func Sleep(tm int) {
function MicroSleep (line 83) | func MicroSleep(tm float64) {
function GoString (line 88) | func GoString(char *C.char) string {
function ScaleX (line 93) | func ScaleX() int {
function ScaleY (line 98) | func ScaleY() int {
function GetScreenSize (line 103) | func GetScreenSize() (int, int) {
function Scale (line 110) | func Scale() int {
function Mul (line 132) | func Mul(x int) int {
function GetScaleSize (line 138) | func GetScaleSize() (int, int) {
function SetXDisplayName (line 145) | func SetXDisplayName(name string) string {
function GetXDisplayName (line 156) | func GetXDisplayName() string {
function CheckMouse (line 175) | func CheckMouse(btn string) C.MMMouseButton {
function MoveMouse (line 193) | func MoveMouse(x, y int) {
function Move (line 199) | func Move(x, y int) {
function DragMouse (line 206) | func DragMouse(x, y int, args ...string) {
function Drag (line 211) | func Drag(x, y int, args ...string) {
function DragSmooth (line 225) | func DragSmooth(x, y int, args ...interface{}) {
function MoveMouseSmooth (line 233) | func MoveMouseSmooth(x, y int, args ...interface{}) bool {
function MoveSmooth (line 241) | func MoveSmooth(x, y int, args ...interface{}) bool {
function GetMousePos (line 269) | func GetMousePos() (int, int) {
function MouseClick (line 281) | func MouseClick(args ...interface{}) {
function Click (line 288) | func Click(args ...interface{}) {
function MoveClick (line 308) | func MoveClick(x, y int, args ...interface{}) {
function MovesClick (line 314) | func MovesClick(x, y int, args ...interface{}) {
function MouseToggle (line 320) | func MouseToggle(togKey string, args ...interface{}) {
function SetMouseDelay (line 334) | func SetMouseDelay(delay int) {
function ScrollMouse (line 340) | func ScrollMouse(x int, direction string) {
function Scroll (line 351) | func Scroll(x, y int, args ...int) {
FILE: pkg/internal/robotgo/screen/goScreen.h
function MMSizeInt32 (line 15) | MMSizeInt32 get_screen_size()
FILE: pkg/internal/robotgo/screen/screen_c.h
function MMSizeInt32 (line 10) | MMSizeInt32 getMainDisplaySize(void)
function pointVisibleOnMainDisplay (line 36) | bool pointVisibleOnMainDisplay(MMPointInt32 point)
FILE: pkg/internal/robotgo/window/arr.h
type Arr (line 1) | struct Arr
FILE: pkg/internal/robotgo/window/goWindow.h
function intptr (line 14) | intptr scale_x()
function intptr (line 19) | intptr scale_y()
function is_valid (line 24) | bool is_valid()
function min_window (line 30) | void min_window(uintptr pid, bool state, uintptr isHwnd)
function max_window (line 55) | void max_window(uintptr pid, bool state, uintptr isHwnd)
function close_window (line 76) | void close_window(uintptr pid, uintptr isHwnd)
function set_handle (line 81) | bool set_handle(uintptr handle)
function uintptr (line 87) | uintptr get_handle()
function uintptr (line 100) | uintptr bget_handle()
function set_active (line 106) | void set_active(const MData win)
function active_PID (line 111) | void active_PID(uintptr pid, uintptr isHwnd)
function MData (line 117) | MData get_active()
function int32 (line 130) | int32 get_PID(void)
FILE: pkg/internal/robotgo/window/process.h
type int8 (line 60) | typedef signed char int8;
type int16 (line 61) | typedef signed short int16;
type int32 (line 62) | typedef signed int int32;
type int64 (line 63) | typedef signed long long int64;
type uint8 (line 65) | typedef unsigned char uint8;
type uint16 (line 66) | typedef unsigned short uint16;
type uint32 (line 67) | typedef unsigned int uint32;
type uint64 (line 68) | typedef unsigned long long uint64;
type real32 (line 70) | typedef float real32;
type real64 (line 71) | typedef double real64;
type int64 (line 75) | typedef int64 intptr;
type uint64 (line 76) | typedef uint64 uintptr;
type int32 (line 80) | typedef int32 intptr;
type uint32 (line 81) | typedef uint32 uintptr;
type _PData (line 86) | struct _PData
type _PPData (line 110) | struct _PPData
type PData (line 134) | typedef struct _PData PData;
FILE: pkg/internal/robotgo/window/pub.h
type _MData (line 11) | struct _MData
type MData (line 24) | typedef struct _MData MData;
type _Bounds (line 28) | struct _Bounds
type Bounds (line 36) | typedef struct _Bounds Bounds;
function AXUIElementRef (line 46) | static AXUIElementRef GetUIElement(CGWindowID win)
function XHandleError (line 137) | static int XHandleError(Display *dp, XErrorEvent *e) { return 0; }
function XDismissErrors (line 141) | void XDismissErrors(void)
type Hints (line 155) | struct Hints
function LoadAtoms (line 182) | static void LoadAtoms(void)
function SetDesktopForWindow (line 255) | static void SetDesktopForWindow(MData win)
function Bounds (line 292) | static Bounds GetFrame(MData win)
FILE: pkg/internal/robotgo/window/win32.h
type WNDINFO (line 12) | typedef struct
function BOOL (line 18) | BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
function HWND (line 32) | HWND GetHwndByPId(DWORD dwProcessId)
function win_min (line 43) | void win_min(HWND hwnd, bool state)
function win_max (line 55) | void win_max(HWND hwnd, bool state)
FILE: pkg/internal/robotgo/window/win_sys.h
function intptr (line 13) | intptr scaleX()
function intptr (line 29) | intptr scaleY()
function Bounds (line 44) | Bounds get_bounds(uintptr pid, uintptr isHwnd)
function Bounds (line 142) | Bounds get_client(uintptr pid, uintptr isHwnd)
FILE: pkg/internal/robotgo/window/window.h
function initWindow (line 30) | void initWindow(uintptr handle)
function Is64Bit (line 58) | bool Is64Bit()
function MData (line 67) | MData set_handle_pid(uintptr pid, uintptr isHwnd)
function set_handle_pid_mData (line 91) | void set_handle_pid_mData(uintptr pid, uintptr isHwnd)
function IsValid (line 97) | bool IsValid()
function IsAxEnabled (line 169) | bool IsAxEnabled(bool options)
function setHandle (line 230) | bool setHandle(uintptr handle)
function uintptr (line 301) | uintptr getHandle()
function IsTopMost (line 312) | bool IsTopMost(void)
function IsMinimized (line 336) | bool IsMinimized(void)
function IsMaximized (line 375) | bool IsMaximized(void)
function SetActive (line 399) | void SetActive(const MData win)
function MData (line 490) | MData GetActive(void)
function SetTopMost (line 608) | void SetTopMost(bool state)
function close_main_window (line 634) | void close_main_window()
function close_window_by_PId (line 645) | void close_window_by_PId(uintptr pid, uintptr isHwnd)
function close_window_by_Id (line 652) | void close_window_by_Id(MData m_data)
function int32 (line 793) | int32 WGetPID(void)
FILE: pkg/mock_driver_test.go
type MockDriver (line 14) | type MockDriver struct
method EXPECT (line 32) | func (m *MockDriver) EXPECT() *MockDriverMockRecorder {
method Click (line 37) | func (m *MockDriver) Click() error {
method DragMouse (line 51) | func (m *MockDriver) DragMouse(arg0, arg1 int) error {
method GetSize (line 65) | func (m *MockDriver) GetSize() (int, int, error) {
method MoveMouse (line 81) | func (m *MockDriver) MoveMouse(arg0, arg1 int) error {
method Unclick (line 95) | func (m *MockDriver) Unclick() error {
type MockDriverMockRecorder (line 20) | type MockDriverMockRecorder struct
method Click (line 45) | func (mr *MockDriverMockRecorder) Click() *gomock.Call {
method DragMouse (line 59) | func (mr *MockDriverMockRecorder) DragMouse(arg0, arg1 interface{}) *g...
method GetSize (line 75) | func (mr *MockDriverMockRecorder) GetSize() *gomock.Call {
method MoveMouse (line 89) | func (mr *MockDriverMockRecorder) MoveMouse(arg0, arg1 interface{}) *g...
method Unclick (line 103) | func (mr *MockDriverMockRecorder) Unclick() *gomock.Call {
function NewMockDriver (line 25) | func NewMockDriver(ctrl *gomock.Controller) *MockDriver {
FILE: pkg/mock_evdeviterator_test.go
type MockEvdevIterator (line 14) | type MockEvdevIterator struct
method EXPECT (line 32) | func (m *MockEvdevIterator) EXPECT() *MockEvdevIteratorMockRecorder {
method Close (line 37) | func (m *MockEvdevIterator) Close() error {
method Current (line 51) | func (m *MockEvdevIterator) Current() EvdevEvent {
method Next (line 65) | func (m *MockEvdevIterator) Next() bool {
type MockEvdevIteratorMockRecorder (line 20) | type MockEvdevIteratorMockRecorder struct
method Close (line 45) | func (mr *MockEvdevIteratorMockRecorder) Close() *gomock.Call {
method Current (line 59) | func (mr *MockEvdevIteratorMockRecorder) Current() *gomock.Call {
method Next (line 73) | func (mr *MockEvdevIteratorMockRecorder) Next() *gomock.Call {
function NewMockEvdevIterator (line 25) | func NewMockEvdevIterator(ctrl *gomock.Controller) *MockEvdevIterator {
FILE: pkg/mock_positionscaler_test.go
type MockPositionScaler (line 14) | type MockPositionScaler struct
method EXPECT (line 32) | func (m *MockPositionScaler) EXPECT() *MockPositionScalerMockRecorder {
method ScalePosition (line 37) | func (m *MockPositionScaler) ScalePosition(arg0, arg1 int) (int, int) {
type MockPositionScalerMockRecorder (line 20) | type MockPositionScalerMockRecorder struct
method ScalePosition (line 46) | func (mr *MockPositionScalerMockRecorder) ScalePosition(arg0, arg1 int...
function NewMockPositionScaler (line 25) | func NewMockPositionScaler(ctrl *gomock.Controller) *MockPositionScaler {
FILE: pkg/mock_readcloser_test.go
type MockReadCloser (line 14) | type MockReadCloser struct
method EXPECT (line 32) | func (m *MockReadCloser) EXPECT() *MockReadCloserMockRecorder {
method Close (line 37) | func (m *MockReadCloser) Close() error {
method Read (line 51) | func (m *MockReadCloser) Read(arg0 []byte) (int, error) {
type MockReadCloserMockRecorder (line 20) | type MockReadCloserMockRecorder struct
method Close (line 45) | func (mr *MockReadCloserMockRecorder) Close() *gomock.Call {
method Read (line 60) | func (mr *MockReadCloserMockRecorder) Read(arg0 interface{}) *gomock.C...
function NewMockReadCloser (line 25) | func NewMockReadCloser(ctrl *gomock.Controller) *MockReadCloser {
FILE: pkg/mock_statemachine_test.go
type MockStateMachine (line 14) | type MockStateMachine struct
method EXPECT (line 32) | func (m *MockStateMachine) EXPECT() *MockStateMachineMockRecorder {
method Close (line 37) | func (m *MockStateMachine) Close() error {
method Current (line 51) | func (m *MockStateMachine) Current() StateChange {
method Next (line 65) | func (m *MockStateMachine) Next() bool {
type MockStateMachineMockRecorder (line 20) | type MockStateMachineMockRecorder struct
method Close (line 45) | func (mr *MockStateMachineMockRecorder) Close() *gomock.Call {
method Current (line 59) | func (mr *MockStateMachineMockRecorder) Current() *gomock.Call {
method Next (line 73) | func (mr *MockStateMachineMockRecorder) Next() *gomock.Call {
function NewMockStateMachine (line 25) | func NewMockStateMachine(ctrl *gomock.Controller) *MockStateMachine {
FILE: pkg/positionscaler.go
constant DefaultTabletHeight (line 26) | DefaultTabletHeight = 15725
constant DefaultTabletWidth (line 35) | DefaultTabletWidth = 20967
type RightPositionScaler (line 40) | type RightPositionScaler struct
method ScalePosition (line 48) | func (s *RightPositionScaler) ScalePosition(x int, y int) (int, int) {
type LeftPositionScaler (line 63) | type LeftPositionScaler struct
method ScalePosition (line 71) | func (s *LeftPositionScaler) ScalePosition(x int, y int) (int, int) {
type VerticalPositionScaler (line 88) | type VerticalPositionScaler struct
method ScalePosition (line 96) | func (s *VerticalPositionScaler) ScalePosition(x int, y int) (int, int) {
FILE: pkg/positionscaler_test.go
function TestRightPositionScaler_ScalePosition (line 23) | func TestRightPositionScaler_ScalePosition(t *testing.T) {
function TestLeftPositionScaler_ScalePosition (line 102) | func TestLeftPositionScaler_ScalePosition(t *testing.T) {
function TestVerticalPositionScaler_ScalePosition (line 181) | func TestVerticalPositionScaler_ScalePosition(t *testing.T) {
FILE: pkg/runtime.go
type Runtime (line 20) | type Runtime struct
method Next (line 28) | func (r *Runtime) Next() bool {
method Close (line 72) | func (r *Runtime) Close() error {
FILE: pkg/runtime_test.go
function TestRuntimeEmptyStateMachine (line 25) | func TestRuntimeEmptyStateMachine(t *testing.T) {
function TestRuntimeStopsInErrorState (line 44) | func TestRuntimeStopsInErrorState(t *testing.T) {
type badStateChange (line 63) | type badStateChange struct
method Type (line 65) | func (*badStateChange) Type() string { return "unknown" }
function TestRuntimeErrorsOnUnknownStateChanges (line 67) | func TestRuntimeErrorsOnUnknownStateChanges(t *testing.T) {
function TestRuntimeHandlesMove (line 86) | func TestRuntimeHandlesMove(t *testing.T) {
function TestRuntimeHandlesDrag (line 114) | func TestRuntimeHandlesDrag(t *testing.T) {
function TestRuntimeHandlesClick (line 142) | func TestRuntimeHandlesClick(t *testing.T) {
function TestRuntimeHandlesUnclick (line 168) | func TestRuntimeHandlesUnclick(t *testing.T) {
FILE: pkg/statemachine.go
type EvdevStateMachine (line 18) | type EvdevStateMachine struct
method next (line 31) | func (it *EvdevStateMachine) next(raw EvdevEvent) bool {
method Next (line 65) | func (it *EvdevStateMachine) Next() bool {
method Current (line 76) | func (it *EvdevStateMachine) Current() StateChange {
method Close (line 81) | func (it *EvdevStateMachine) Close() error {
type DraggingEvdevStateMachine (line 85) | type DraggingEvdevStateMachine struct
method next (line 91) | func (it *DraggingEvdevStateMachine) next(raw EvdevEvent) bool {
method Next (line 107) | func (it *DraggingEvdevStateMachine) Next() bool {
FILE: pkg/statemachine_test.go
function TestStateMachineEmptyIterator (line 24) | func TestStateMachineEmptyIterator(t *testing.T) {
function TestEvdevStateMachine_next (line 41) | func TestEvdevStateMachine_next(t *testing.T) {
function TestDraggingEvdevStateMachine_next (line 356) | func TestDraggingEvdevStateMachine_next(t *testing.T) {
Condensed preview — 92 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (874K chars).
[
{
"path": ".devcontainer/Containerfile",
"chars": 821,
"preview": "FROM docker.io/golang:1-bookworm\n\nRUN apt-get update && apt-get install --yes \\\n curl wget gpg \\\n make git vim les"
},
{
"path": ".devcontainer/devcontainer.json",
"chars": 1198,
"preview": "{\n \"name\": \"remouseable\",\n \"build\": {\n \"dockerfile\": \"Containerfile\",\n \"context\": \"..\"\n },\n \"r"
},
{
"path": ".github/workflows/pr-workflow.yaml",
"chars": 2028,
"preview": "name: Pull Request Checks\n\non:\n pull_request:\n branches:\n - \"**\"\n workflow_dispatch: {}\n\njobs:\n tests:\n na"
},
{
"path": ".github/workflows/tag-workflow.yaml",
"chars": 2157,
"preview": "name: Build Linux/Windows\n\non:\n release:\n types:\n - published\n workflow_dispatch: {}\n\npermissions:\n contents:"
},
{
"path": ".gitignore",
"chars": 15503,
"preview": "\n# Created by https://www.gitignore.io/api/go,vim,osx,node,linux,emacs,python,windows,intellij,jetbrains,sublimetext,vis"
},
{
"path": ".golangci.errcheck.ignore",
"chars": 0,
"preview": ""
},
{
"path": ".golangci.yaml",
"chars": 8123,
"preview": "# options for analysis running\nrun:\n # timeout for analysis, e.g. 30s, 5m, default is 1m\n deadline: 1m\n\n # exit code "
},
{
"path": ".travis.yml",
"chars": 1741,
"preview": "language: go\ngo:\n - 1.14.x\nservices:\n - xvfb\naddons:\n homebrew:\n update: true\n packages:\n - go@1.14\n "
},
{
"path": "LICENSE",
"chars": 35149,
"preview": " GNU GENERAL PUBLIC LICENSE\n Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
},
{
"path": "Makefile",
"chars": 4589,
"preview": ".PHONY : update updatetools tools\n.PHONY : lint test integration coverage\n.PHONY : build\n.PHONY : clean cleancoverage cl"
},
{
"path": "README.md",
"chars": 18636,
"preview": "# reMouseable\n\n> Use your reMarkable tablet as a mouse.\n\n- [reMouseable](#remouseable)\n - [Update From September 19, 20"
},
{
"path": "go.mod",
"chars": 424,
"preview": "module github.com/kevinconway/remouseable\n\ngo 1.23\n\nrequire (\n\tgithub.com/dave/jennifer v1.7.1\n\tgithub.com/golang/mock v"
},
{
"path": "go.sum",
"chars": 4199,
"preview": "github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo=\ngithub.com/dave/jennifer v1.7.1/go.mod h"
},
{
"path": "main.go",
"chars": 6287,
"preview": "// This file is part of remouseable.\n//\n// remouseable is free software: you can redistribute it and/or modify\n// it und"
},
{
"path": "pkg/domain.go",
"chars": 4524,
"preview": "// This file is part of remouseable.\n//\n// remouseable is free software: you can redistribute it and/or modify\n// it und"
},
{
"path": "pkg/driver.go",
"chars": 1823,
"preview": "// This file is part of remouseable.\n//\n// remouseable is free software: you can redistribute it and/or modify\n// it und"
},
{
"path": "pkg/evdevcodes.go",
"chars": 42647,
"preview": "package remouseable\n\n// Code generated DO NOT EDIT\n\n// Generated using Linux 5.0.0-31-generic x86_64.\n// Generated at 20"
},
{
"path": "pkg/evdeviterator.go",
"chars": 3700,
"preview": "// This file is part of remouseable.\n//\n// remouseable is free software: you can redistribute it and/or modify\n// it und"
},
{
"path": "pkg/evdeviterator_test.go",
"chars": 4770,
"preview": "// This file is part of remouseable.\n//\n// remouseable is free software: you can redistribute it and/or modify\n// it und"
},
{
"path": "pkg/gen.go",
"chars": 910,
"preview": "package remouseable\n\n//go:generate mockgen -destination mock_driver_test.go -package remouseable -self_package github.co"
},
{
"path": "pkg/internal/gen.go",
"chars": 239,
"preview": "package internal\n\nimport (\n\t// Force a nimport of mock so that it guarantees that the mock package\n\t// will be included "
},
{
"path": "pkg/internal/gencodes/main.go",
"chars": 8254,
"preview": "// This file is part of remouseable.\n//\n// remouseable is free software: you can redistribute it and/or modify\n// it und"
},
{
"path": "pkg/internal/robotgo/base/LICENSE",
"chars": 1155,
"preview": "The software is licensed under the terms of the MIT license.\n\nCopyright 2010 Michael Sanders, AE and the go-vgo Project "
},
{
"path": "pkg/internal/robotgo/base/MMBitmap.h",
"chars": 3414,
"preview": "#pragma once\n#ifndef MMBITMAP_H\n#define MMBITMAP_H\n\n#include \"types.h\"\n#include \"rgb.h\"\n#include <assert.h>\n// #include "
},
{
"path": "pkg/internal/robotgo/base/MMBitmap_c.h",
"chars": 2352,
"preview": "#include \"MMBitmap.h\"\n#include <assert.h>\n#include <string.h>\n\n\n//MMBitmapRef createMMBitmap()\nMMBitmapRef createMMBitma"
},
{
"path": "pkg/internal/robotgo/base/MMPointArray.h",
"chars": 1072,
"preview": "#pragma once\n#ifndef MMARRAY_H\n#define MMARRAY_H\n\n#include \"types.h\"\n\nstruct _MMPointArray {\n\tMMPoint *array; /* Pointer"
},
{
"path": "pkg/internal/robotgo/base/MMPointArray_c.h",
"chars": 1098,
"preview": "#include \"MMPointArray.h\"\n#include <stdlib.h>\n\nMMPointArrayRef createMMPointArray(size_t initialCount)\n{\n\tMMPointArrayRe"
},
{
"path": "pkg/internal/robotgo/base/UTHashTable.h",
"chars": 3019,
"preview": "#pragma once\n#ifndef UTHASHTABLE_H\n#define UTHASHTABLE_H\n\n#include <stddef.h>\n#include \"uthash.h\"\n\n/* All node structs m"
},
{
"path": "pkg/internal/robotgo/base/UTHashTable_c.h",
"chars": 1641,
"preview": "#include \"UTHashTable.h\"\n#include <stdlib.h>\n#include <assert.h>\n\n/* Base struct class (all nodes must contain at least "
},
{
"path": "pkg/internal/robotgo/base/base64.c",
"chars": 3533,
"preview": "#include \"base64.h\"\n#include <string.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <assert.h>\n\n/* Encoding table as"
},
{
"path": "pkg/internal/robotgo/base/base64.h",
"chars": 1009,
"preview": "#pragma once\n#ifndef BASE64_H\n#define BASE64_H\n\n#include <stddef.h>\n\n#if defined(_MSC_VER)\n\t#include \"ms_stdint.h\"\n#else"
},
{
"path": "pkg/internal/robotgo/base/base64_c.h",
"chars": 3535,
"preview": "#include \"base64.h\"\n#include <string.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <assert.h>\n\n/* Encoding table as"
},
{
"path": "pkg/internal/robotgo/base/bmp_io.h",
"chars": 1884,
"preview": "#pragma once\n#ifndef BMP_IO_H\n#define BMP_IO_H\n\n#include \"MMBitmap.h\"\n#include \"file_io.h\"\n\nenum _BMPReadError {\n\tkBMPGe"
},
{
"path": "pkg/internal/robotgo/base/bmp_io_c.h",
"chars": 14043,
"preview": "#include \"bmp_io.h\"\n#include \"os.h\"\n#include \"endian.h\"\n#include <stdio.h> /* fopen() */\n#include <string.h> /* memcpy()"
},
{
"path": "pkg/internal/robotgo/base/color_find.h",
"chars": 2108,
"preview": "#pragma once\n#ifndef COLOR_FIND_H\n#define COLOR_FIND_H\n\n#include \"MMBitmap.h\"\n#include \"MMPointArray.h\"\n\n/* Convenience "
},
{
"path": "pkg/internal/robotgo/base/color_find_c.h",
"chars": 1679,
"preview": "#include \"color_find.h\"\n// #include \"../screen/screen_init.h\"\n#include <stdlib.h>\n\n/* Abstracted, general function to av"
},
{
"path": "pkg/internal/robotgo/base/deadbeef_rand.h",
"chars": 1090,
"preview": "#ifndef DEADBEEF_RAND_H\n#define DEADBEEF_RAND_H\n\n#include <stdint.h>\n\n#define DEADBEEF_MAX UINT32_MAX\n\n/* Dead Beef Rand"
},
{
"path": "pkg/internal/robotgo/base/deadbeef_rand_c.h",
"chars": 690,
"preview": "#include \"deadbeef_rand.h\"\n#include <time.h>\n\nstatic uint32_t deadbeef_seed;\nstatic uint32_t deadbeef_beef = 0xdeadbeef;"
},
{
"path": "pkg/internal/robotgo/base/endian.h",
"chars": 3823,
"preview": "#pragma once\n#ifndef ENDIAN_H\n#define ENDIAN_H\n\n#include \"os.h\"\n\n/*\n * (Mostly) cross-platform endian definitions and bi"
},
{
"path": "pkg/internal/robotgo/base/file_io.h",
"chars": 1418,
"preview": "#pragma once\n#ifndef FILE_IO_H\n#define FILE_IO_H\n\n#include \"MMBitmap.h\"\n#include <stddef.h>\n#include <stdint.h>\n\n\nenum _"
},
{
"path": "pkg/internal/robotgo/base/file_io_c.h",
"chars": 1671,
"preview": "#include \"file_io.h\"\n// #include \"os.h\"\n// #include \"bmp_io_c.h\"\n#include \"png_io_c.h\"\n#include <stdio.h> /* For fputs()"
},
{
"path": "pkg/internal/robotgo/base/inline_keywords.h",
"chars": 488,
"preview": "#pragma once\n\n/* A complicated, portable model for declaring inline functions in\n * header files. */\n#if !defined(H_INLI"
},
{
"path": "pkg/internal/robotgo/base/io.c",
"chars": 1661,
"preview": "#include \"file_io.h\"\n#include \"os.h\"\n#include \"bmp_io.h\"\n#include \"png_io.h\"\n#include <stdio.h> /* For fputs() */\n#inclu"
},
{
"path": "pkg/internal/robotgo/base/microsleep.h",
"chars": 1158,
"preview": "#pragma once\n#ifndef MICROSLEEP_H\n#define MICROSLEEP_H\n\n#include \"os.h\"\n#include \"inline_keywords.h\"\n\n#if !defined(IS_WI"
},
{
"path": "pkg/internal/robotgo/base/ms_stdbool.h",
"chars": 536,
"preview": "#pragma once\n#if !defined(MS_STDBOOL_H) && \\\n\t(!defined(__bool_true_false_are_defined) || __bool_true_false_are_defined)"
},
{
"path": "pkg/internal/robotgo/base/ms_stdint.h",
"chars": 6934,
"preview": "/* ISO C9x compliant stdint.h for Microsoft Visual Studio\n * Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG"
},
{
"path": "pkg/internal/robotgo/base/os.h",
"chars": 1515,
"preview": "#pragma once\n#ifndef OS_H\n#define OS_H\n\n/* Python versions under 2.5 don't support this macro, but it's not\n * terribly "
},
{
"path": "pkg/internal/robotgo/base/pasteboard.h",
"chars": 661,
"preview": "#pragma once\n#ifndef PASTEBOARD_H\n#define PASTEBOARD_H\n\n#include \"MMBitmap.h\"\n#include \"file_io.h\"\n\nenum _MMBitmapPasteE"
},
{
"path": "pkg/internal/robotgo/base/pasteboard_c.h",
"chars": 2587,
"preview": "#include \"pasteboard.h\"\n#include \"os.h\"\n\n#if defined(IS_MACOSX)\n\t#include \"png_io.h\"\n\t#include <ApplicationServices/Appl"
},
{
"path": "pkg/internal/robotgo/base/png_io.h",
"chars": 1192,
"preview": "#pragma once\n#ifndef PNG_IO_H\n#define PNG_IO_H\n\n// #include \"MMBitmap_c.h\"\n// #include \"file_io_c.h\"\n\nenum _PNGReadError"
},
{
"path": "pkg/internal/robotgo/base/png_io_c.h",
"chars": 9238,
"preview": "#include \"png_io.h\"\n#include \"os.h\"\n// #include \"libpng/png.c\"\n#if defined(IS_MACOSX)\n\t#include \"../cdeps/mac/png.h\"\n#el"
},
{
"path": "pkg/internal/robotgo/base/rgb.h",
"chars": 3455,
"preview": "#pragma once\n#ifndef RGB_H\n#define RGB_H\n\n#include <stdlib.h> /* For abs() */\n#include <math.h>\n#include \"inline_keyword"
},
{
"path": "pkg/internal/robotgo/base/snprintf.h",
"chars": 1181,
"preview": "#ifndef _PORTABLE_SNPRINTF_H_\n#define _PORTABLE_SNPRINTF_H_\n\n#define PORTABLE_SNPRINTF_VERSION_MAJOR 2\n#define PORTABLE_"
},
{
"path": "pkg/internal/robotgo/base/snprintf_c.h",
"chars": 41584,
"preview": "/*\n * snprintf.c - a portable implementation of snprintf\n *\n * AUTHOR\n * Mark Martinec <mark.martinec@ijs.si>, April 1"
},
{
"path": "pkg/internal/robotgo/base/str_io.h",
"chars": 1700,
"preview": "#pragma once\n#ifndef STR_IO_H\n#define STR_IO_H\n\n#include \"MMBitmap.h\"\n#include \"file_io.h\"\n#include <stdint.h>\n\n\nenum _M"
},
{
"path": "pkg/internal/robotgo/base/str_io_c.h",
"chars": 5842,
"preview": "#include \"str_io.h\"\n#include \"zlib_util_c.h\"\n#include \"base64_c.h\"\n#include \"snprintf_c.h\" /* snprintf() */\n#include <st"
},
{
"path": "pkg/internal/robotgo/base/types.h",
"chars": 2191,
"preview": "#pragma once\n#ifndef TYPES_H\n#define TYPES_H\n\n#include \"os.h\"\n#include \"inline_keywords.h\" /* For H_INLINE */\n#include <"
},
{
"path": "pkg/internal/robotgo/base/uthash.h",
"chars": 62091,
"preview": "/*\n * Copyright (c) 2003-2009, Troy D. Hanson http://uthash.sourceforge.net\n * All rights reserved.\n *\n * Redistribu"
},
{
"path": "pkg/internal/robotgo/base/xdisplay.h",
"chars": 638,
"preview": "#pragma once\n#ifndef XDISPLAY_H\n#define XDISPLAY_H\n\n#include <X11/Xlib.h>\n\n/* Returns the main display, closed either on"
},
{
"path": "pkg/internal/robotgo/base/xdisplay_c.h",
"chars": 1093,
"preview": "#include \"xdisplay.h\"\n#include <stdio.h> /* For fputs() */\n#include <stdlib.h> /* For atexit() */\n\nstatic Display *mainD"
},
{
"path": "pkg/internal/robotgo/base/zlib_util.h",
"chars": 989,
"preview": "#pragma once\n#ifndef ZLIB_UTIL_H\n#define ZLIB_UTIL_H\n\n#include <stddef.h>\n\n#if defined(_MSC_VER)\n\t#include \"ms_stdint.h\""
},
{
"path": "pkg/internal/robotgo/base/zlib_util_c.h",
"chars": 2396,
"preview": "#include \"zlib_util.h\"\n#include <zlib.h>\n#include <stdio.h> /* fprintf() */\n#include <stdlib.h> /* malloc() */\n#include "
},
{
"path": "pkg/internal/robotgo/mouse/goMouse.h",
"chars": 2213,
"preview": "// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT\n// file at the top-level directory of this distributi"
},
{
"path": "pkg/internal/robotgo/mouse/mouse.h",
"chars": 2731,
"preview": "#pragma once\n#ifndef MOUSE_H\n#define MOUSE_H\n\n#include \"../base/os.h\"\n#include \"../base/types.h\"\n\n#if defined(_MSC_VER)\n"
},
{
"path": "pkg/internal/robotgo/mouse/mouse_c.h",
"chars": 12805,
"preview": "#include \"mouse.h\"\n#include \"../base/deadbeef_rand_c.h\"\n#include \"../base/microsleep.h\"\n\n#include <math.h> /* For floor("
},
{
"path": "pkg/internal/robotgo/robotgo.go",
"chars": 7331,
"preview": "// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT\n// file at the top-level directory of this distributi"
},
{
"path": "pkg/internal/robotgo/screen/goScreen.h",
"chars": 1117,
"preview": "// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT\n// file at the top-level directory of this distributi"
},
{
"path": "pkg/internal/robotgo/screen/screen.h",
"chars": 500,
"preview": "#pragma once\n#ifndef SCREEN_H\n#define SCREEN_H\n\n#include \"../base/types.h\"\n\n#if defined(_MSC_VER)\n#include \"../base/ms_s"
},
{
"path": "pkg/internal/robotgo/screen/screen_c.h",
"chars": 1138,
"preview": "#include \"screen.h\"\n\n#if defined(IS_MACOSX)\n#include <ApplicationServices/ApplicationServices.h>\n#elif defined(USE_X11)\n"
},
{
"path": "pkg/internal/robotgo/window/arr.h",
"chars": 74,
"preview": "struct Arr\n{\n int len;\n int cnu;\n char **pName;\n int *pId;\n};\n"
},
{
"path": "pkg/internal/robotgo/window/goWindow.h",
"chars": 2505,
"preview": "// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT\n// file at the top-level directory of this distributi"
},
{
"path": "pkg/internal/robotgo/window/process.h",
"chars": 2948,
"preview": "// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT\n// file at the top-level directory of this distributi"
},
{
"path": "pkg/internal/robotgo/window/pub.h",
"chars": 7412,
"preview": "// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT\n// file at the top-level directory of this distributi"
},
{
"path": "pkg/internal/robotgo/window/win32.h",
"chars": 1325,
"preview": "// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT\n// file at the top-level directory of this distributi"
},
{
"path": "pkg/internal/robotgo/window/win_sys.h",
"chars": 4378,
"preview": "// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT\n// file at the top-level directory of this distributi"
},
{
"path": "pkg/internal/robotgo/window/window.h",
"chars": 15163,
"preview": "// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT\n// file at the top-level directory of this distributi"
},
{
"path": "pkg/mock_driver_test.go",
"chars": 3143,
"preview": "// Code generated by MockGen. DO NOT EDIT.\n// Source: github.com/kevinconway/remouseable/pkg (interfaces: Driver)\n\n// Pa"
},
{
"path": "pkg/mock_evdeviterator_test.go",
"chars": 2242,
"preview": "// Code generated by MockGen. DO NOT EDIT.\n// Source: github.com/kevinconway/remouseable/pkg (interfaces: EvdevIterator)"
},
{
"path": "pkg/mock_positionscaler_test.go",
"chars": 1573,
"preview": "// Code generated by MockGen. DO NOT EDIT.\n// Source: github.com/kevinconway/remouseable/pkg (interfaces: PositionScaler"
},
{
"path": "pkg/mock_readcloser_test.go",
"chars": 1778,
"preview": "// Code generated by MockGen. DO NOT EDIT.\n// Source: io (interfaces: ReadCloser)\n\n// Package remouseable is a generated"
},
{
"path": "pkg/mock_statemachine_test.go",
"chars": 2219,
"preview": "// Code generated by MockGen. DO NOT EDIT.\n// Source: github.com/kevinconway/remouseable/pkg (interfaces: StateMachine)\n"
},
{
"path": "pkg/positionscaler.go",
"chars": 5528,
"preview": "// This file is part of remouseable.\n//\n// remouseable is free software: you can redistribute it and/or modify\n// it und"
},
{
"path": "pkg/positionscaler_test.go",
"chars": 4880,
"preview": "// This file is part of remouseable.\n//\n// remouseable is free software: you can redistribute it and/or modify\n// it und"
},
{
"path": "pkg/runtime.go",
"chars": 2117,
"preview": "// This file is part of remouseable.\n//\n// remouseable is free software: you can redistribute it and/or modify\n// it und"
},
{
"path": "pkg/runtime_test.go",
"chars": 5043,
"preview": "// This file is part of remouseable.\n//\n// remouseable is free software: you can redistribute it and/or modify\n// it und"
},
{
"path": "pkg/statemachine.go",
"chars": 2984,
"preview": "// This file is part of remouseable.\n//\n// remouseable is free software: you can redistribute it and/or modify\n// it und"
},
{
"path": "pkg/statemachine_test.go",
"chars": 16419,
"preview": "// This file is part of remouseable.\n//\n// remouseable is free software: you can redistribute it and/or modify\n// it und"
},
{
"path": "technical-documentation/README.md",
"chars": 29091,
"preview": "# reMouseable Design Documentation\n\nThis document details how reMouseable works, the rationale for the software\ndesign c"
},
{
"path": "technical-documentation/static-assets/diagrams.puml",
"chars": 1525,
"preview": "@startuml remouseable_overview\n\nnode \"reMarkable Tablet\" as tablet {\n folder \"Linux\" as linux {\n component \"Ev"
},
{
"path": "tools/go.mod",
"chars": 39368,
"preview": "module github.com/kevinconway/remouseable/tools\n\ngo 1.22.1\n\ntoolchain go1.23.1\n\nrequire (\n\tgithub.com/AlekSi/gocov-xml v"
},
{
"path": "tools/go.sum",
"chars": 287903,
"preview": "4d63.com/gocheckcompilerdirectives v1.2.1 h1:AHcMYuw56NPjq/2y615IGg2kYkBdTvOaojYCBcRE7MA=\n4d63.com/gocheckcompilerdirect"
},
{
"path": "tools/tools.go",
"chars": 287,
"preview": "package tools\n\nimport (\n\t_ \"github.com/AlekSi/gocov-xml\"\n\t_ \"github.com/axw/gocov/gocov\"\n\t_ \"github.com/golang/mock/mock"
}
]
About this extraction
This page contains the full source code of the kevinconway/remouseable GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 92 files (815.3 KB), approximately 307.3k tokens, and a symbol index with 1118 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.