Fix tray icon event handling on Windows
- Add Windows message queue pumping in process_events() - PeekMessageW/TranslateMessage/DispatchMessageW for event delivery - Menu clicks and tray events now work properly 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,11 @@ use std::sync::Arc;
|
|||||||
use tray_icon::{Icon, TrayIcon, TrayIconBuilder, TrayIconEvent};
|
use tray_icon::{Icon, TrayIcon, TrayIconBuilder, TrayIconEvent};
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
use windows::Win32::UI::WindowsAndMessaging::{
|
||||||
|
PeekMessageW, TranslateMessage, DispatchMessageW, MSG, PM_REMOVE,
|
||||||
|
};
|
||||||
|
|
||||||
/// Events that can be triggered from the tray menu
|
/// Events that can be triggered from the tray menu
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum TrayAction {
|
pub enum TrayAction {
|
||||||
@@ -83,6 +88,10 @@ impl TrayController {
|
|||||||
|
|
||||||
/// Process pending menu events (call this from the main loop)
|
/// Process pending menu events (call this from the main loop)
|
||||||
pub fn process_events(&self) -> Option<TrayAction> {
|
pub fn process_events(&self) -> Option<TrayAction> {
|
||||||
|
// Pump Windows message queue to process tray icon events
|
||||||
|
#[cfg(windows)]
|
||||||
|
pump_windows_messages();
|
||||||
|
|
||||||
// Check for menu events
|
// Check for menu events
|
||||||
if let Ok(event) = MenuEvent::receiver().try_recv() {
|
if let Ok(event) = MenuEvent::receiver().try_recv() {
|
||||||
if event.id == self.end_session_item.id() {
|
if event.id == self.end_session_item.id() {
|
||||||
@@ -107,6 +116,19 @@ impl TrayController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pump the Windows message queue to process tray icon events
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn pump_windows_messages() {
|
||||||
|
unsafe {
|
||||||
|
let mut msg = MSG::default();
|
||||||
|
// Process all pending messages
|
||||||
|
while PeekMessageW(&mut msg, None, 0, 0, PM_REMOVE).as_bool() {
|
||||||
|
let _ = TranslateMessage(&msg);
|
||||||
|
DispatchMessageW(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a simple default icon (green circle for connected)
|
/// Create a simple default icon (green circle for connected)
|
||||||
fn create_default_icon() -> Result<Icon> {
|
fn create_default_icon() -> Result<Icon> {
|
||||||
// Create a simple 32x32 green icon
|
// Create a simple 32x32 green icon
|
||||||
|
|||||||
Reference in New Issue
Block a user