mouse control with buttons
This commit is contained in:
137
src/main.rs
137
src/main.rs
@@ -1,11 +1,11 @@
|
|||||||
|
use eframe::UserEvent;
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
|
use egui::{FontData, FontDefinitions, FontFamily};
|
||||||
use egui::{Key, RichText};
|
use egui::{Key, RichText};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use egui::{FontData, FontDefinitions, FontFamily};
|
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
use winit::event_loop::{EventLoop};
|
|
||||||
use eframe::UserEvent;
|
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use winit::event_loop::EventLoop;
|
||||||
|
|
||||||
const MAX_KEYS: usize = 6;
|
const MAX_KEYS: usize = 6;
|
||||||
const SECRET_COMBO: [Key; MAX_KEYS] = [
|
const SECRET_COMBO: [Key; MAX_KEYS] = [
|
||||||
@@ -17,7 +17,6 @@ const SECRET_COMBO: [Key; MAX_KEYS] = [
|
|||||||
Key::ArrowRight,
|
Key::ArrowRight,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
struct AdminGateApp {
|
struct AdminGateApp {
|
||||||
key_history: VecDeque<Key>,
|
key_history: VecDeque<Key>,
|
||||||
should_run_admin_command: Arc<Mutex<bool>>,
|
should_run_admin_command: Arc<Mutex<bool>>,
|
||||||
@@ -32,7 +31,6 @@ impl Default for AdminGateApp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl eframe::App for AdminGateApp {
|
impl eframe::App for AdminGateApp {
|
||||||
fn update(&mut self, ctx: &egui::Context, _: &mut eframe::Frame) {
|
fn update(&mut self, ctx: &egui::Context, _: &mut eframe::Frame) {
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
@@ -55,20 +53,81 @@ impl eframe::App for AdminGateApp {
|
|||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(" ");
|
.join(" ");
|
||||||
|
|
||||||
ui.label(
|
ui.label(RichText::new(&key_display).size(60.0).strong());
|
||||||
RichText::new(&key_display)
|
|
||||||
.size(60.0)
|
|
||||||
.strong(),
|
|
||||||
);
|
|
||||||
|
|
||||||
ui.add_space(20.0);
|
ui.add_space(20.0);
|
||||||
|
|
||||||
|
ui.horizontal_top(|ui| {
|
||||||
|
ui.add_space(30.0);
|
||||||
|
|
||||||
|
egui::Grid::new("arrow_grid")
|
||||||
|
.spacing([20.0, 20.0])
|
||||||
|
.striped(false)
|
||||||
|
.min_col_width(80.0)
|
||||||
|
.show(ui, |ui| {
|
||||||
|
// Row 1
|
||||||
|
if ui.add_sized([80.0, 80.0], egui::Button::new("X")).clicked() {
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ui.add_sized([80.0, 80.0], egui::Button::new("↑")).clicked() {
|
||||||
|
if self.key_history.len() == MAX_KEYS {
|
||||||
|
self.key_history.pop_front();
|
||||||
|
}
|
||||||
|
self.key_history.push_back(Key::ArrowUp);
|
||||||
|
}
|
||||||
|
ui.label(""); // empty cell
|
||||||
|
ui.end_row();
|
||||||
|
|
||||||
|
// Row 2
|
||||||
|
if ui.add_sized([80.0, 80.0], egui::Button::new("←")).clicked() {
|
||||||
|
if self.key_history.len() == MAX_KEYS {
|
||||||
|
self.key_history.pop_front();
|
||||||
|
}
|
||||||
|
self.key_history.push_back(Key::ArrowLeft);
|
||||||
|
}
|
||||||
|
if ui.add_sized([80.0, 80.0], egui::Button::new("⏎")).clicked() {
|
||||||
|
if self.key_history.len() == MAX_KEYS
|
||||||
|
&& self
|
||||||
|
.key_history
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.eq(SECRET_COMBO.iter().copied())
|
||||||
|
{
|
||||||
|
*self.should_run_admin_command.lock().unwrap() = true;
|
||||||
|
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ui.add_sized([80.0, 80.0], egui::Button::new("→")).clicked() {
|
||||||
|
if self.key_history.len() == MAX_KEYS {
|
||||||
|
self.key_history.pop_front();
|
||||||
|
}
|
||||||
|
self.key_history.push_back(Key::ArrowRight);
|
||||||
|
}
|
||||||
|
ui.end_row();
|
||||||
|
|
||||||
|
// Row 3
|
||||||
|
ui.label(""); // empty cell
|
||||||
|
if ui.add_sized([80.0, 80.0], egui::Button::new("↓")).clicked() {
|
||||||
|
if self.key_history.len() == MAX_KEYS {
|
||||||
|
self.key_history.pop_front();
|
||||||
|
}
|
||||||
|
self.key_history.push_back(Key::ArrowDown);
|
||||||
|
}
|
||||||
|
ui.label(""); // empty cell
|
||||||
|
ui.end_row();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
egui::TopBottomPanel::bottom("footer").show(ctx, |ui| {
|
egui::TopBottomPanel::bottom("footer").show(ctx, |ui| {
|
||||||
ui.horizontal_centered(|ui| {
|
ui.horizontal_centered(|ui| {
|
||||||
ui.label(egui::RichText::new("Press ESC to quit. Enter runs the admin command.").size(24.0).weak());
|
ui.label(
|
||||||
|
egui::RichText::new("Press ESC to quit. Enter runs the admin command.")
|
||||||
|
.size(24.0)
|
||||||
|
.weak(),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -78,7 +137,7 @@ impl eframe::App for AdminGateApp {
|
|||||||
key,
|
key,
|
||||||
pressed: true,
|
pressed: true,
|
||||||
modifiers: _,
|
modifiers: _,
|
||||||
physical_key : _,
|
physical_key: _,
|
||||||
repeat: _,
|
repeat: _,
|
||||||
} = event
|
} = event
|
||||||
{
|
{
|
||||||
@@ -116,7 +175,6 @@ impl eframe::App for AdminGateApp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn setup_custom_fonts(ctx: &egui::Context) {
|
fn setup_custom_fonts(ctx: &egui::Context) {
|
||||||
let mut fonts = FontDefinitions::default();
|
let mut fonts = FontDefinitions::default();
|
||||||
|
|
||||||
@@ -124,10 +182,9 @@ fn setup_custom_fonts(ctx: &egui::Context) {
|
|||||||
fonts.font_data.insert(
|
fonts.font_data.insert(
|
||||||
"custom".to_string(),
|
"custom".to_string(),
|
||||||
FontData::from_owned(
|
FontData::from_owned(
|
||||||
|
|
||||||
|
|
||||||
std::fs::read("/usr/share/fonts/TTF/DejaVuSans.ttf").expect("Failed to load font"),
|
std::fs::read("/usr/share/fonts/TTF/DejaVuSans.ttf").expect("Failed to load font"),
|
||||||
).into(),
|
)
|
||||||
|
.into(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Use the custom font for all proportional and monospace text
|
// Use the custom font for all proportional and monospace text
|
||||||
@@ -146,11 +203,8 @@ fn setup_custom_fonts(ctx: &egui::Context) {
|
|||||||
ctx.set_fonts(fonts);
|
ctx.set_fonts(fonts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut args = env::args().skip(1); // Skip program name
|
||||||
fn main() {
|
|
||||||
|
|
||||||
let mut args = env::args().skip(1); // Skip program name
|
|
||||||
|
|
||||||
let admin_command = match args.next() {
|
let admin_command = match args.next() {
|
||||||
Some(cmd) => cmd,
|
Some(cmd) => cmd,
|
||||||
@@ -162,37 +216,38 @@ fn main() {
|
|||||||
|
|
||||||
let admin_args: Vec<String> = args.collect();
|
let admin_args: Vec<String> = args.collect();
|
||||||
|
|
||||||
|
|
||||||
let should_run_admin_command = Arc::new(Mutex::new(false));
|
let should_run_admin_command = Arc::new(Mutex::new(false));
|
||||||
let shared_flag = should_run_admin_command.clone();
|
let shared_flag = should_run_admin_command.clone();
|
||||||
|
|
||||||
let app = AdminGateApp {
|
let app = AdminGateApp {
|
||||||
key_history: VecDeque::with_capacity(6),
|
key_history: VecDeque::with_capacity(6),
|
||||||
should_run_admin_command: shared_flag,
|
should_run_admin_command: shared_flag,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let options = eframe::NativeOptions::default();
|
let options = eframe::NativeOptions::default();
|
||||||
let eventloop = EventLoop::<UserEvent>::with_user_event().build().unwrap();
|
let eventloop = EventLoop::<UserEvent>::with_user_event().build().unwrap();
|
||||||
|
|
||||||
let mut winit_app = eframe::create_native("Admin Gate", options, Box::new(|cc| {
|
let mut winit_app = eframe::create_native(
|
||||||
// Setup fonts
|
"Admin Gate",
|
||||||
setup_custom_fonts(&cc.egui_ctx);
|
options,
|
||||||
Ok(Box::new(app))
|
Box::new(|cc| {
|
||||||
}), &eventloop);
|
// Setup fonts
|
||||||
|
setup_custom_fonts(&cc.egui_ctx);
|
||||||
|
Ok(Box::new(app))
|
||||||
eventloop.run_app(&mut winit_app).unwrap();
|
}),
|
||||||
|
&eventloop,
|
||||||
|
);
|
||||||
|
|
||||||
|
eventloop.run_app(&mut winit_app).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// After GUI closes
|
// After GUI closes
|
||||||
if *should_run_admin_command.lock().unwrap() {
|
if *should_run_admin_command.lock().unwrap() {
|
||||||
println!("✅ Running admin command...");
|
println!("✅ Running admin command...");
|
||||||
|
|
||||||
match std::process::Command::new(admin_command)
|
match std::process::Command::new(admin_command)
|
||||||
.args(admin_args)
|
.args(admin_args)
|
||||||
.status() // ← wait until it finishes
|
.status() // ← wait until it finishes
|
||||||
{
|
{
|
||||||
@@ -203,8 +258,6 @@ fn main() {
|
|||||||
eprintln!("❌ Failed to run admin command: {}", e);
|
eprintln!("❌ Failed to run admin command: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user