Skip to content

Commit 0ee34f9

Browse files
committed
fix: startup registry, menu events, click behavior
- startup: switch from Task Scheduler/PowerShell to HKCU Run registry key via winreg — simpler and more reliable - tray: remove with_menu_on_left_click(false) which was breaking menu event delivery in tray_icon 0.17; add Clone to TrayMenuIds - main: double-click now toggles icons; remove single-click toggle (menu is the primary interface); reduce loop sleep 50ms -> 16ms; add dlog! to every menu event for diagnostics - startup_tab: update UI text to reflect registry approach
1 parent 02d0826 commit 0ee34f9

4 files changed

Lines changed: 32 additions & 89 deletions

File tree

src/main.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ fn main_loop(
150150
}
151151
}
152152

153-
std::thread::sleep(Duration::from_millis(50));
153+
std::thread::sleep(Duration::from_millis(16));
154154

155155
// ── Poll hotkey events ────────────────────────────────────────────
156156
while let Some(event) = hotkeys::poll_hotkey_event() {
@@ -179,6 +179,7 @@ fn main_loop(
179179

180180
// ── Poll tray menu events ─────────────────────────────────────────
181181
while let Some(event) = tray::poll_menu_event() {
182+
dlog!("menu event: id={:?}", event.id);
182183
let id = &event.id;
183184
if id == &tray_handle.ids.toggle_icons {
184185
let _ = cmd_tx.send(Cmd::ToggleIcons);
@@ -205,23 +206,16 @@ fn main_loop(
205206
}
206207
}
207208

208-
// ── Poll tray icon events (double-click opens settings) ───────────
209+
// ── Poll tray icon events (double-click toggles icons) ───────────
209210
while let Some(event) = tray::poll_tray_event() {
210-
use tray_icon::{MouseButton, MouseButtonState, TrayIconEvent};
211-
if let TrayIconEvent::Click {
212-
button: MouseButton::Left,
213-
button_state: MouseButtonState::Up,
214-
..
215-
} = event
216-
{
217-
let _ = cmd_tx.send(Cmd::ToggleIcons);
218-
}
211+
use tray_icon::{MouseButton, TrayIconEvent};
219212
if let TrayIconEvent::DoubleClick {
220213
button: MouseButton::Left,
221214
..
222215
} = event
223216
{
224-
let _ = cmd_tx.send(Cmd::OpenSettings);
217+
dlog!("tray double-click: ToggleIcons");
218+
let _ = cmd_tx.send(Cmd::ToggleIcons);
225219
}
226220
}
227221

src/startup.rs

Lines changed: 21 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,44 @@
11
use anyhow::Result;
2+
use winreg::enums::*;
3+
use winreg::RegKey;
24

3-
/// Register a Task Scheduler ONLOGON task via PowerShell.
4-
pub fn register(exe_path: &str, delay_s: u32) -> Result<()> {
5-
let delay_iso = format!("PT{}S", delay_s);
6-
let script = format!(
7-
r#"
8-
$action = New-ScheduledTaskAction -Execute '{exe}'
9-
$trigger = New-ScheduledTaskTrigger -AtLogOn
10-
$trigger.Delay = '{delay}'
11-
$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable -ExecutionTimeLimit 0
12-
$principal = New-ScheduledTaskPrincipal -UserId ([System.Security.Principal.WindowsIdentity]::GetCurrent().Name) -RunLevel Limited
13-
Register-ScheduledTask -TaskName 'HideDesktopApps' -Action $action -Trigger $trigger -Settings $settings -Principal $principal -Force | Out-Null
14-
"#,
15-
exe = exe_path,
16-
delay = delay_iso
17-
);
18-
19-
let output = std::process::Command::new("powershell")
20-
.args([
21-
"-ExecutionPolicy",
22-
"Bypass",
23-
"-WindowStyle",
24-
"Hidden",
25-
"-NonInteractive",
26-
"-Command",
27-
&script,
28-
])
29-
.output()?;
30-
31-
if !output.status.success() {
32-
let stderr = String::from_utf8_lossy(&output.stderr);
33-
eprintln!("Startup register warning: {stderr}");
34-
}
5+
const RUN_KEY: &str = r"Software\Microsoft\Windows\CurrentVersion\Run";
6+
const APP_NAME: &str = "HideDesktopApps";
357

8+
/// Add the app to HKCU\...\Run so it starts at login.
9+
pub fn register(exe_path: &str, _delay_s: u32) -> Result<()> {
10+
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
11+
let (run_key, _) = hkcu.create_subkey(RUN_KEY)?;
12+
run_key.set_value(APP_NAME, &exe_path.to_string())?;
3613
Ok(())
3714
}
3815

39-
/// Unregister the Task Scheduler task.
16+
/// Remove the app from HKCU\...\Run.
4017
pub fn unregister() -> Result<()> {
41-
let output = std::process::Command::new("powershell")
42-
.args([
43-
"-ExecutionPolicy",
44-
"Bypass",
45-
"-WindowStyle",
46-
"Hidden",
47-
"-NonInteractive",
48-
"-Command",
49-
"Unregister-ScheduledTask -TaskName 'HideDesktopApps' -Confirm:$false 2>$null",
50-
])
51-
.output()?;
52-
53-
if !output.status.success() {
54-
let stderr = String::from_utf8_lossy(&output.stderr);
55-
eprintln!("Startup unregister warning: {stderr}");
18+
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
19+
if let Ok(run_key) = hkcu.open_subkey_with_flags(RUN_KEY, KEY_WRITE) {
20+
run_key.delete_value(APP_NAME).ok();
5621
}
57-
5822
Ok(())
5923
}
6024

61-
/// Check whether the task is currently registered.
25+
/// Returns true if the app is registered in HKCU\...\Run.
6226
pub fn is_registered() -> bool {
63-
let out = std::process::Command::new("powershell")
64-
.args([
65-
"-ExecutionPolicy",
66-
"Bypass",
67-
"-WindowStyle",
68-
"Hidden",
69-
"-NonInteractive",
70-
"-Command",
71-
"Get-ScheduledTask -TaskName 'HideDesktopApps' -ErrorAction SilentlyContinue",
72-
])
73-
.output();
74-
75-
out.map(|o| !o.stdout.is_empty()).unwrap_or(false)
27+
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
28+
hkcu.open_subkey(RUN_KEY)
29+
.and_then(|k| k.get_value::<String, _>(APP_NAME))
30+
.is_ok()
7631
}
7732

78-
/// Sync the startup task to match the config: register if enabled, unregister if disabled.
33+
/// Sync the startup entry to match the config: register if enabled, remove if disabled.
7934
pub fn sync_startup(config: &crate::config::StartupConfig, exe_path: &str) {
8035
if config.enabled {
8136
if let Err(e) = register(exe_path, config.delay_s) {
82-
eprintln!("Failed to register startup task: {e}");
37+
eprintln!("Failed to register startup: {e}");
8338
}
8439
} else if is_registered() {
8540
if let Err(e) = unregister() {
86-
eprintln!("Failed to unregister startup task: {e}");
41+
eprintln!("Failed to unregister startup: {e}");
8742
}
8843
}
8944
}

src/tray.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::config::ProfileConfig;
66
use crate::state::AppState;
77

88
/// IDs for tray menu items, including one entry per profile.
9+
#[derive(Clone)]
910
pub struct TrayMenuIds {
1011
pub toggle_icons: tray_icon::menu::MenuId,
1112
pub toggle_taskbar: tray_icon::menu::MenuId,
@@ -259,7 +260,6 @@ pub fn build_tray(state: &AppState, profiles: &[ProfileConfig]) -> Result<TrayHa
259260
.with_menu(Box::new(menu))
260261
.with_icon(icon)
261262
.with_tooltip(tooltip)
262-
.with_menu_on_left_click(false) // left click fires the click event; right click shows menu
263263
.build()?;
264264

265265
Ok(TrayHandle { tray, ids })

src/ui/startup_tab.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,23 @@ impl SettingsApp {
1010
&mut self.config.startup.enabled,
1111
"Start HideDesktopApps at Windows logon",
1212
);
13-
ui.label("Uses Windows Task Scheduler (runs without UAC prompt).");
14-
15-
ui.add_space(8.0);
16-
ui.horizontal(|ui| {
17-
ui.label("Startup delay:");
18-
ui.add(egui::Slider::new(&mut self.config.startup.delay_s, 0..=60).suffix(" seconds"));
19-
});
13+
ui.label("Adds the app to the Windows registry Run key (HKCU).");
2014

2115
ui.add_space(8.0);
2216
ui.separator();
2317

2418
let registered = self.startup_registered;
2519
ui.label(if registered {
26-
"Status: Task Scheduler task is registered."
20+
"Status: Registered in startup."
2721
} else {
28-
"Status: Not registered in Task Scheduler."
22+
"Status: Not registered in startup."
2923
});
3024

3125
ui.add_space(4.0);
3226
ui.horizontal(|ui| {
3327
if ui.button("Register Now").clicked() {
3428
let exe = crate::win_ops::current_exe_path();
35-
if let Err(e) = crate::startup::register(&exe, self.config.startup.delay_s) {
29+
if let Err(e) = crate::startup::register(&exe, 0) {
3630
eprintln!("Startup register error: {e}");
3731
} else {
3832
self.startup_registered = true;

0 commit comments

Comments
 (0)