#[cfg(target_os = "windows")]
use std::cell::RefCell;
#[cfg(target_os = "windows")]
use std::rc::Rc;
#[cfg(target_os = "windows")]
use std::sync::atomic::AtomicBool;
#[cfg(target_os = "windows")]
use std::sync::{Arc, Mutex, RwLock};
#[cfg(target_os = "windows")]
use std::time::{Duration, Instant};
use crate::clipboard_history;
#[cfg(target_os = "windows")]
use crate::config::Config;
#[cfg(target_os = "windows")]
use crate::config::DiscoveryBackend;
#[cfg(target_os = "windows")]
use crate::core_service::CoreService;
#[cfg(target_os = "windows")]
use crate::everything_bridge::EverythingBridge;
#[cfg(target_os = "windows")]
use crate::overlay_state::{HotkeyAction, OverlayState};
#[cfg(target_os = "windows")]
use crate::plugin_sdk::PluginRegistry;
#[cfg(target_os = "windows")]
use crate::query_dsl::ParsedQuery;
#[cfg(target_os = "windows")]
use crate::runtime::{log_info, log_warn, RuntimeError};
#[cfg(target_os = "windows")]
use crate::runtime_actions::{
execute_action_selection, launch_overlay_selection, should_suppress_failed_uninstall,
uninstall_confirmation_results,
};
#[cfg(target_os = "windows")]
use crate::runtime_hotkey::{should_suppress_hotkey_for_game_mode, toggle_game_mode_from_tray};
#[cfg(target_os = "windows")]
use crate::runtime_index::{
config_file_modified_time, maybe_apply_background_index_refresh,
maybe_apply_runtime_config_reload, start_background_index_refresh, BackgroundIndexRefresh,
RuntimeConfigWatcher,
};
#[cfg(target_os = "windows")]
use crate::runtime_overlay_rows::{
filter_suppressed_uninstall_results, overlay_rows,
reconcile_suppressed_uninstall_titles, set_idle_overlay_state, set_status_row_overlay_state,
track_uninstall_title_suppression, PendingUninstallConfirmation, ACTION_UNINSTALL_CANCEL_ID,
ACTION_UNINSTALL_CONFIRM_ID, STATUS_ROW_NO_COMMAND_RESULTS, STATUS_ROW_NO_RESULTS,
STATUS_ROW_TYPE_TO_SEARCH,
};
#[cfg(target_os = "windows")]
use crate::runtime_process::{
acquire_single_instance_guard, hotkey_registration_recovery_message,
hotkey_registration_status_text, launch_stable_updater,
};
#[cfg(target_os = "windows")]
use crate::runtime_search_session::{
maybe_expand_uninstall_quick_shortcut, result_limit_for_query, OverlaySearchSession,
};
#[cfg(target_os = "windows")]
use crate::search_worker::SearchWorker;
#[cfg(target_os = "windows")]
use crate::overlay::host::Host;
#[cfg(target_os = "windows")]
use crate::overlay::hotkey::HotkeyListener;
#[cfg(target_os = "windows")]
use crate::overlay::indexing_progress::run_with_progress_window;
#[cfg(target_os = "windows")]
use crate::overlay::{
signal_existing_instance_show, NativeOverlayShell, OverlayEvent, OverlayRow, OverlayRowRole,
};
#[cfg(target_os = "windows")]
use crate::overlay::tray::TrayIcon;
#[cfg(target_os = "windows")]
pub(crate) fn run_windows_runtime(
startup_started_at: Instant,
runtime_config: Config,
service: CoreService,
) -> Result<(), RuntimeError> {
let service = Arc::new(RwLock::new(service));
let initial_cache_empty = {
let guard = service.read().unwrap();
guard.cached_items_len() == 0
};
let background_index_refresh = if initial_cache_empty {
let use_progress_window = match runtime_config.file_discovery_backend {
DiscoveryBackend::Everything => false,
DiscoveryBackend::Walkdir => true,
DiscoveryBackend::Auto => match EverythingBridge::detect() {
Some(bridge) if bridge.is_service_running() => false,
_ => true,
},
};
if use_progress_window {
log_info("[nex] startup cached_items=0 (first-time indexing with progress window)");
let service_arc = service.clone();
let result = run_with_progress_window(move |pct| {
let svc = service_arc.write().unwrap();
*svc.progress.lock().unwrap() = Some(pct);
let report = svc.rebuild_index_incremental_with_report();
*svc.progress.lock().unwrap() = None;
report
});
match result {
Ok(report) => {
log_info(&format!(
"[nex] startup indexed_items={} discovered={} upserted={} removed={}",
report.indexed_total,
report.discovered_total,
report.upserted_total,
report.removed_total,
));
for provider in &report.providers {
log_info(&format!(
"[nex] index_provider name={} discovered={} upserted={} removed={} skipped={} elapsed_ms={}",
provider.provider,
provider.discovered,
provider.upserted,
provider.removed,
provider.skipped,
provider.elapsed_ms
));
}
if let Ok(svc) = service.write() {
let _ = svc.sync_indexes_from_cache();
}
BackgroundIndexRefresh {
completed: Arc::new(AtomicBool::new(true)),
result: Arc::new(Mutex::new(Some(Ok(report)))),
cache_applied: true,
indexes_synced: true,
initial_cache_empty: true,
pending_discovery_reindex: false,
pending_discovery_reindex_due_at: None,
pending_discovery_reindex_requests: 0,
started_at: Instant::now(),
startup_started_at,
}
}
Err(e) => {
log_warn(&format!("[nex] first-time indexing failed: {e}"));
start_background_index_refresh(&runtime_config, true, startup_started_at)
}
}
} else {
log_info("[nex] startup cached_items=0 (first-time indexing, Everything backend — async, no progress window)");
log_info(&format!(
"[nex] startup_phase phase=indexing_started elapsed_ms={} initial_cache_empty=true cached_items=0",
startup_started_at.elapsed().as_millis()
));
start_background_index_refresh(&runtime_config, true, startup_started_at)
}
} else {
log_info(&format!(
"[nex] startup cached_items={} (async indexing scheduled)",
{
let guard = service.read().unwrap();
guard.cached_items_len()
}
));
start_background_index_refresh(&runtime_config, false, startup_started_at)
};
let plugin_registry = PluginRegistry::load_from_config(&runtime_config);
for warning in &plugin_registry.load_warnings {
log_warn(&format!("[nex] plugin_warning {warning}"));
}
log_info(&format!(
"[nex] plugins loaded provider_items={} action_items={}",
plugin_registry.provider_items.len(),
plugin_registry.action_items.len()
));
unsafe {
let _ = windows_sys::Win32::UI::HiDpi::SetProcessDpiAwarenessContext(
windows_sys::Win32::UI::HiDpi::DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2,
);
}
if let Ok(exe) = std::env::current_exe() {
if let Err(error) = crate::startup::set_enabled(runtime_config.launch_at_startup, &exe) {
log_warn(&format!("[nex] startup sync warning: {error}"));
}
}
let _single_instance = match acquire_single_instance_guard() {
Ok(guard) => guard,
Err(error) => return Err(RuntimeError::Overlay(error)),
};
if _single_instance.is_none() {
let _ = signal_existing_instance_show();
log_info("[nex] runtime already active; signaled existing instance");
return Ok(());
}
let overlay_state = OverlayState::default();
let overlay = NativeOverlayShell::create().map_err(RuntimeError::Overlay)?;
overlay.set_help_config_path(runtime_config.config_path.to_string_lossy().as_ref());
overlay.set_hotkey_hint(&runtime_config.hotkey);
overlay.set_performance_tuning(
runtime_config.idle_cache_trim_ms,
runtime_config.active_memory_target_mb,
runtime_config.ui_warm_release_ms,
);
overlay.set_game_mode_enabled(runtime_config.game_mode_enabled);
log_info("[nex] native overlay shell initialized (hidden)");
log_info(&format!(
"[nex] startup_phase phase=overlay_ready elapsed_ms={}",
startup_started_at.elapsed().as_millis()
));
let (event_tx, event_rx) = crossbeam_channel::unbounded::<OverlayEvent>();
let tray_icon = TrayIcon::create(
event_tx.clone(),
runtime_config.config_path.to_string_lossy().as_ref(),
)
.map_err(|e| RuntimeError::Overlay(format!("tray icon: {e}")))?;
log_info("[nex] system tray icon created");
let (tray_gm_tx, tray_gm_rx) = crossbeam_channel::unbounded::<bool>();
let (tray_hi_tx, tray_hi_rx) = crossbeam_channel::unbounded::<bool>();
let _tray_updater = std::thread::Builder::new()
.name("nex-tray-updater".into())
.spawn(move || {
loop {
crossbeam_channel::select! {
recv(tray_gm_rx) -> msg => {
match msg {
Ok(enabled) => tray_icon.set_game_mode(enabled),
Err(_) => break,
}
}
recv(tray_hi_rx) -> msg => {
match msg {
Ok(active) => tray_icon.set_hotkey_issue(active),
Err(_) => break,
}
}
}
}
})
.map_err(|e| RuntimeError::Overlay(format!("tray updater thread: {e}")))?;
let hotkey_listener: Arc<Mutex<Option<HotkeyListener>>> = Arc::new(Mutex::new(None));
let hotkey_issue_status: Option<String> =
match HotkeyListener::start(&runtime_config.hotkey, event_tx.clone()) {
Ok(listener) => {
log_info(&format!(
"[nex] hotkey registered native_id=1 hotkey={} listener_thread_id={}",
runtime_config.hotkey,
listener
.thread_id()
.map(|id| id.to_string())
.unwrap_or_else(|| "unknown".to_string())
));
overlay.set_hotkey_issue_active(false);
let _ = tray_hi_tx.send(false);
*hotkey_listener.lock().unwrap() = Some(listener);
None
}
Err(error) => {
let recovery_message = hotkey_registration_recovery_message(
&runtime_config.hotkey,
&runtime_config.config_path,
);
let suggested = crate::settings::suggested_hotkey_presets(
&runtime_config.hotkey,
3,
)
.join("|");
log_warn(&format!(
"[nex] hotkey_registration_issue hotkey={} suggestions={} error={:?}",
runtime_config.hotkey, suggested, error
));
log_warn(&format!("[nex] {recovery_message}"));
overlay.set_hotkey_issue_active(true);
let _ = tray_hi_tx.send(true);
let status = hotkey_registration_status_text(&runtime_config.hotkey);
overlay.set_status_text(&status);
Some(status)
}
};
log_info(&format!(
"[nex] startup_phase phase=hotkey_ready elapsed_ms={} hotkey={}",
startup_started_at.elapsed().as_millis(),
runtime_config.hotkey
));
log_info("[nex] event loop running (native overlay)");
let search_worker = SearchWorker::new(
service.clone(),
runtime_config.clone(),
Arc::new(plugin_registry.clone()),
event_tx.clone(),
);
let max_results = runtime_config.max_results as usize;
let config_watcher = RuntimeConfigWatcher {
path: runtime_config.config_path.clone(),
last_checked: Instant::now(),
last_modified: config_file_modified_time(runtime_config.config_path.as_path()),
};
let shared_state = overlay.shared_state();
let proxy_slot = overlay.proxy_slot();
let is_running = overlay.is_running();
let icon_cache = overlay.icon_cache();
is_running.store(true, std::sync::atomic::Ordering::SeqCst);
let host = Host {
state: shared_state,
proxy_slot,
icon_cache,
event_tx: event_tx.clone(),
is_running: is_running.clone(),
};
let test_show = matches!(
std::env::var("NEX_TEST_SHOW").as_deref(),
Ok("1") | Ok("true")
);
if test_show {
let tx = event_tx.clone();
std::thread::Builder::new()
.name("nex-test-show".into())
.spawn(move || {
std::thread::sleep(std::time::Duration::from_secs(2));
let _ = tx.send(OverlayEvent::Hotkey(1));
})
.map_err(|e| RuntimeError::Overlay(format!("test-show thread: {e}")))?;
}
let worker = RuntimeWorker {
overlay: overlay.clone(),
service: service.clone(),
runtime_config,
background_index_refresh,
plugin_registry,
search_worker,
overlay_state,
max_results,
config_watcher,
current_results: Vec::new(),
suppressed_uninstall_titles: Vec::new(),
pending_uninstall_confirmation: None,
selected_index: 0,
last_query: String::new(),
last_sent_generation: 0,
search_session: OverlaySearchSession::default(),
hotkey_issue_status,
event_rx,
is_running,
tray_gm_tx,
tray_hi_tx,
hotkey_listener: hotkey_listener.clone(),
event_tx: event_tx.clone(),
hotkey_check_counter: 0,
last_memory_log: Instant::now(),
};
let worker_join = std::thread::Builder::new()
.name("nex-runtime".to_string())
.spawn(move || worker.run())
.map_err(|e| RuntimeError::Overlay(format!("failed to spawn runtime thread: {e}")))?;
let host_result = crate::overlay::host::run(host);
overlay.stop();
drop(hotkey_listener.lock().unwrap().take());
let _ = worker_join.join();
host_result.map_err(RuntimeError::Overlay)
}
struct RuntimeWorker {
overlay: NativeOverlayShell,
service: Arc<RwLock<CoreService>>,
runtime_config: Config,
background_index_refresh: BackgroundIndexRefresh,
plugin_registry: PluginRegistry,
search_worker: SearchWorker,
overlay_state: OverlayState,
max_results: usize,
config_watcher: RuntimeConfigWatcher,
current_results: Vec<crate::model::SearchItem>,
suppressed_uninstall_titles: Vec<String>,
pending_uninstall_confirmation: Option<PendingUninstallConfirmation>,
selected_index: usize,
last_query: String,
last_sent_generation: u64,
search_session: OverlaySearchSession,
hotkey_issue_status: Option<String>,
event_rx: crossbeam_channel::Receiver<OverlayEvent>,
is_running: Arc<AtomicBool>,
tray_gm_tx: crossbeam_channel::Sender<bool>,
tray_hi_tx: crossbeam_channel::Sender<bool>,
hotkey_listener: Arc<Mutex<Option<HotkeyListener>>>,
event_tx: crossbeam_channel::Sender<OverlayEvent>,
hotkey_check_counter: u32,
last_memory_log: Instant,
}
impl RuntimeWorker {
fn run(self) {
let shared: Rc<RefCell<Self>> = Rc::new(RefCell::new(self));
let shared_for_closure = shared.clone();
let (overlay, event_rx, is_running) = {
let guard = shared.borrow();
(
guard.overlay.clone(),
guard.event_rx.clone(),
guard.is_running.clone(),
)
};
let _ = overlay.run_message_pump(&event_rx, &is_running, move |event| {
let _ = shared_for_closure.borrow_mut().on_event(event);
});
}
fn on_event(&mut self, event: OverlayEvent) {
self.hotkey_check_counter = self.hotkey_check_counter.wrapping_add(1);
if self.last_memory_log.elapsed() >= Duration::from_secs(30) {
if let Ok(guard) = self.service.read() {
guard.log_memory_stats();
}
self.last_memory_log = Instant::now();
}
if self.hotkey_check_counter % 32 == 0 {
let needs_restart = match self.hotkey_listener.lock() {
Ok(guard) => match guard.as_ref() {
Some(listener) => !listener.is_alive(),
None => false,
},
Err(_) => false,
};
if needs_restart {
log_warn("[nex] hotkey listener thread died; attempting restart");
if let Ok(mut guard) = self.hotkey_listener.lock() {
*guard = None;
match HotkeyListener::start(&self.runtime_config.hotkey, self.event_tx.clone())
{
Ok(new_listener) => {
log_info("[nex] hotkey listener restarted successfully");
*guard = Some(new_listener);
}
Err(error) => {
log_warn(&format!(
"[nex] hotkey listener restart failed: {error}"
));
}
}
}
}
}
let was_indexing_complete = self
.background_index_refresh
.completed
.load(std::sync::atomic::Ordering::Acquire);
if let Ok(svc) = self.service.try_write() {
maybe_apply_runtime_config_reload(
&self.overlay,
&*svc,
&mut self.runtime_config,
&mut self.plugin_registry,
&mut self.search_session,
&mut self.pending_uninstall_confirmation,
&mut self.max_results,
&mut self.config_watcher,
&mut self.background_index_refresh,
);
maybe_apply_background_index_refresh(
&*svc,
&mut self.background_index_refresh,
&self.runtime_config,
);
if self.background_index_refresh.cache_applied {
svc.start_stale_pruner(&self.service);
if let Err(error) = svc.start_file_watchers(&self.service) {
log_warn(&format!("[nex] directory_watcher start failed: {error}"));
}
}
} else {
}
if !was_indexing_complete
&& self
.background_index_refresh
.completed
.load(std::sync::atomic::Ordering::Acquire)
&& !self.last_query.is_empty()
{
let pending_query = self.last_query.clone();
self.last_query.clear();
apply_query_change(
pending_query,
&self.overlay,
&self.search_worker,
&self.runtime_config,
self.max_results,
&mut self.pending_uninstall_confirmation,
&mut self.current_results,
&mut self.selected_index,
&mut self.last_query,
&mut self.last_sent_generation,
);
}
match event {
OverlayEvent::Hotkey(_) => {
log_info("[nex] hotkey_event received");
let overlay_visible = self.overlay.is_visible();
self.overlay_state.set_visible(overlay_visible);
if self.overlay.query_text().trim().starts_with('=') {
let query = self.overlay.query_text();
if let Some(expr) = query.trim().strip_prefix('=') {
let expr = expr.trim();
if let Ok(value) = crate::calculator::evaluate(expr) {
let display = format_result(value);
let status_text = if copy_to_clipboard(&display) {
format!("Copied: {display}")
} else {
format!("= {display}")
};
self.overlay.set_status_text(&status_text);
}
}
return;
}
if !overlay_visible
&& should_suppress_hotkey_for_game_mode(&self.runtime_config)
{
log_info(
"[nex] hotkey ignored because game mode is active for the foreground app",
);
return;
}
let action = self.overlay_state.on_hotkey(self.overlay.has_focus());
match action {
HotkeyAction::ShowAndFocus | HotkeyAction::FocusExisting => {
if let Ok(guard) = self.service.read() {
guard.warm_search_cache();
}
reconcile_suppressed_uninstall_titles(
&mut self.suppressed_uninstall_titles,
);
self.overlay.show_and_focus();
if self.runtime_config.clipboard_enabled {
let _ = clipboard_history::maybe_capture_latest(&self.runtime_config);
}
if self.overlay.query_text().trim().is_empty() {
set_idle_overlay_state(&self.overlay);
if let Some(issue) = self.hotkey_issue_status.as_deref() {
self.overlay.set_status_text(issue);
}
}
}
HotkeyAction::Hide => {
self.overlay.hide();
reset_overlay_session(
&self.overlay,
&mut self.current_results,
&mut self.selected_index,
);
self.pending_uninstall_confirmation = None;
self.last_query.clear();
self.last_sent_generation = 0;
self.search_session.clear();
self.search_worker.clear_session();
while self.search_worker.try_recv().is_some() {}
maybe_apply_background_index_refresh(
&*self.service.write().unwrap(),
&mut self.background_index_refresh,
&self.runtime_config,
);
}
}
}
OverlayEvent::ExternalShow => {
if let Ok(guard) = self.service.read() {
guard.warm_search_cache();
}
reconcile_suppressed_uninstall_titles(&mut self.suppressed_uninstall_titles);
self.overlay.show_and_focus();
self.overlay_state.set_visible(true);
if self.runtime_config.clipboard_enabled {
let _ = clipboard_history::maybe_capture_latest(&self.runtime_config);
}
if self.overlay.query_text().trim().is_empty() {
set_idle_overlay_state(&self.overlay);
if let Some(issue) = self.hotkey_issue_status.as_deref() {
self.overlay.set_status_text(issue);
}
}
}
OverlayEvent::ExternalQuit => {
self.overlay.hide_now();
self.last_query.clear();
self.last_sent_generation = 0;
self.search_session.clear();
self.search_worker.clear_session();
while self.search_worker.try_recv().is_some() {}
self.overlay.quit_if_running();
}
OverlayEvent::TrayToggleGameMode => {
toggle_game_mode_from_tray(&self.overlay, &mut self.runtime_config);
let _ = self.tray_gm_tx.send(self.runtime_config.game_mode_enabled);
}
OverlayEvent::TrayCheckForUpdates => {
match launch_stable_updater() {
Ok(_) => self.overlay.set_status_text("Updater launched"),
Err(error) => {
log_warn(&format!("[nex] updater launch failed from tray: {error}"));
self.overlay.set_status_text("Could not launch updater");
}
}
}
OverlayEvent::Escape => {
if self.overlay_state.on_escape() {
self.overlay.hide();
reset_overlay_session(
&self.overlay,
&mut self.current_results,
&mut self.selected_index,
);
self.pending_uninstall_confirmation = None;
self.last_query.clear();
self.last_sent_generation = 0;
self.search_session.clear();
self.search_worker.clear_session();
while self.search_worker.try_recv().is_some() {}
while self.search_worker.try_recv().is_some() {}
}
}
OverlayEvent::QueryChanged(query) => {
apply_query_change(
query,
&self.overlay,
&self.search_worker,
&self.runtime_config,
self.max_results,
&mut self.pending_uninstall_confirmation,
&mut self.current_results,
&mut self.selected_index,
&mut self.last_query,
&mut self.last_sent_generation,
);
}
OverlayEvent::SearchResultsReady => {
if self.overlay.query_text().trim().is_empty() {
let _ = self.search_worker.try_recv();
return;
}
apply_search_results(
&self.search_worker,
&self.overlay,
&self.runtime_config,
&self.background_index_refresh,
&self.suppressed_uninstall_titles,
&mut self.current_results,
&mut self.selected_index,
self.last_sent_generation,
);
}
OverlayEvent::Submit => {
if self.current_results.is_empty() {
if self.overlay.query_text().trim().is_empty() {
set_idle_overlay_state(&self.overlay);
self.overlay.show_placeholder_hint(STATUS_ROW_TYPE_TO_SEARCH);
} else {
let parsed_query = ParsedQuery::parse(
self.overlay.query_text().trim(),
self.runtime_config.search_dsl_enabled,
);
set_status_row_overlay_state(
&self.overlay,
if parsed_query.command_mode {
STATUS_ROW_NO_COMMAND_RESULTS
} else {
STATUS_ROW_NO_RESULTS
},
);
}
return;
}
if let Some(list_selection) = self.overlay.selected_index() {
self.selected_index = list_selection.min(self.current_results.len() - 1);
}
let selected = &self.current_results[self.selected_index];
if self.pending_uninstall_confirmation.is_some() {
let selected_id = selected.id.clone();
if selected_id == ACTION_UNINSTALL_CONFIRM_ID {
let Some(pending) = self.pending_uninstall_confirmation.take() else {
return;
};
self.overlay.hide_now();
self.overlay_state.on_escape();
match execute_action_selection(
&*self.service.write().unwrap(),
&self.runtime_config,
&self.plugin_registry,
&pending.uninstall_action,
) {
Ok(()) => {
track_uninstall_title_suppression(
&mut self.suppressed_uninstall_titles,
pending.uninstall_action.title.as_str(),
);
self.overlay.set_status_text("");
reset_overlay_session(
&self.overlay,
&mut self.current_results,
&mut self.selected_index,
);
self.last_query.clear();
self.last_sent_generation = 0;
self.search_session.clear();
self.search_worker.clear_session();
}
Err(error) => {
if should_suppress_failed_uninstall(error.as_str()) {
track_uninstall_title_suppression(
&mut self.suppressed_uninstall_titles,
pending.uninstall_action.title.as_str(),
);
self.current_results = pending.previous_results;
filter_suppressed_uninstall_results(
&mut self.current_results,
&self.suppressed_uninstall_titles,
);
self.selected_index = pending
.previous_selected_index
.min(self.current_results.len().saturating_sub(1));
if self.current_results.is_empty() {
set_status_row_overlay_state(
&self.overlay,
if pending.previous_command_mode {
STATUS_ROW_NO_COMMAND_RESULTS
} else {
STATUS_ROW_NO_RESULTS
},
);
} else {
let rows = overlay_rows(
&self.current_results,
pending.previous_command_mode,
);
self.overlay.set_results(&rows, self.selected_index);
}
self.overlay.set_status_text(
"Uninstall entry is stale and was hidden",
);
} else {
self.pending_uninstall_confirmation = Some(pending);
self.overlay.show_and_focus();
self.overlay
.set_status_text(&format!("Launch error: {error}"));
}
}
}
return;
}
if selected_id == ACTION_UNINSTALL_CANCEL_ID {
let Some(pending) = self.pending_uninstall_confirmation.take() else {
return;
};
self.current_results = pending.previous_results;
self.selected_index = pending
.previous_selected_index
.min(self.current_results.len().saturating_sub(1));
if self.current_results.is_empty() {
set_status_row_overlay_state(
&self.overlay,
if pending.previous_command_mode {
STATUS_ROW_NO_COMMAND_RESULTS
} else {
STATUS_ROW_NO_RESULTS
},
);
} else {
let rows = overlay_rows(
&self.current_results,
pending.previous_command_mode,
);
self.overlay.set_results(&rows, self.selected_index);
}
self.overlay.set_status_text("");
return;
}
self.pending_uninstall_confirmation = None;
}
let selected_is_uninstall = selected
.id
.starts_with(crate::uninstall_registry::ACTION_UNINSTALL_PREFIX);
if selected_is_uninstall {
let parsed_query = ParsedQuery::parse(
self.overlay.query_text().trim(),
self.runtime_config.search_dsl_enabled,
);
self.pending_uninstall_confirmation = Some(PendingUninstallConfirmation {
uninstall_action: selected.clone(),
previous_results: self.current_results.clone(),
previous_selected_index: self.selected_index,
previous_command_mode: parsed_query.command_mode,
});
self.current_results = uninstall_confirmation_results(selected);
self.selected_index = 0;
let rows = overlay_rows(&self.current_results, true);
self.overlay.set_results(&rows, self.selected_index);
self.overlay.set_status_text("");
return;
}
if selected.id == crate::action_registry::ACTION_TRIM_MEMORY_ID {
self.search_session.clear();
self.overlay.trim_runtime_memory();
self.overlay.set_status_text("Memory caches trimmed");
return;
}
match launch_overlay_selection(
&*self.service.write().unwrap(),
&self.runtime_config,
&self.plugin_registry,
&self.current_results,
self.selected_index,
self.last_query.as_str(),
) {
Ok(()) => {
self.overlay.set_status_text("");
self.overlay.hide_now();
self.overlay_state.on_escape();
reset_overlay_session(
&self.overlay,
&mut self.current_results,
&mut self.selected_index,
);
self.pending_uninstall_confirmation = None;
self.last_query.clear();
self.last_sent_generation = 0;
self.search_session.clear();
self.search_worker.clear_session();
}
Err(error) => {
self.overlay
.set_status_text(&format!("Launch error: {error}"));
}
}
}
_ => {} }
}
}
#[cfg(target_os = "windows")]
fn reset_overlay_session(
overlay: &NativeOverlayShell,
current_results: &mut Vec<crate::model::SearchItem>,
selected_index: &mut usize,
) {
overlay.clear_query_text();
current_results.clear();
*selected_index = 0;
set_idle_overlay_state(overlay);
}
#[cfg(target_os = "windows")]
fn apply_query_change(
query: String,
overlay: &NativeOverlayShell,
search_worker: &SearchWorker,
runtime_config: &Config,
max_results: usize,
pending_uninstall_confirmation: &mut Option<PendingUninstallConfirmation>,
current_results: &mut Vec<crate::model::SearchItem>,
selected_index: &mut usize,
last_query: &mut String,
last_sent_generation: &mut u64,
) {
*pending_uninstall_confirmation = None;
let mut query = query;
if let Some(expanded) = maybe_expand_uninstall_quick_shortcut(&query, last_query.as_str()) {
overlay.set_query_text(&expanded);
query = expanded;
}
let trimmed = query.trim();
if trimmed.is_empty() {
current_results.clear();
*selected_index = 0;
last_query.clear();
*last_sent_generation = last_sent_generation.wrapping_add(1);
*pending_uninstall_confirmation = None;
set_idle_overlay_state(overlay);
return;
}
if let Some(expr) = trimmed.strip_prefix('=') {
let expr = expr.trim();
if !expr.is_empty() {
*last_query = trimmed.to_string();
*last_sent_generation = last_sent_generation.wrapping_add(1);
current_results.clear();
*selected_index = 0;
match crate::calculator::evaluate(expr) {
Ok(value) => {
let display = format_result(value);
let row = OverlayRow {
role: OverlayRowRole::Calculator,
result_index: Some(0),
kind: "calculator".into(),
title: format!("= {expr}"),
path: display,
icon_path: String::new(),
};
overlay.set_results(&[row], 0);
}
Err(error) => {
let row = OverlayRow {
role: OverlayRowRole::Status,
result_index: None,
kind: String::new(),
title: format!("{error}"),
path: String::new(),
icon_path: String::new(),
};
overlay.set_results(&[row], 0);
}
}
}
return;
}
if trimmed == last_query {
return;
}
*last_query = trimmed.to_string();
let parsed_query = ParsedQuery::parse(trimmed, runtime_config.search_dsl_enabled);
let query_result_limit = result_limit_for_query(max_results, &parsed_query);
let gen = search_worker.send_request(parsed_query, query_result_limit);
*last_sent_generation = gen;
}
#[cfg(target_os = "windows")]
fn apply_search_results(
search_worker: &SearchWorker,
overlay: &NativeOverlayShell,
_runtime_config: &Config,
background_index_refresh: &BackgroundIndexRefresh,
suppressed_uninstall_titles: &[String],
current_results: &mut Vec<crate::model::SearchItem>,
selected_index: &mut usize,
last_sent_generation: u64,
) {
let Some(result) = search_worker.try_recv() else {
return;
};
if result.generation < last_sent_generation {
return;
}
let command_mode = result.command_mode;
if let Some(error) = result.error {
current_results.clear();
*selected_index = 0;
overlay.set_results(&[], 0);
overlay.set_status_text(&format!("Search error: {error}"));
return;
}
let mut results = result.results;
crate::runtime_overlay_rows::dedupe_overlay_results(&mut results);
if !suppressed_uninstall_titles.is_empty() {
filter_suppressed_uninstall_results(&mut results, suppressed_uninstall_titles);
}
*current_results = results;
*selected_index = 0;
if current_results.is_empty() {
let indexing_in_progress = !background_index_refresh
.completed
.load(std::sync::atomic::Ordering::Acquire);
let message = if indexing_in_progress
&& background_index_refresh.initial_cache_empty
&& !command_mode
{
"Indexing, please wait..."
} else if command_mode {
STATUS_ROW_NO_COMMAND_RESULTS
} else {
STATUS_ROW_NO_RESULTS
};
set_status_row_overlay_state(overlay, message);
} else {
let rows = overlay_rows(current_results, command_mode);
overlay.set_results(&rows, *selected_index);
}
}
#[cfg(target_os = "windows")]
fn format_result(value: f64) -> String {
if value.is_nan() {
"NaN".into()
} else if value.is_infinite() {
if value.is_sign_positive() {
"∞".into()
} else {
"-∞".into()
}
} else if value.fract() == 0.0 && value.abs() < 1e15 {
format!("{}", value as i64)
} else if value.abs() > 1e10 || value.abs() < 1e-4 {
format!("{:.6e}", value)
} else {
let s = format!("{:.10}", value);
let trimmed = s.trim_end_matches('0');
if trimmed.ends_with('.') {
format!("{}.0", &trimmed[..trimmed.len() - 1])
} else {
trimmed.to_string()
}
}
}
#[cfg(target_os = "windows")]
fn copy_to_clipboard(text: &str) -> bool {
let wide: Vec<u16> = text.encode_utf16().collect();
let len_bytes = (wide.len() * 2) as u32;
unsafe {
let hglob = windows_sys::Win32::System::Memory::GlobalAlloc(
windows_sys::Win32::System::Memory::GMEM_MOVEABLE,
(len_bytes + 2) as usize,
);
if hglob.is_null() {
return false;
}
let lock = windows_sys::Win32::System::Memory::GlobalLock(hglob);
if lock.is_null() {
windows_sys::Win32::Foundation::GlobalFree(hglob);
return false;
}
std::ptr::copy_nonoverlapping(wide.as_ptr(), lock as *mut u16, wide.len());
windows_sys::Win32::System::Memory::GlobalUnlock(hglob);
let opened = windows_sys::Win32::System::DataExchange::OpenClipboard(std::ptr::null_mut());
if opened == 0 {
windows_sys::Win32::Foundation::GlobalFree(hglob);
return false;
}
windows_sys::Win32::System::DataExchange::EmptyClipboard();
let result = windows_sys::Win32::System::DataExchange::SetClipboardData(
13, hglob,
);
windows_sys::Win32::System::DataExchange::CloseClipboard();
if result.is_null() {
windows_sys::Win32::Foundation::GlobalFree(hglob);
return false;
}
}
true
}