Created
December 7, 2023 12:32
-
-
Save SkyaTura/3fd1959c7997206ca2dfce9804af2e2c to your computer and use it in GitHub Desktop.
Touch driver draft
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate enigo; | |
#[macro_use] | |
extern crate lazy_static; | |
use enigo::*; | |
use std::collections::HashMap; | |
use std::sync::Mutex; | |
lazy_static! { | |
static ref ENUM_MAP_COORDINATE: Mutex<HashMap<i8, Coordinate>> = { | |
let mut m = HashMap::new(); | |
m.insert(1, Coordinate::Abs); | |
m.insert(2, Coordinate::Rel); | |
Mutex::new(m) | |
}; | |
static ref ENUM_MAP_BUTTON: Mutex<HashMap<i8, Button>> = { | |
let mut m = HashMap::new(); | |
m.insert(1, Button::Left); | |
m.insert(2, Button::Middle); | |
m.insert(3, Button::Right); | |
Mutex::new(m) | |
}; | |
static ref ENUM_MAP_DIRECTION: Mutex<HashMap<i8, Direction>> = { | |
let mut m = HashMap::new(); | |
m.insert(1, Direction::Press); | |
m.insert(2, Direction::Release); | |
m.insert(3, Direction::Click); | |
Mutex::new(m) | |
}; | |
static ref ENUM_MAP_AXIS: Mutex<HashMap<i8, Axis>> = { | |
let mut m = HashMap::new(); | |
m.insert(1, Axis::Horizontal); | |
m.insert(2, Axis::Vertical); | |
Mutex::new(m) | |
}; | |
} | |
fn parse_coordinate(num: i8) -> Result<Coordinate, &'static str> { | |
let map = ENUM_MAP_COORDINATE.lock().unwrap(); | |
map.get(&num).cloned().ok_or("invalid enum variant") | |
} | |
fn parse_button(num: i8) -> Result<Button, &'static str> { | |
let map = ENUM_MAP_BUTTON.lock().unwrap(); | |
map.get(&num).cloned().ok_or("invalid enum variant") | |
} | |
fn parse_direction(num: i8) -> Result<Direction, &'static str> { | |
let map = ENUM_MAP_DIRECTION.lock().unwrap(); | |
map.get(&num).cloned().ok_or("invalid enum variant") | |
} | |
fn parse_axis(num: i8) -> Result<Axis, &'static str> { | |
let map = ENUM_MAP_AXIS.lock().unwrap(); | |
map.get(&num).cloned().ok_or("invalid enum variant") | |
} | |
#[no_mangle] | |
pub extern "C" fn move_mouse(x: i32, y: i32, coordinate: i8) -> bool { | |
let coordinate_enum = match parse_coordinate(coordinate) { | |
Ok(coord) => coord, | |
Err(_) => return false, | |
}; | |
let mut enigo = match Enigo::new(&Settings::default()) { | |
Ok(enigo) => enigo, | |
Err(_) => return false, | |
}; | |
enigo.move_mouse(x, y, coordinate_enum).is_ok() | |
} | |
#[no_mangle] | |
pub extern "C" fn button(button: i8, direction: i8) -> bool { | |
let button_enum = match parse_button(button) { | |
Ok(button) => button, | |
Err(_) => return false, | |
}; | |
let direction_enum = match parse_direction(direction) { | |
Ok(direction) => direction, | |
Err(_) => return false, | |
}; | |
let mut enigo = match Enigo::new(&Settings::default()) { | |
Ok(enigo) => enigo, | |
Err(_) => return false, | |
}; | |
enigo.button(button_enum, direction_enum).is_ok() | |
} | |
#[no_mangle] | |
pub extern "C" fn scroll(amount: i32, axis: i8) -> bool { | |
let axis_enum = match parse_axis(axis) { | |
Ok(axis) => axis, | |
Err(_) => return false, | |
}; | |
let mut enigo = match Enigo::new(&Settings::default()) { | |
Ok(enigo) => enigo, | |
Err(_) => return false, | |
}; | |
enigo.scroll(amount, axis_enum).is_ok() | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { dlopen, FFIType } from "bun:ffi"; | |
import path from "../libenigo_wrapper.dylib"; | |
// console.log('aaaa', path.replace('compiled://root/', './')) | |
// const path = '../libenigo_wrapper.dylib' | |
const lib = dlopen(path, { | |
move_mouse: { | |
args: [FFIType.i32, FFIType.i32, FFIType.i8], | |
returns: FFIType.bool, | |
}, | |
button: { | |
args: [FFIType.i8, FFIType.i8], | |
returns: FFIType.bool, | |
}, | |
scroll: { | |
args: [FFIType.i32, FFIType.i8], | |
returns: FFIType.bool, | |
}, | |
}) | |
// const lib = { | |
// symbols: { | |
// move_mouse: (x: number, y: number, coordinate: Coordinate) => true, | |
// button: (button: Button, direction: Direction) => true, | |
// scroll: (amount: number, axis: Axis) => true, | |
// } | |
// } | |
export const Coordinate = { | |
Abs: 1, | |
Rel: 2, | |
} | |
export type Coordinate = typeof Coordinate[keyof typeof Coordinate] | |
export const Button = { | |
Left: 1, | |
Middle: 2, | |
Right: 3, | |
} | |
export type Button = typeof Button[keyof typeof Button] | |
export const Axis = { | |
Vertical: 1, | |
Horizontal: 2, | |
} | |
export type Axis = typeof Axis[keyof typeof Axis] | |
export const Direction = { | |
Press: 1, | |
Release: 2, | |
Click: 3, | |
} | |
export type Direction = typeof Direction[keyof typeof Direction] | |
export const Enigo = { | |
moveMouse: (x: number, y: number, coordinate: Coordinate) => lib.symbols.move_mouse(x, y, coordinate), | |
button: (button: Button, direction: Direction) => lib.symbols.button(button, direction), | |
scroll: (amount: number, axis: Axis) => lib.symbols.scroll(amount, axis), | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { HID, devices as Devices } from 'node-hid' | |
import { Button, Direction, Enigo } from './enigo' | |
const DEBUG = false | |
const log = (...args: any[]) => { | |
if (!DEBUG) return | |
console.log(...args) | |
} | |
const TOUCH_DATA_HEADER = 1 | |
const TOUCH_DATA_LENGTH = 7 | |
const TOUCH_INDEX_STATE = 0 | |
const TOUCH_INDEX_X = 2 | |
const TOUCH_INDEX_Y = 4 | |
const TOUCH_CALIBRATION_X = 2046 | |
const TOUCH_CALIBRATION_Y = 2040 | |
const PRECISION = 1000 | |
const getCalibrated = (value: number, calibration: number) => Math.min(100, Math.max(0, Math.floor(value / calibration * PRECISION) / PRECISION)) | |
const readTouchData = (buffer: Buffer, finger = 0) => { | |
const offset = TOUCH_DATA_HEADER + finger + TOUCH_DATA_LENGTH * finger | |
const state = buffer.readInt8(offset + TOUCH_INDEX_STATE) === 1 | |
if (!state) return { state, xRaw: 0, yRaw: 0, xPos: 0, yPos: 0 } | |
const xRaw = buffer.readInt16LE(offset + TOUCH_INDEX_X) | |
const yRaw = buffer.readInt16LE(offset + TOUCH_INDEX_Y) | |
const xPos = getCalibrated(xRaw, TOUCH_CALIBRATION_X) | |
const yPos = getCalibrated(yRaw, TOUCH_CALIBRATION_Y) | |
return { state, xRaw, yRaw, xPos, yPos } | |
} | |
const devices = Devices() | |
const deviceMeta = devices.find(item => item.product === 'USB2IIC_CTP_CONTROL') | |
if (!deviceMeta?.path) { | |
console.error('device not found') | |
throw new Error('device not found') | |
} | |
const device = new HID(deviceMeta.path) | |
let state = false | |
let mouse = false | |
let canmove = true | |
let start: null | [number, number] = null | |
let canclick = true | |
let thread: null | symbol = null | |
const reset = () => { | |
state = false | |
mouse = false | |
canmove = true | |
start = null | |
canclick = true | |
thread = null | |
log('reseting states') | |
} | |
device.on('data', (data) => { | |
try { | |
const touchData = readTouchData(data, 0) | |
if (!touchData.state) { | |
if (state && canmove) { | |
log('touch finised') | |
if (canclick) { | |
if (mouse) { | |
Enigo.button(Button.Left, Direction.Release) | |
log('release') | |
} else { | |
Enigo.button(Button.Left, Direction.Click) | |
log('click') | |
} | |
} else { | |
log('no click') | |
} | |
} | |
reset() | |
return | |
} | |
if (!canmove) return | |
Enigo.moveMouse( | |
54 + touchData.xPos * 1920, | |
1333 + touchData.yPos * 1080, | |
1 | |
) | |
if (!mouse) { | |
const biggestDiff = !start ? 0 : Math.max( | |
Math.abs(touchData.xPos - start[0]), | |
Math.abs(touchData.yPos - start[1]) | |
) | |
if (biggestDiff > 0.1) { | |
// log(biggestDiff, start, touchData.xPos, touchData.yPos) | |
canclick = false | |
} | |
} | |
if (!canclick) return | |
if (!mouse) { | |
const touchData2 = readTouchData(data, 1) | |
// log(touchData2) | |
if (touchData2.state) { | |
log('right click') | |
canmove = false | |
Enigo.button(Button.Right, Direction.Click) | |
return | |
} | |
} | |
if (!state) { | |
state = true | |
start = [touchData.xPos, touchData.yPos] | |
const tid = Symbol() | |
thread = tid | |
log('touch started') | |
setTimeout(() => { | |
if (tid !== thread || !canclick) return | |
Enigo.button(Button.Left, Direction.Press) | |
mouse = true | |
thread = null | |
log('hold') | |
}, 400) | |
} | |
} catch (e) { | |
console.error(e) | |
} | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment