You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
5.3 KiB
Rust
190 lines
5.3 KiB
Rust
mod types;
|
|
mod config;
|
|
mod maps;
|
|
mod lua_config;
|
|
|
|
extern crate x11;
|
|
|
|
use x11::xlib;
|
|
use x11::xtest;
|
|
|
|
use std::mem;
|
|
use std::ffi::{CStr, CString};
|
|
use std::ptr::null;
|
|
use x11::xlib::{AnyModifier, ButtonPress, ButtonRelease, ButtonReleaseMask, ButtonPressMask, GrabModeAsync, RevertToNone, BadCursor, XEvent, xError, XAnyEvent, xEvent, Display, XKeyEvent, InputFocus, KeyPress, KeyRelease, KeyPressMask, KeyReleaseMask, XButtonEvent, CurrentTime, Button1Mask, Button2Mask, Window};
|
|
use std::io::Cursor;
|
|
use x11::xinput2::XINotifyDetailNone;
|
|
use crate::types::{Bind, Action, Handler};
|
|
use std::os::raw::c_long;
|
|
use std::collections::HashMap;
|
|
use crate::types::Bind::{Key, Mouse};
|
|
|
|
struct XInfo {
|
|
root: u64,
|
|
display: *mut Display,
|
|
}
|
|
|
|
struct Subscription {
|
|
on: Bind,
|
|
handler: Handler,
|
|
}
|
|
|
|
impl Subscription {
|
|
pub fn subscribe(&self, xinfo: &XInfo) {
|
|
unsafe {
|
|
match self.on {
|
|
Bind::Key(key) => {
|
|
xlib::XGrabKey(xinfo.display, key as i32, AnyModifier, xinfo.root, 0, GrabModeAsync, GrabModeAsync);
|
|
}
|
|
|
|
Bind::Mouse(button) => {
|
|
xlib::XGrabButton(xinfo.display, button, AnyModifier, xinfo.root, 0, (ButtonReleaseMask | ButtonPressMask) as u32, GrabModeAsync, GrabModeAsync, xinfo.root, 0);
|
|
}
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn unsubscribe(&self, xinfo: &XInfo) {
|
|
unsafe {
|
|
match self.on {
|
|
Bind::Key(key) => {
|
|
xlib::XUngrabKey(xinfo.display, key as i32, AnyModifier, xinfo.root);
|
|
}
|
|
|
|
Bind::Mouse(button) => {
|
|
xlib::XUngrabButton(xinfo.display, button, AnyModifier, xinfo.root);
|
|
}
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn handle(&self, pressed: bool, xinfo: &XInfo, coords: Target) {
|
|
println!("Handling trigger={:?} pressed={:?} action={:?}", self.on, pressed, self.handler.action);
|
|
|
|
match &self.handler.action {
|
|
Action::Sync(bind) => {
|
|
match bind {
|
|
Bind::Key(key) => {
|
|
unsafe {
|
|
xtest::XTestFakeKeyEvent(xinfo.display, *key, pressed as i32, CurrentTime);
|
|
}
|
|
}
|
|
|
|
Bind::Mouse(key) => {
|
|
unsafe {
|
|
xtest::XTestFakeButtonEvent(xinfo.display, *key, pressed as i32, CurrentTime);
|
|
}
|
|
}
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
let config = lua_config::load_config("\
|
|
|
|
# sync up keys with others
|
|
# tables defined in maps.rs
|
|
# manual key codes can be given via k.n() or m.n()
|
|
sync(k.n(52), m.left)\
|
|
\
|
|
").unwrap();
|
|
|
|
let display = unsafe { xlib::XOpenDisplay(null()) };
|
|
let root = unsafe { xlib::XDefaultRootWindow(display) };
|
|
|
|
unsafe { xtest::XTestGrabControl(display, true as i32) };
|
|
|
|
let xinfo = XInfo { display, root };
|
|
|
|
let mut subs: HashMap<Bind, Subscription> = HashMap::new();
|
|
|
|
for (bind, handler) in config.binds.iter() {
|
|
let sub = Subscription { handler: (*handler).clone(), on: (*bind).clone() };
|
|
sub.subscribe(&xinfo);
|
|
subs.insert((*bind).clone(), sub);
|
|
}
|
|
|
|
let mut event: xlib::XEvent = unsafe { mem::MaybeUninit::uninit().assume_init() };
|
|
loop {
|
|
unsafe { xlib::XNextEvent(display, &mut event); }
|
|
match event.get_type() {
|
|
xlib::KeyPress => {
|
|
let key = Key(unsafe { event.key.keycode });
|
|
if let Some(sub) = subs.get(&key) {
|
|
sub.handle(true, &xinfo, unsafe { event.key.to_coords() });
|
|
}
|
|
}
|
|
|
|
xlib::KeyRelease => {
|
|
let key = Key(unsafe { event.key.keycode });
|
|
if let Some(sub) = subs.get(&key) {
|
|
sub.handle(false, &xinfo, unsafe { event.key.to_coords() });
|
|
}
|
|
}
|
|
|
|
xlib::ButtonPress => {
|
|
let key = Mouse(unsafe { event.button.button });
|
|
if let Some(sub) = subs.get(&key) {
|
|
sub.handle(true, &xinfo, unsafe { event.button.to_coords() });
|
|
}
|
|
}
|
|
|
|
xlib::ButtonRelease => {
|
|
let key = Mouse(unsafe { event.button.button });
|
|
if let Some(sub) = subs.get(&key) {
|
|
sub.handle(false, &xinfo, unsafe { event.button.to_coords() });
|
|
}
|
|
}
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct Target {
|
|
x: i32,
|
|
y: i32,
|
|
x_root: i32,
|
|
y_root: i32,
|
|
window: Window,
|
|
subwindow: Window,
|
|
}
|
|
|
|
trait ToCoords {
|
|
fn to_coords(&self) -> Target;
|
|
}
|
|
|
|
impl ToCoords for XKeyEvent {
|
|
fn to_coords(&self) -> Target {
|
|
Target {
|
|
x: self.x,
|
|
y: self.y,
|
|
x_root: self.x_root,
|
|
y_root: self.y_root,
|
|
window: self.window,
|
|
subwindow: self.subwindow,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl ToCoords for XButtonEvent {
|
|
fn to_coords(&self) -> Target {
|
|
Target {
|
|
x: self.x,
|
|
y: self.y,
|
|
x_root: self.x_root,
|
|
y_root: self.y_root,
|
|
window: self.window,
|
|
subwindow: self.subwindow,
|
|
}
|
|
}
|
|
} |