Fixed close hotkey not working so it works now

This commit is contained in:
2025-05-09 22:10:03 -05:00
parent 49226cf5c5
commit a8d8d2ea0b
2 changed files with 113 additions and 9 deletions
+114 -11
View File
@@ -76,17 +76,36 @@ pub fn update_app(state: &mut CursorRush, message: Message) -> Task<Message> {
if let Some(shared) = &state.shared_state { if let Some(shared) = &state.shared_state {
if let Ok(mut shared_state) = shared.lock() { if let Ok(mut shared_state) = shared.lock() {
shared_state.running = false; shared_state.running = false;
println!("Set running flag to false in shared state");
} else {
println!("Failed to lock shared state to set running flag");
} }
} else {
println!("Shared state not available when handling Quit message");
}
// Unregister hotkeys if possible
if let Some(_) = &state.hotkey_manager {
println!("Unregistering hotkeys before exit");
// We don't have a list of registered hotkeys, so we'll just drop the manager
// The hotkeys will be unregistered when the manager is dropped
println!("Hotkey manager will be dropped during exit");
} else {
println!("No hotkey manager available to unregister hotkeys");
} }
// Restore the system cursor before exiting // Restore the system cursor before exiting
platform::restore_cursor(); platform::restore_cursor();
println!("System cursor restored");
// Cleanly drop the tray icon *before* exiting iced // Cleanly drop the tray icon *before* exiting iced
// This removes the icon from the system tray immediately // This removes the icon from the system tray immediately
if let Some(tray) = state.tray_icon.take() { if let Some(tray) = state.tray_icon.take() {
println!("Dropping tray icon...");
drop(tray); drop(tray);
println!("Tray icon explicitly dropped."); println!("Tray icon explicitly dropped.");
} else {
println!("No tray icon to drop");
} }
// Use iced's exit mechanism for a cleaner shutdown // Use iced's exit mechanism for a cleaner shutdown
@@ -213,9 +232,10 @@ pub struct CursorRush {
pub shared_state: Option<Arc<Mutex<SharedState>>>, pub shared_state: Option<Arc<Mutex<SharedState>>>,
pub main_window: Option<iced::window::Id>, // Store the main window ID pub main_window: Option<iced::window::Id>, // Store the main window ID
pub tray_icon: Option<tray_icon::TrayIcon>, // Store the TrayIcon object to keep it alive pub tray_icon: Option<tray_icon::TrayIcon>, // Store the TrayIcon object to keep it alive
pub hotkey_manager: Option<GlobalHotKeyManager>, // Store the hotkey manager to keep it alive
} }
// Make sure the default impl initializes tray_icon to None // Make sure the default impl initializes tray_icon and hotkey_manager to None
impl Default for CursorRush { impl Default for CursorRush {
fn default() -> Self { fn default() -> Self {
Self { Self {
@@ -224,6 +244,7 @@ impl Default for CursorRush {
shared_state: None, shared_state: None,
main_window: None, main_window: None,
tray_icon: None, // Initialize as None tray_icon: None, // Initialize as None
hotkey_manager: None, // Initialize as None
} }
} }
} }
@@ -240,6 +261,22 @@ pub fn app_subscription(_state: &CursorRush) -> Subscription<Message> {
// Return TrayEvent which is essentially a no-op // Return TrayEvent which is essentially a no-op
Message::TrayEvent Message::TrayEvent
}, },
// Add a fallback keyboard handler for Ctrl+Shift+F12
iced::Event::Keyboard(iced::keyboard::Event::KeyPressed {
key,
modifiers,
..
}) => {
// Check if Ctrl+Shift+F12 is pressed
if key == iced::keyboard::Key::Named(iced::keyboard::key::Named::F12) &&
modifiers.control() &&
modifiers.shift() {
println!("Detected Ctrl+Shift+F12 via iced keyboard event");
Message::Quit
} else {
Message::TrayEvent // No-op for other key events
}
},
// Handle other events // Handle other events
_ => Message::TrayEvent, // Use TrayEvent as a no-op message _ => Message::TrayEvent, // Use TrayEvent as a no-op message
} }
@@ -326,20 +363,38 @@ pub fn boot_app() -> (CursorRush, Task<Message>) {
eprintln!("Failed to initialize tray icon, application might not function correctly in background."); eprintln!("Failed to initialize tray icon, application might not function correctly in background.");
} }
setup_hotkeys(shared_state.clone()); // Set up hotkeys and store the manager in the application state
state.hotkey_manager = setup_hotkeys(shared_state.clone());
if state.hotkey_manager.is_none() {
eprintln!("Failed to initialize hotkey manager, hotkeys will not work!");
} else {
println!("Hotkey manager successfully initialized and stored in application state");
}
(state, Task::none()) (state, Task::none())
} }
// Set up global hotkeys // Set up global hotkeys
fn setup_hotkeys(shared_state: Arc<Mutex<SharedState>>) { fn setup_hotkeys(shared_state: Arc<Mutex<SharedState>>) -> Option<GlobalHotKeyManager> {
// Set up global hotkey manager // Set up global hotkey manager
let hotkey_manager = match GlobalHotKeyManager::new() { let hotkey_manager = match GlobalHotKeyManager::new() {
Ok(manager) => manager, Ok(manager) => {
println!("Successfully created hotkey manager");
manager
},
Err(e) => { Err(e) => {
eprintln!("Failed to create hotkey manager: {}", e); eprintln!("Failed to create hotkey manager: {}", e);
// Continue without hotkey support // Continue without hotkey support
GlobalHotKeyManager::new().expect("Critical failure: could not create hotkey manager") match GlobalHotKeyManager::new() {
Ok(manager) => {
println!("Second attempt to create hotkey manager succeeded");
manager
},
Err(e) => {
eprintln!("Critical failure: could not create hotkey manager on second attempt: {}", e);
return None;
}
}
} }
}; };
@@ -351,10 +406,13 @@ fn setup_hotkeys(shared_state: Arc<Mutex<SharedState>>) {
Code::F12, Code::F12,
); );
println!("Attempting to register Ctrl+Shift+F12 as exit hotkey");
// Register the hotkey with better error handling // Register the hotkey with better error handling
match hotkey_manager.register(hotkey) { let registered_hotkey = match hotkey_manager.register(hotkey) {
Ok(_) => { Ok(_) => {
println!("Successfully registered Ctrl+Shift+F12 as exit hotkey"); println!("Successfully registered Ctrl+Shift+F12 as exit hotkey");
hotkey
}, },
Err(e) => { Err(e) => {
eprintln!("Failed to register hotkey: {}", e); eprintln!("Failed to register hotkey: {}", e);
@@ -364,21 +422,50 @@ fn setup_hotkeys(shared_state: Arc<Mutex<SharedState>>) {
Code::F12, Code::F12,
); );
println!("Attempting to register fallback hotkey Ctrl+Alt+F12");
match hotkey_manager.register(fallback_hotkey) { match hotkey_manager.register(fallback_hotkey) {
Ok(_) => println!("Registered fallback hotkey Ctrl+Alt+F12 instead"), Ok(_) => {
Err(e) => eprintln!("Failed to register fallback hotkey: {}", e), println!("Registered fallback hotkey Ctrl+Alt+F12 instead");
} fallback_hotkey
} },
} Err(e) => {
eprintln!("Failed to register fallback hotkey: {}", e);
// Try one more fallback with just F12
let last_fallback = GlobalHotKey::new(None, Code::F12);
println!("Attempting to register last fallback hotkey F12");
match hotkey_manager.register(last_fallback) {
Ok(_) => {
println!("Registered last fallback hotkey F12");
last_fallback
},
Err(e) => {
eprintln!("Failed to register any hotkey: {}", e);
return None;
}
}
}
}
}
};
println!("Hotkey registered: {:?}", registered_hotkey);
println!("Press Ctrl+Shift+F12 to exit the application"); println!("Press Ctrl+Shift+F12 to exit the application");
// We can't clone the hotkey manager, so we'll use Arc to share it
let manager_arc = Arc::new(hotkey_manager);
let manager_for_thread = Arc::clone(&manager_arc);
// Spawn a thread to listen for hotkeys // Spawn a thread to listen for hotkeys
let state_clone = shared_state.clone(); let state_clone = shared_state.clone();
thread::spawn(move || { thread::spawn(move || {
println!("Hotkey listener thread started"); println!("Hotkey listener thread started");
let event_receiver = global_hotkey::GlobalHotKeyEvent::receiver(); let event_receiver = global_hotkey::GlobalHotKeyEvent::receiver();
// Keep a reference to the manager in this thread to ensure it stays alive
let _manager_ref = &manager_for_thread;
println!("Hotkey manager reference maintained in thread");
loop { loop {
match event_receiver.try_recv() { match event_receiver.try_recv() {
Ok(event) => { Ok(event) => {
@@ -388,15 +475,20 @@ fn setup_hotkeys(shared_state: Arc<Mutex<SharedState>>) {
// Send Quit message instead of direct exit // Send Quit message instead of direct exit
// Get the global sender // Get the global sender
if let Some(tx) = TRAY_SENDER.lock().unwrap().as_ref() { if let Some(tx) = TRAY_SENDER.lock().unwrap().as_ref() {
println!("Found global sender, sending Quit message");
if let Err(e) = tx.unbounded_send(Message::Quit) { if let Err(e) = tx.unbounded_send(Message::Quit) {
eprintln!("Failed to send Quit message from hotkey thread: {}", e); eprintln!("Failed to send Quit message from hotkey thread: {}", e);
// Fallback to direct exit if channel fails // Fallback to direct exit if channel fails
println!("Using fallback exit mechanism");
platform::restore_cursor(); platform::restore_cursor();
std::process::exit(0); std::process::exit(0);
} else {
println!("Successfully sent Quit message through channel");
} }
} else { } else {
eprintln!("Hotkey: Global sender not initialized yet"); eprintln!("Hotkey: Global sender not initialized yet");
// Fallback to direct exit if sender not available // Fallback to direct exit if sender not available
println!("Global sender not available, using direct exit");
platform::restore_cursor(); platform::restore_cursor();
std::process::exit(0); std::process::exit(0);
} }
@@ -417,4 +509,15 @@ fn setup_hotkeys(shared_state: Arc<Mutex<SharedState>>) {
} }
} }
}); });
// Return the hotkey manager from the Arc so it can be stored in the application state
match Arc::try_unwrap(manager_arc) {
Ok(manager) => Some(manager),
Err(_arc) => {
// If we can't unwrap the Arc (which shouldn't happen), extract a clone from it
println!("Warning: Could not unwrap Arc<GlobalHotKeyManager>, using a new instance");
// Create a new instance as a fallback
GlobalHotKeyManager::new().ok()
}
}
} }
+1
View File
@@ -17,6 +17,7 @@ impl Steam {
Self { client, single } Self { client, single }
} }
#[allow(dead_code)]
pub fn drop_item(&self) { pub fn drop_item(&self) {
unsafe { unsafe {
let mut r = 0; let mut r = 0;