Format Rust code using rustfmt
This commit is contained in:
parent
94c7af7709
commit
91624c0ce0
6 changed files with 989 additions and 421 deletions
|
@ -1,9 +1,9 @@
|
||||||
|
use crate::udev_monitor::{Client, Environment, Server};
|
||||||
use crate::Config;
|
use crate::Config;
|
||||||
use crate::udev_monitor::{Client, Server, Environment};
|
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use swayipc_async::Connection;
|
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
use x11rb::protocol::xproto::{get_property, get_input_focus, Atom, AtomEnum};
|
use swayipc_async::Connection;
|
||||||
|
use x11rb::protocol::xproto::{get_input_focus, get_property, Atom, AtomEnum};
|
||||||
|
|
||||||
pub async fn get_active_window(environment: &Environment, config: &Vec<Config>) -> Client {
|
pub async fn get_active_window(environment: &Environment, config: &Vec<Config>) -> Client {
|
||||||
match &environment.server {
|
match &environment.server {
|
||||||
|
@ -11,10 +11,19 @@ pub async fn get_active_window(environment: &Environment, config: &Vec<Config>)
|
||||||
let server_str = server.as_str();
|
let server_str = server.as_str();
|
||||||
match server_str {
|
match server_str {
|
||||||
"Hyprland" => {
|
"Hyprland" => {
|
||||||
let query = Command::new("hyprctl").args(["activewindow", "-j"]).output().unwrap();
|
let query = Command::new("hyprctl")
|
||||||
if let Ok(reply) = serde_json::from_str::<serde_json::Value>(std::str::from_utf8(query.stdout.as_slice()).unwrap()) {
|
.args(["activewindow", "-j"])
|
||||||
let active_window = Client::Class(reply["class"].to_string().replace("\"", ""));
|
.output()
|
||||||
if let Some(_) = config.iter().find(|&x| x.associations.client == active_window) {
|
.unwrap();
|
||||||
|
if let Ok(reply) = serde_json::from_str::<serde_json::Value>(
|
||||||
|
std::str::from_utf8(query.stdout.as_slice()).unwrap(),
|
||||||
|
) {
|
||||||
|
let active_window =
|
||||||
|
Client::Class(reply["class"].to_string().replace("\"", ""));
|
||||||
|
if let Some(_) = config
|
||||||
|
.iter()
|
||||||
|
.find(|&x| x.associations.client == active_window)
|
||||||
|
{
|
||||||
active_window
|
active_window
|
||||||
} else {
|
} else {
|
||||||
Client::Default
|
Client::Default
|
||||||
|
@ -22,33 +31,37 @@ pub async fn get_active_window(environment: &Environment, config: &Vec<Config>)
|
||||||
} else {
|
} else {
|
||||||
Client::Default
|
Client::Default
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"sway" => {
|
"sway" => {
|
||||||
let mut connection = Connection::new().await.unwrap();
|
let mut connection = Connection::new().await.unwrap();
|
||||||
let active_window = match connection.get_tree().await.unwrap().find_focused(|window| window.focused) {
|
let active_window = match connection
|
||||||
Some(window) => {
|
.get_tree()
|
||||||
match window.app_id {
|
.await
|
||||||
Some(id) => Client::Class(id),
|
.unwrap()
|
||||||
None => Client::Class(window.window_properties.unwrap().class.unwrap())
|
.find_focused(|window| window.focused)
|
||||||
}
|
{
|
||||||
|
Some(window) => match window.app_id {
|
||||||
|
Some(id) => Client::Class(id),
|
||||||
|
None => Client::Class(window.window_properties.unwrap().class.unwrap()),
|
||||||
},
|
},
|
||||||
None => Client::Default
|
None => Client::Default,
|
||||||
};
|
};
|
||||||
if let Some(_) = config.iter().find(|&x| x.associations.client == active_window) {
|
if let Some(_) = config
|
||||||
|
.iter()
|
||||||
|
.find(|&x| x.associations.client == active_window)
|
||||||
|
{
|
||||||
active_window
|
active_window
|
||||||
} else {
|
} else {
|
||||||
Client::Default
|
Client::Default
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"KDE" => {
|
"KDE" => {
|
||||||
let (user, running_as_root) =
|
let (user, running_as_root) =
|
||||||
if let Ok(sudo_user) = environment.sudo_user.clone() {
|
if let Ok(sudo_user) = environment.sudo_user.clone() {
|
||||||
(Option::Some(sudo_user), true)
|
(Option::Some(sudo_user), true)
|
||||||
}
|
} else if let Ok(user) = environment.user.clone() {
|
||||||
else if let Ok(user) = environment.user.clone() {
|
|
||||||
(Option::Some(user), false)
|
(Option::Some(user), false)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
(Option::None, false)
|
(Option::None, false)
|
||||||
};
|
};
|
||||||
let active_window = {
|
let active_window = {
|
||||||
|
@ -60,7 +73,12 @@ pub async fn get_active_window(environment: &Environment, config: &Vec<Config>)
|
||||||
.arg("kdotool getactivewindow getwindowclassname")
|
.arg("kdotool getactivewindow getwindowclassname")
|
||||||
.output()
|
.output()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Client::Class(std::str::from_utf8(output.stdout.as_slice()).unwrap().trim().to_string())
|
Client::Class(
|
||||||
|
std::str::from_utf8(output.stdout.as_slice())
|
||||||
|
.unwrap()
|
||||||
|
.trim()
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
let output = Command::new("sh")
|
let output = Command::new("sh")
|
||||||
.arg("-c")
|
.arg("-c")
|
||||||
|
@ -68,46 +86,69 @@ pub async fn get_active_window(environment: &Environment, config: &Vec<Config>)
|
||||||
.stderr(Stdio::null())
|
.stderr(Stdio::null())
|
||||||
.output()
|
.output()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Client::Class(std::str::from_utf8(output.stdout.as_slice()).unwrap().trim().to_string())
|
Client::Class(
|
||||||
|
std::str::from_utf8(output.stdout.as_slice())
|
||||||
|
.unwrap()
|
||||||
|
.trim()
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Client::Default
|
Client::Default
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(_) = config.iter().find(|&x| x.associations.client == active_window) {
|
if let Some(_) = config
|
||||||
|
.iter()
|
||||||
|
.find(|&x| x.associations.client == active_window)
|
||||||
|
{
|
||||||
active_window
|
active_window
|
||||||
} else {
|
} else {
|
||||||
Client::Default
|
Client::Default
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"x11" => {
|
"x11" => {
|
||||||
let connection = x11rb::connect(None).unwrap().0;
|
let connection = x11rb::connect(None).unwrap().0;
|
||||||
let focused_window = get_input_focus(&connection)
|
let focused_window =
|
||||||
.unwrap().reply().unwrap().focus;
|
get_input_focus(&connection).unwrap().reply().unwrap().focus;
|
||||||
let (wm_class, string): (Atom, Atom) = (AtomEnum::WM_CLASS.into(), AtomEnum::STRING.into());
|
let (wm_class, string): (Atom, Atom) =
|
||||||
let class = get_property(&connection, false, focused_window, wm_class, string, 0, u32::MAX)
|
(AtomEnum::WM_CLASS.into(), AtomEnum::STRING.into());
|
||||||
.unwrap().reply().unwrap().value;
|
let class = get_property(
|
||||||
|
&connection,
|
||||||
|
false,
|
||||||
|
focused_window,
|
||||||
|
wm_class,
|
||||||
|
string,
|
||||||
|
0,
|
||||||
|
u32::MAX,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.reply()
|
||||||
|
.unwrap()
|
||||||
|
.value;
|
||||||
if let Some(middle) = class.iter().position(|&byte| byte == 0) {
|
if let Some(middle) = class.iter().position(|&byte| byte == 0) {
|
||||||
let class = class.split_at(middle).1;
|
let class = class.split_at(middle).1;
|
||||||
let mut class = &class[1..];
|
let mut class = &class[1..];
|
||||||
if class.last() == Some(&0) {
|
if class.last() == Some(&0) {
|
||||||
class = &class[..class.len() -1];
|
class = &class[..class.len() - 1];
|
||||||
}
|
}
|
||||||
let active_window = Client::Class(std::str::from_utf8(class).unwrap().to_string());
|
let active_window =
|
||||||
if let Some(_) = config.iter().find(|&x| x.associations.client == active_window) {
|
Client::Class(std::str::from_utf8(class).unwrap().to_string());
|
||||||
active_window
|
if let Some(_) = config
|
||||||
|
.iter()
|
||||||
|
.find(|&x| x.associations.client == active_window)
|
||||||
|
{
|
||||||
|
active_window
|
||||||
} else {
|
} else {
|
||||||
Client::Default
|
Client::Default
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Client::Default
|
Client::Default
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => Client::Default
|
_ => Client::Default,
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Server::Unsupported => Client::Default,
|
Server::Unsupported => Client::Default,
|
||||||
Server::Failed => Client::Default,
|
Server::Failed => Client::Default,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
110
src/config.rs
110
src/config.rs
|
@ -1,8 +1,7 @@
|
||||||
use std::{collections::HashMap, str::FromStr};
|
use crate::udev_monitor::Client;
|
||||||
use evdev::Key;
|
use evdev::Key;
|
||||||
use serde;
|
use serde;
|
||||||
use crate::udev_monitor::Client;
|
use std::{collections::HashMap, str::FromStr};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
|
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
|
@ -31,7 +30,7 @@ pub enum Axis {
|
||||||
BTN_TL2,
|
BTN_TL2,
|
||||||
BTN_TR2,
|
BTN_TR2,
|
||||||
ABS_WHEEL_CW,
|
ABS_WHEEL_CW,
|
||||||
ABS_WHEEL_CCW
|
ABS_WHEEL_CCW,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for Axis {
|
impl FromStr for Axis {
|
||||||
|
@ -92,10 +91,13 @@ pub struct RawConfig {
|
||||||
|
|
||||||
impl RawConfig {
|
impl RawConfig {
|
||||||
fn new_from_file(file: &str) -> Self {
|
fn new_from_file(file: &str) -> Self {
|
||||||
println!("Parsing config file:\n{:?}\n", file.rsplit_once("/").unwrap().1);
|
println!(
|
||||||
|
"Parsing config file:\n{:?}\n",
|
||||||
|
file.rsplit_once("/").unwrap().1
|
||||||
|
);
|
||||||
let file_content: String = std::fs::read_to_string(file).unwrap();
|
let file_content: String = std::fs::read_to_string(file).unwrap();
|
||||||
let raw_config: RawConfig = toml::from_str(&file_content)
|
let raw_config: RawConfig =
|
||||||
.expect("Couldn't parse config file.");
|
toml::from_str(&file_content).expect("Couldn't parse config file.");
|
||||||
let remap = raw_config.remap;
|
let remap = raw_config.remap;
|
||||||
let commands = raw_config.commands;
|
let commands = raw_config.commands;
|
||||||
let settings = raw_config.settings;
|
let settings = raw_config.settings;
|
||||||
|
@ -162,8 +164,10 @@ fn parse_raw_config(raw_config: RawConfig) -> (Bindings, HashMap<String, String>
|
||||||
all: Vec::new(),
|
all: Vec::new(),
|
||||||
};
|
};
|
||||||
let custom_modifiers: Vec<Event> = parse_modifiers(&settings, "CUSTOM_MODIFIERS");
|
let custom_modifiers: Vec<Event> = parse_modifiers(&settings, "CUSTOM_MODIFIERS");
|
||||||
let lstick_activation_modifiers: Vec<Event> = parse_modifiers(&settings, "LSTICK_ACTIVATION_MODIFIERS");
|
let lstick_activation_modifiers: Vec<Event> =
|
||||||
let rstick_activation_modifiers: Vec<Event> = parse_modifiers(&settings, "RSTICK_ACTIVATION_MODIFIERS");
|
parse_modifiers(&settings, "LSTICK_ACTIVATION_MODIFIERS");
|
||||||
|
let rstick_activation_modifiers: Vec<Event> =
|
||||||
|
parse_modifiers(&settings, "RSTICK_ACTIVATION_MODIFIERS");
|
||||||
|
|
||||||
mapped_modifiers.custom.extend(custom_modifiers);
|
mapped_modifiers.custom.extend(custom_modifiers);
|
||||||
mapped_modifiers.custom.extend(lstick_activation_modifiers);
|
mapped_modifiers.custom.extend(lstick_activation_modifiers);
|
||||||
|
@ -192,30 +196,54 @@ fn parse_raw_config(raw_config: RawConfig) -> (Bindings, HashMap<String, String>
|
||||||
}
|
}
|
||||||
if let Ok(event) = Axis::from_str(event) {
|
if let Ok(event) = Axis::from_str(event) {
|
||||||
if !bindings.remap.contains_key(&Event::Axis(event)) {
|
if !bindings.remap.contains_key(&Event::Axis(event)) {
|
||||||
bindings.remap.insert(Event::Axis(event), HashMap::from([(modifiers, output)]));
|
bindings
|
||||||
|
.remap
|
||||||
|
.insert(Event::Axis(event), HashMap::from([(modifiers, output)]));
|
||||||
} else {
|
} else {
|
||||||
bindings.remap.get_mut(&Event::Axis(event)).unwrap().insert(modifiers, output);
|
bindings
|
||||||
|
.remap
|
||||||
|
.get_mut(&Event::Axis(event))
|
||||||
|
.unwrap()
|
||||||
|
.insert(modifiers, output);
|
||||||
}
|
}
|
||||||
} else if let Ok(event) = Key::from_str(event) {
|
} else if let Ok(event) = Key::from_str(event) {
|
||||||
if !bindings.remap.contains_key(&Event::Key(event)) {
|
if !bindings.remap.contains_key(&Event::Key(event)) {
|
||||||
bindings.remap.insert(Event::Key(event), HashMap::from([(modifiers, output)]));
|
bindings
|
||||||
|
.remap
|
||||||
|
.insert(Event::Key(event), HashMap::from([(modifiers, output)]));
|
||||||
} else {
|
} else {
|
||||||
bindings.remap.get_mut(&Event::Key(event)).unwrap().insert(modifiers, output);
|
bindings
|
||||||
|
.remap
|
||||||
|
.get_mut(&Event::Key(event))
|
||||||
|
.unwrap()
|
||||||
|
.insert(modifiers, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let modifiers: Vec<Event> = Vec::new();
|
let modifiers: Vec<Event> = Vec::new();
|
||||||
if let Ok(event) = Axis::from_str(input.as_str()) {
|
if let Ok(event) = Axis::from_str(input.as_str()) {
|
||||||
if !bindings.remap.contains_key(&Event::Axis(event)) {
|
if !bindings.remap.contains_key(&Event::Axis(event)) {
|
||||||
bindings.remap.insert(Event::Axis(event), HashMap::from([(modifiers, output)]));
|
bindings
|
||||||
|
.remap
|
||||||
|
.insert(Event::Axis(event), HashMap::from([(modifiers, output)]));
|
||||||
} else {
|
} else {
|
||||||
bindings.remap.get_mut(&Event::Axis(event)).unwrap().insert(modifiers, output);
|
bindings
|
||||||
|
.remap
|
||||||
|
.get_mut(&Event::Axis(event))
|
||||||
|
.unwrap()
|
||||||
|
.insert(modifiers, output);
|
||||||
}
|
}
|
||||||
} else if let Ok(event) = Key::from_str(input.as_str()) {
|
} else if let Ok(event) = Key::from_str(input.as_str()) {
|
||||||
if !bindings.remap.contains_key(&Event::Key(event)) {
|
if !bindings.remap.contains_key(&Event::Key(event)) {
|
||||||
bindings.remap.insert(Event::Key(event), HashMap::from([(modifiers, output)]));
|
bindings
|
||||||
|
.remap
|
||||||
|
.insert(Event::Key(event), HashMap::from([(modifiers, output)]));
|
||||||
} else {
|
} else {
|
||||||
bindings.remap.get_mut(&Event::Key(event)).unwrap().insert(modifiers, output);
|
bindings
|
||||||
|
.remap
|
||||||
|
.get_mut(&Event::Key(event))
|
||||||
|
.unwrap()
|
||||||
|
.insert(modifiers, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,39 +269,64 @@ fn parse_raw_config(raw_config: RawConfig) -> (Bindings, HashMap<String, String>
|
||||||
}
|
}
|
||||||
if let Ok(event) = Axis::from_str(event) {
|
if let Ok(event) = Axis::from_str(event) {
|
||||||
if !bindings.commands.contains_key(&Event::Axis(event)) {
|
if !bindings.commands.contains_key(&Event::Axis(event)) {
|
||||||
bindings.commands.insert(Event::Axis(event), HashMap::from([(modifiers, output)]));
|
bindings
|
||||||
|
.commands
|
||||||
|
.insert(Event::Axis(event), HashMap::from([(modifiers, output)]));
|
||||||
} else {
|
} else {
|
||||||
bindings.commands.get_mut(&Event::Axis(event)).unwrap().insert(modifiers, output);
|
bindings
|
||||||
|
.commands
|
||||||
|
.get_mut(&Event::Axis(event))
|
||||||
|
.unwrap()
|
||||||
|
.insert(modifiers, output);
|
||||||
}
|
}
|
||||||
} else if let Ok(event) = Key::from_str(event) {
|
} else if let Ok(event) = Key::from_str(event) {
|
||||||
if !bindings.commands.contains_key(&Event::Key(event)) {
|
if !bindings.commands.contains_key(&Event::Key(event)) {
|
||||||
bindings.commands.insert(Event::Key(event), HashMap::from([(modifiers, output)]));
|
bindings
|
||||||
|
.commands
|
||||||
|
.insert(Event::Key(event), HashMap::from([(modifiers, output)]));
|
||||||
} else {
|
} else {
|
||||||
bindings.commands.get_mut(&Event::Key(event)).unwrap().insert(modifiers, output);
|
bindings
|
||||||
|
.commands
|
||||||
|
.get_mut(&Event::Key(event))
|
||||||
|
.unwrap()
|
||||||
|
.insert(modifiers, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let modifiers: Vec<Event> = Vec::new();
|
let modifiers: Vec<Event> = Vec::new();
|
||||||
if let Ok(event) = Axis::from_str(input.as_str()) {
|
if let Ok(event) = Axis::from_str(input.as_str()) {
|
||||||
if !bindings.commands.contains_key(&Event::Axis(event)) {
|
if !bindings.commands.contains_key(&Event::Axis(event)) {
|
||||||
bindings.commands.insert(Event::Axis(event), HashMap::from([(modifiers, output)]));
|
bindings
|
||||||
|
.commands
|
||||||
|
.insert(Event::Axis(event), HashMap::from([(modifiers, output)]));
|
||||||
} else {
|
} else {
|
||||||
bindings.commands.get_mut(&Event::Axis(event)).unwrap().insert(modifiers, output);
|
bindings
|
||||||
|
.commands
|
||||||
|
.get_mut(&Event::Axis(event))
|
||||||
|
.unwrap()
|
||||||
|
.insert(modifiers, output);
|
||||||
}
|
}
|
||||||
} else if let Ok(event) = Key::from_str(input.as_str()) {
|
} else if let Ok(event) = Key::from_str(input.as_str()) {
|
||||||
if !bindings.commands.contains_key(&Event::Key(event)) {
|
if !bindings.commands.contains_key(&Event::Key(event)) {
|
||||||
bindings.commands.insert(Event::Key(event), HashMap::from([(modifiers, output)]));
|
bindings
|
||||||
|
.commands
|
||||||
|
.insert(Event::Key(event), HashMap::from([(modifiers, output)]));
|
||||||
} else {
|
} else {
|
||||||
bindings.commands.get_mut(&Event::Key(event)).unwrap().insert(modifiers, output);
|
bindings
|
||||||
|
.commands
|
||||||
|
.get_mut(&Event::Key(event))
|
||||||
|
.unwrap()
|
||||||
|
.insert(modifiers, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mapped_modifiers.custom.sort();
|
mapped_modifiers.custom.sort();
|
||||||
mapped_modifiers.custom.dedup();
|
mapped_modifiers.custom.dedup();
|
||||||
mapped_modifiers.all.extend(mapped_modifiers.default.clone());
|
mapped_modifiers
|
||||||
|
.all
|
||||||
|
.extend(mapped_modifiers.default.clone());
|
||||||
mapped_modifiers.all.extend(mapped_modifiers.custom.clone());
|
mapped_modifiers.all.extend(mapped_modifiers.custom.clone());
|
||||||
mapped_modifiers.all.sort();
|
mapped_modifiers.all.sort();
|
||||||
mapped_modifiers.all.dedup();
|
mapped_modifiers.all.dedup();
|
||||||
|
@ -296,8 +349,7 @@ pub fn parse_modifiers(settings: &HashMap<String, String>, parameter: &str) -> V
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
custom_modifiers
|
custom_modifiers
|
||||||
},
|
}
|
||||||
None => Vec::new(),
|
None => Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
29
src/main.rs
29
src/main.rs
|
@ -1,15 +1,14 @@
|
||||||
|
mod active_client;
|
||||||
mod config;
|
mod config;
|
||||||
mod virtual_devices;
|
|
||||||
mod event_reader;
|
mod event_reader;
|
||||||
mod udev_monitor;
|
mod udev_monitor;
|
||||||
mod active_client;
|
mod virtual_devices;
|
||||||
|
|
||||||
|
use crate::udev_monitor::*;
|
||||||
|
use config::Config;
|
||||||
use std::env;
|
use std::env;
|
||||||
use tokio;
|
use tokio;
|
||||||
use config::Config;
|
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
use crate::udev_monitor::*;
|
|
||||||
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
@ -23,20 +22,21 @@ async fn main() {
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let user_home = match env::var("HOME") {
|
let user_home = match env::var("HOME") {
|
||||||
Ok(user_home) if user_home == "/root".to_string() => {
|
Ok(user_home) if user_home == "/root".to_string() => match env::var("SUDO_USER") {
|
||||||
match env::var("SUDO_USER") {
|
Ok(sudo_user) => format!("/home/{}", sudo_user),
|
||||||
Ok(sudo_user) => format!("/home/{}", sudo_user),
|
_ => user_home,
|
||||||
_ => user_home,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Ok(user_home) => user_home,
|
Ok(user_home) => user_home,
|
||||||
_ => "/root".to_string(),
|
_ => "/root".to_string(),
|
||||||
};
|
};
|
||||||
let default_config_path = format!("{}/.config/makima", user_home);
|
let default_config_path = format!("{}/.config/makima", user_home);
|
||||||
println!("\nMAKIMA_CONFIG environment variable is not set, defaulting to {:?}.\n", default_config_path);
|
println!(
|
||||||
|
"\nMAKIMA_CONFIG environment variable is not set, defaulting to {:?}.\n",
|
||||||
|
default_config_path
|
||||||
|
);
|
||||||
match std::fs::read_dir(default_config_path) {
|
match std::fs::read_dir(default_config_path) {
|
||||||
Ok(dir) => dir,
|
Ok(dir) => dir,
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -44,14 +44,15 @@ async fn main() {
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
let mut config_files: Vec<Config> = Vec::new();
|
let mut config_files: Vec<Config> = Vec::new();
|
||||||
for file in config_path {
|
for file in config_path {
|
||||||
let filename: String = file.as_ref().unwrap().file_name().into_string().unwrap();
|
let filename: String = file.as_ref().unwrap().file_name().into_string().unwrap();
|
||||||
if filename.ends_with(".toml") && !filename.starts_with(".") {
|
if filename.ends_with(".toml") && !filename.starts_with(".") {
|
||||||
let name: String = filename.split(".toml").collect::<Vec<&str>>()[0].to_string();
|
let name: String = filename.split(".toml").collect::<Vec<&str>>()[0].to_string();
|
||||||
let config_file: Config = Config::new_from_file(file.unwrap().path().to_str().unwrap(), name);
|
let config_file: Config =
|
||||||
|
Config::new_from_file(file.unwrap().path().to_str().unwrap(), name);
|
||||||
config_files.push(config_file);
|
config_files.push(config_file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
use std::{sync::Arc, path::Path, process::Command, env};
|
use crate::config::{Associations, Event};
|
||||||
|
use crate::event_reader::EventReader;
|
||||||
|
use crate::Config;
|
||||||
|
use evdev::{Device, EventStream};
|
||||||
|
use std::{env, path::Path, process::Command, sync::Arc};
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use tokio::task::JoinHandle;
|
use tokio::task::JoinHandle;
|
||||||
use tokio_stream::StreamExt;
|
use tokio_stream::StreamExt;
|
||||||
use evdev::{Device, EventStream};
|
|
||||||
use crate::Config;
|
|
||||||
use crate::config::{Event, Associations};
|
|
||||||
use crate::event_reader::EventReader;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Eq, PartialEq, Hash, Clone)]
|
#[derive(Debug, Default, Eq, PartialEq, Hash, Clone)]
|
||||||
pub enum Client {
|
pub enum Client {
|
||||||
|
@ -32,11 +31,15 @@ pub struct Environment {
|
||||||
pub async fn start_monitoring_udev(config_files: Vec<Config>, mut tasks: Vec<JoinHandle<()>>) {
|
pub async fn start_monitoring_udev(config_files: Vec<Config>, mut tasks: Vec<JoinHandle<()>>) {
|
||||||
let environment = set_environment();
|
let environment = set_environment();
|
||||||
launch_tasks(&config_files, &mut tasks, environment.clone());
|
launch_tasks(&config_files, &mut tasks, environment.clone());
|
||||||
let mut monitor = tokio_udev::AsyncMonitorSocket::new (
|
let mut monitor = tokio_udev::AsyncMonitorSocket::new(
|
||||||
tokio_udev::MonitorBuilder::new().unwrap()
|
tokio_udev::MonitorBuilder::new()
|
||||||
.match_subsystem(std::ffi::OsStr::new("input")).unwrap()
|
.unwrap()
|
||||||
.listen().unwrap()
|
.match_subsystem(std::ffi::OsStr::new("input"))
|
||||||
).unwrap();
|
.unwrap()
|
||||||
|
.listen()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
while let Some(Ok(event)) = monitor.next().await {
|
while let Some(Ok(event)) = monitor.next().await {
|
||||||
if is_mapped(&event.device(), &config_files) {
|
if is_mapped(&event.device(), &config_files) {
|
||||||
println!("---------------------\n\nReinitializing...\n");
|
println!("---------------------\n\nReinitializing...\n");
|
||||||
|
@ -49,15 +52,27 @@ pub async fn start_monitoring_udev(config_files: Vec<Config>, mut tasks: Vec<Joi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn launch_tasks(config_files: &Vec<Config>, tasks: &mut Vec<JoinHandle<()>>, environment: Environment) {
|
pub fn launch_tasks(
|
||||||
|
config_files: &Vec<Config>,
|
||||||
|
tasks: &mut Vec<JoinHandle<()>>,
|
||||||
|
environment: Environment,
|
||||||
|
) {
|
||||||
let modifiers: Arc<Mutex<Vec<Event>>> = Arc::new(Mutex::new(Default::default()));
|
let modifiers: Arc<Mutex<Vec<Event>>> = Arc::new(Mutex::new(Default::default()));
|
||||||
let modifier_was_activated: Arc<Mutex<bool>> = Arc::new(Mutex::new(true));
|
let modifier_was_activated: Arc<Mutex<bool>> = Arc::new(Mutex::new(true));
|
||||||
let user_has_access = match Command::new("groups").output() {
|
let user_has_access = match Command::new("groups").output() {
|
||||||
Ok(groups) if std::str::from_utf8(&groups.stdout.as_slice()).unwrap().contains("input") => {
|
Ok(groups)
|
||||||
|
if std::str::from_utf8(&groups.stdout.as_slice())
|
||||||
|
.unwrap()
|
||||||
|
.contains("input") =>
|
||||||
|
{
|
||||||
println!("Evdev permissions available.\nScanning for event devices with a matching config file...\n");
|
println!("Evdev permissions available.\nScanning for event devices with a matching config file...\n");
|
||||||
true
|
true
|
||||||
},
|
}
|
||||||
Ok(groups) if std::str::from_utf8(&groups.stdout.as_slice()).unwrap().contains("root") => {
|
Ok(groups)
|
||||||
|
if std::str::from_utf8(&groups.stdout.as_slice())
|
||||||
|
.unwrap()
|
||||||
|
.contains("root") =>
|
||||||
|
{
|
||||||
println!("Root permissions available.\nScanning for event devices with a matching config file...\n");
|
println!("Root permissions available.\nScanning for event devices with a matching config file...\n");
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -65,11 +80,13 @@ pub fn launch_tasks(config_files: &Vec<Config>, tasks: &mut Vec<JoinHandle<()>>,
|
||||||
println!("Warning: user has no access to event devices, Makima might not be able to detect all connected devices.\n\
|
println!("Warning: user has no access to event devices, Makima might not be able to detect all connected devices.\n\
|
||||||
Note: Run Makima with 'sudo -E makima' or as a system service. Refer to the docs for more info. Continuing...\n");
|
Note: Run Makima with 'sudo -E makima' or as a system service. Refer to the docs for more info. Continuing...\n");
|
||||||
false
|
false
|
||||||
},
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
println!("Warning: unable to determine if user has access to event devices. Continuing...\n");
|
println!(
|
||||||
|
"Warning: unable to determine if user has access to event devices. Continuing...\n"
|
||||||
|
);
|
||||||
false
|
false
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
let devices: evdev::EnumerateDevices = evdev::enumerate();
|
let devices: evdev::EnumerateDevices = evdev::enumerate();
|
||||||
let mut devices_found = 0;
|
let mut devices_found = 0;
|
||||||
|
@ -79,7 +96,7 @@ pub fn launch_tasks(config_files: &Vec<Config>, tasks: &mut Vec<JoinHandle<()>>,
|
||||||
let split_config_name = config.name.split("::").collect::<Vec<&str>>();
|
let split_config_name = config.name.split("::").collect::<Vec<&str>>();
|
||||||
let associated_device_name = split_config_name[0];
|
let associated_device_name = split_config_name[0];
|
||||||
if associated_device_name == device.1.name().unwrap().replace("/", "") {
|
if associated_device_name == device.1.name().unwrap().replace("/", "") {
|
||||||
let (window_class, layout) = match split_config_name.len() {
|
let (window_class, layout) = match split_config_name.len() {
|
||||||
1 => (Client::Default, 0),
|
1 => (Client::Default, 0),
|
||||||
2 => {
|
2 => {
|
||||||
if let Ok(layout) = split_config_name[1].parse::<u16>() {
|
if let Ok(layout) = split_config_name[1].parse::<u16>() {
|
||||||
|
@ -87,7 +104,7 @@ pub fn launch_tasks(config_files: &Vec<Config>, tasks: &mut Vec<JoinHandle<()>>,
|
||||||
} else {
|
} else {
|
||||||
(Client::Class(split_config_name[1].to_string()), 0)
|
(Client::Class(split_config_name[1].to_string()), 0)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
3 => {
|
3 => {
|
||||||
if let Ok(layout) = split_config_name[1].parse::<u16>() {
|
if let Ok(layout) = split_config_name[1].parse::<u16>() {
|
||||||
(Client::Class(split_config_name[2].to_string()), layout)
|
(Client::Class(split_config_name[2].to_string()), layout)
|
||||||
|
@ -97,24 +114,37 @@ pub fn launch_tasks(config_files: &Vec<Config>, tasks: &mut Vec<JoinHandle<()>>,
|
||||||
println!("Warning: unable to parse layout number in {}, treating it as default.", config.name);
|
println!("Warning: unable to parse layout number in {}, treating it as default.", config.name);
|
||||||
(Client::Default, 0)
|
(Client::Default, 0)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => {
|
_ => {
|
||||||
println!("Warning: too many arguments in config file name {}, treating it as default.", config.name);
|
println!("Warning: too many arguments in config file name {}, treating it as default.", config.name);
|
||||||
(Client::Default, 0)
|
(Client::Default, 0)
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
config.associations.client = window_class;
|
config.associations.client = window_class;
|
||||||
config.associations.layout = layout;
|
config.associations.layout = layout;
|
||||||
config_list.push(config.clone());
|
config_list.push(config.clone());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if config_list.len() > 0 && !config_list.iter().any(|x| x.associations == Associations::default()) {
|
if config_list.len() > 0
|
||||||
|
&& !config_list
|
||||||
|
.iter()
|
||||||
|
.any(|x| x.associations == Associations::default())
|
||||||
|
{
|
||||||
config_list.push(Config::new_empty(device.1.name().unwrap().replace("/", "")));
|
config_list.push(Config::new_empty(device.1.name().unwrap().replace("/", "")));
|
||||||
}
|
}
|
||||||
let event_device = device.0.as_path().to_str().unwrap().to_string();
|
let event_device = device.0.as_path().to_str().unwrap().to_string();
|
||||||
if config_list.len() != 0 {
|
if config_list.len() != 0 {
|
||||||
let stream = Arc::new(Mutex::new(get_event_stream(Path::new(&event_device), config_list.clone())));
|
let stream = Arc::new(Mutex::new(get_event_stream(
|
||||||
let reader = EventReader::new(config_list.clone(), stream, modifiers.clone(), modifier_was_activated.clone(), environment.clone());
|
Path::new(&event_device),
|
||||||
|
config_list.clone(),
|
||||||
|
)));
|
||||||
|
let reader = EventReader::new(
|
||||||
|
config_list.clone(),
|
||||||
|
stream,
|
||||||
|
modifiers.clone(),
|
||||||
|
modifier_was_activated.clone(),
|
||||||
|
environment.clone(),
|
||||||
|
);
|
||||||
tasks.push(tokio::spawn(start_reader(reader)));
|
tasks.push(tokio::spawn(start_reader(reader)));
|
||||||
devices_found += 1
|
devices_found += 1
|
||||||
}
|
}
|
||||||
|
@ -133,24 +163,38 @@ pub async fn start_reader(reader: EventReader) {
|
||||||
fn set_environment() -> Environment {
|
fn set_environment() -> Environment {
|
||||||
match env::var("DBUS_SESSION_BUS_ADDRESS") {
|
match env::var("DBUS_SESSION_BUS_ADDRESS") {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let command = Command::new("sh").arg("-c").arg("systemctl --user show-environment").output().unwrap();
|
let command = Command::new("sh")
|
||||||
let vars = std::str::from_utf8(command.stdout.as_slice()).unwrap().split("\n").collect::<Vec<&str>>();
|
.arg("-c")
|
||||||
|
.arg("systemctl --user show-environment")
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
let vars = std::str::from_utf8(command.stdout.as_slice())
|
||||||
|
.unwrap()
|
||||||
|
.split("\n")
|
||||||
|
.collect::<Vec<&str>>();
|
||||||
for var in vars {
|
for var in vars {
|
||||||
if let Some((variable, value)) = var.split_once("=") {
|
if let Some((variable, value)) = var.split_once("=") {
|
||||||
if let Err(env::VarError::NotPresent) = env::var(variable) {
|
if let Err(env::VarError::NotPresent) = env::var(variable) {
|
||||||
env::set_var(variable, value);
|
env::set_var(variable, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let uid = Command::new("sh").arg("-c").arg("id -u").output().unwrap();
|
let uid = Command::new("sh").arg("-c").arg("id -u").output().unwrap();
|
||||||
let uid_number = std::str::from_utf8(uid.stdout.as_slice()).unwrap().trim();
|
let uid_number = std::str::from_utf8(uid.stdout.as_slice()).unwrap().trim();
|
||||||
if uid_number != "0" {
|
if uid_number != "0" {
|
||||||
let bus_address = format!("unix:path=/run/user/{}/bus", uid_number);
|
let bus_address = format!("unix:path=/run/user/{}/bus", uid_number);
|
||||||
env::set_var("DBUS_SESSION_BUS_ADDRESS", bus_address);
|
env::set_var("DBUS_SESSION_BUS_ADDRESS", bus_address);
|
||||||
let command = Command::new("sh").arg("-c").arg("systemctl --user show-environment").output().unwrap();
|
let command = Command::new("sh")
|
||||||
let vars = std::str::from_utf8(command.stdout.as_slice()).unwrap().split("\n").collect::<Vec<&str>>();
|
.arg("-c")
|
||||||
|
.arg("systemctl --user show-environment")
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
let vars = std::str::from_utf8(command.stdout.as_slice())
|
||||||
|
.unwrap()
|
||||||
|
.split("\n")
|
||||||
|
.collect::<Vec<&str>>();
|
||||||
for var in vars {
|
for var in vars {
|
||||||
if let Some((variable, value)) = var.split_once("=") {
|
if let Some((variable, value)) = var.split_once("=") {
|
||||||
if let Err(env::VarError::NotPresent) = env::var(variable) {
|
if let Err(env::VarError::NotPresent) = env::var(variable) {
|
||||||
|
@ -166,21 +210,33 @@ fn set_environment() -> Environment {
|
||||||
println!("Warning: unable to inherit user environment.\n\
|
println!("Warning: unable to inherit user environment.\n\
|
||||||
Launch Makima with 'sudo -E makima' or make sure that your systemd unit is running with the 'User=<username>' parameter.\n");
|
Launch Makima with 'sudo -E makima' or make sure that your systemd unit is running with the 'User=<username>' parameter.\n");
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
if let (Err(env::VarError::NotPresent), Ok(_)) = (env::var("XDG_SESSION_TYPE"), env::var("WAYLAND_DISPLAY")) {
|
if let (Err(env::VarError::NotPresent), Ok(_)) =
|
||||||
|
(env::var("XDG_SESSION_TYPE"), env::var("WAYLAND_DISPLAY"))
|
||||||
|
{
|
||||||
env::set_var("XDG_SESSION_TYPE", "wayland")
|
env::set_var("XDG_SESSION_TYPE", "wayland")
|
||||||
}
|
}
|
||||||
|
|
||||||
let supported_compositors = vec!["Hyprland", "sway", "KDE"].into_iter().map(|str| String::from(str)).collect::<Vec<String>>();
|
let supported_compositors = vec!["Hyprland", "sway", "KDE"]
|
||||||
|
.into_iter()
|
||||||
|
.map(|str| String::from(str))
|
||||||
|
.collect::<Vec<String>>();
|
||||||
let (x11, wayland) = (String::from("x11"), String::from("wayland"));
|
let (x11, wayland) = (String::from("x11"), String::from("wayland"));
|
||||||
let server: Server = match (env::var("XDG_SESSION_TYPE"), env::var("XDG_CURRENT_DESKTOP")) {
|
let server: Server = match (
|
||||||
(Ok(session), Ok(desktop)) if session == wayland && supported_compositors.contains(&desktop) => {
|
env::var("XDG_SESSION_TYPE"),
|
||||||
|
env::var("XDG_CURRENT_DESKTOP"),
|
||||||
|
) {
|
||||||
|
(Ok(session), Ok(desktop))
|
||||||
|
if session == wayland && supported_compositors.contains(&desktop) =>
|
||||||
|
{
|
||||||
let server = 'a: {
|
let server = 'a: {
|
||||||
if desktop == String::from("KDE") {
|
if desktop == String::from("KDE") {
|
||||||
if let Err(_) = Command::new("kdotool").output() {
|
if let Err(_) = Command::new("kdotool").output() {
|
||||||
println!("Running on KDE but kdotool doesn't seem to be installed.\n\
|
println!(
|
||||||
Won't be able to change bindings according to the active window.\n");
|
"Running on KDE but kdotool doesn't seem to be installed.\n\
|
||||||
|
Won't be able to change bindings according to the active window.\n"
|
||||||
|
);
|
||||||
break 'a Server::Unsupported;
|
break 'a Server::Unsupported;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,28 +244,28 @@ fn set_environment() -> Environment {
|
||||||
Server::Connected(desktop)
|
Server::Connected(desktop)
|
||||||
};
|
};
|
||||||
server
|
server
|
||||||
},
|
}
|
||||||
(Ok(session), Ok(desktop)) if session == wayland => {
|
(Ok(session), Ok(desktop)) if session == wayland => {
|
||||||
println!("Warning: unsupported compositor: {}, won't be able to change bindings according to the active window.\n\
|
println!("Warning: unsupported compositor: {}, won't be able to change bindings according to the active window.\n\
|
||||||
Currently supported desktops: Hyprland, Sway, Plasma/KWin, X11.\n", desktop);
|
Currently supported desktops: Hyprland, Sway, Plasma/KWin, X11.\n", desktop);
|
||||||
Server::Unsupported
|
Server::Unsupported
|
||||||
},
|
}
|
||||||
(Ok(session), _) if session == x11 => {
|
(Ok(session), _) if session == x11 => {
|
||||||
println!("Running on X11, per application bindings enabled.");
|
println!("Running on X11, per application bindings enabled.");
|
||||||
Server::Connected(session)
|
Server::Connected(session)
|
||||||
},
|
}
|
||||||
(Ok(session), Err(_)) if session == wayland => {
|
(Ok(session), Err(_)) if session == wayland => {
|
||||||
println!("Warning: unable to retrieve the current desktop based on XDG_CURRENT_DESKTOP env var.\n\
|
println!("Warning: unable to retrieve the current desktop based on XDG_CURRENT_DESKTOP env var.\n\
|
||||||
Won't be able to change bindings according to the active window.\n");
|
Won't be able to change bindings according to the active window.\n");
|
||||||
Server::Unsupported
|
Server::Unsupported
|
||||||
},
|
}
|
||||||
(Err(_), _) => {
|
(Err(_), _) => {
|
||||||
println!("Warning: unable to retrieve the session type based on XDG_SESSION_TYPE or WAYLAND_DISPLAY env vars.\n\
|
println!("Warning: unable to retrieve the session type based on XDG_SESSION_TYPE or WAYLAND_DISPLAY env vars.\n\
|
||||||
Is your Wayland compositor or X server running?\n\
|
Is your Wayland compositor or X server running?\n\
|
||||||
Exiting Makima.");
|
Exiting Makima.");
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
},
|
}
|
||||||
_ => Server::Failed
|
_ => Server::Failed,
|
||||||
};
|
};
|
||||||
|
|
||||||
Environment {
|
Environment {
|
||||||
|
@ -221,16 +277,26 @@ fn set_environment() -> Environment {
|
||||||
|
|
||||||
pub fn get_event_stream(path: &Path, config: Vec<Config>) -> EventStream {
|
pub fn get_event_stream(path: &Path, config: Vec<Config>) -> EventStream {
|
||||||
let mut device: Device = Device::open(path).expect("Couldn't open device path.");
|
let mut device: Device = Device::open(path).expect("Couldn't open device path.");
|
||||||
match config.iter().find(|&x| x.associations == Associations::default()).unwrap().settings.get("GRAB_DEVICE") {
|
match config
|
||||||
|
.iter()
|
||||||
|
.find(|&x| x.associations == Associations::default())
|
||||||
|
.unwrap()
|
||||||
|
.settings
|
||||||
|
.get("GRAB_DEVICE")
|
||||||
|
{
|
||||||
Some(value) => {
|
Some(value) => {
|
||||||
if value == &true.to_string() {
|
if value == &true.to_string() {
|
||||||
device.grab().expect("Unable to grab device. Is another instance of Makima running?")
|
device
|
||||||
|
.grab()
|
||||||
|
.expect("Unable to grab device. Is another instance of Makima running?")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => device.grab().expect("Unable to grab device. Is another instance of Makima running?")
|
None => device
|
||||||
|
.grab()
|
||||||
|
.expect("Unable to grab device. Is another instance of Makima running?"),
|
||||||
}
|
}
|
||||||
let stream: EventStream = device.into_event_stream().unwrap();
|
let stream: EventStream = device.into_event_stream().unwrap();
|
||||||
return stream
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_mapped(udev_device: &tokio_udev::Device, config_files: &Vec<Config>) -> bool {
|
pub fn is_mapped(udev_device: &tokio_udev::Device, config_files: &Vec<Config>) -> bool {
|
||||||
|
@ -239,15 +305,17 @@ pub fn is_mapped(udev_device: &tokio_udev::Device, config_files: &Vec<Config>) -
|
||||||
let evdev_devices: evdev::EnumerateDevices = evdev::enumerate();
|
let evdev_devices: evdev::EnumerateDevices = evdev::enumerate();
|
||||||
for evdev_device in evdev_devices {
|
for evdev_device in evdev_devices {
|
||||||
for config in config_files {
|
for config in config_files {
|
||||||
if config.name.contains(&evdev_device.1.name().unwrap().to_string())
|
if config
|
||||||
&& devnode.to_path_buf() == evdev_device.0 {
|
.name
|
||||||
return true
|
.contains(&evdev_device.1.name().unwrap().to_string())
|
||||||
|
&& devnode.to_path_buf() == evdev_device.0
|
||||||
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => return false
|
_ => return false,
|
||||||
}
|
}
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use evdev::{Key, uinput::{VirtualDevice, VirtualDeviceBuilder}};
|
use evdev::{
|
||||||
|
uinput::{VirtualDevice, VirtualDeviceBuilder},
|
||||||
|
Key,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct VirtualDevices {
|
pub struct VirtualDevices {
|
||||||
pub keys: VirtualDevice,
|
pub keys: VirtualDevice,
|
||||||
|
@ -9,9 +11,13 @@ pub struct VirtualDevices {
|
||||||
impl VirtualDevices {
|
impl VirtualDevices {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut key_capabilities = evdev::AttributeSet::new();
|
let mut key_capabilities = evdev::AttributeSet::new();
|
||||||
for i in 1..334 {key_capabilities.insert(Key(i));};
|
for i in 1..334 {
|
||||||
|
key_capabilities.insert(Key(i));
|
||||||
|
}
|
||||||
let mut axis_capabilities = evdev::AttributeSet::new();
|
let mut axis_capabilities = evdev::AttributeSet::new();
|
||||||
for i in 0..13 {axis_capabilities.insert(evdev::RelativeAxisType(i));};
|
for i in 0..13 {
|
||||||
|
axis_capabilities.insert(evdev::RelativeAxisType(i));
|
||||||
|
}
|
||||||
let keys_builder = VirtualDeviceBuilder::new()
|
let keys_builder = VirtualDeviceBuilder::new()
|
||||||
.expect("Unable to create virtual device through uinput. Take a look at the Troubleshooting section for more info.")
|
.expect("Unable to create virtual device through uinput. Take a look at the Troubleshooting section for more info.")
|
||||||
.name("Makima Virtual Keyboard/Mouse")
|
.name("Makima Virtual Keyboard/Mouse")
|
||||||
|
@ -28,4 +34,3 @@ impl VirtualDevices {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue