Skip to content

feat: add Windows support with foreground app detection, clipboard in…#10

Merged
abhinavgautam01 merged 3 commits into
Lame-Coders:mainfrom
ArushKhasru:for_windows
Jun 19, 2026
Merged

feat: add Windows support with foreground app detection, clipboard in…#10
abhinavgautam01 merged 3 commits into
Lame-Coders:mainfrom
ArushKhasru:for_windows

Conversation

@ArushKhasru

Copy link
Copy Markdown
Contributor

This pull request introduces several improvements and fixes across error handling, input simulation, dynamic trigger processing, and Windows support. The most significant changes enhance robustness during extraction failures, implement dynamic trigger debounce logic, and improve the integration of platform-specific dependencies.

Error handling and extraction robustness:

  • Improved error recovery in ClipboardTextExtractor: If select_all, copy, or clipboard read fails during extraction, the code now collapses the selection and restores the clipboard to its original state, preventing lingering selections or corrupted clipboard content. A new helper method cleanup_failed_extraction was added for this purpose. [1] [2]
  • Updated tests to verify that selection is collapsed after failed extractions, ensuring the new error handling logic is exercised.

Input simulation and interface:

  • Added a new collapse_selection method to the InputSimulator trait and its implementations. This allows the system to programmatically remove text selections (e.g., by sending a right-arrow keystroke), which is now used for cleanup after extraction failures. [1] [2] [3] [4] [5]

Dynamic trigger debounce and pipeline processing:

  • Implemented dynamic trigger debounce logic in InputController: When a dynamic trigger is detected, the controller now waits for a configurable debounce interval before finalizing the trigger, improving reliability for triggers that require additional user input. New methods and fields (pending_dynamic_deadline, handle_pending_timeout, etc.) support this logic. [1] [2] [3] [4] [5] [6]
  • Added support in TransformationPipeline for finalizing pending dynamic triggers, including new methods and tests to ensure correct behavior. [1] [2] [3] [4]

Main loop and threading improvements:

  • Refactored the main event loop to use a background thread for handling input events and pending dynamic trigger timeouts, improving responsiveness and separation of concerns. [1] [2] [3]

Platform support and documentation:

  • Added Windows-specific dependencies (windows-sys) to Cargo.toml and updated documentation (README.md, RUNNING.md) to reference new Windows setup instructions. [1] [2] [3]

Copilot AI review requested due to automatic review settings June 19, 2026 10:47

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands Stringcast’s cross-platform runtime by adding Windows foreground-app detection, improving robustness around clipboard-based extraction failures, and introducing debounce-based finalization for dynamic triggers (e.g., ?ask: / ?translate:) via a pending-timeout mechanism.

Changes:

  • Add Windows foreground application detection (Win32) and document Windows setup/troubleshooting.
  • Add dynamic-trigger debounce with timeout-driven finalization, including main-loop refactor to support timeouts.
  • Improve clipboard extraction failure cleanup via selection collapse + clipboard restoration, and extend input simulation APIs accordingly.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/runtime.rs Exposes pending-timeout handling and updates progress marker used by the runtime pipeline.
src/platform/windows.rs Implements Win32 foreground-app detection with process image lookup and elevation checks.
src/pipeline.rs Adds methods to finalize pending dynamic triggers (buffer + foreground variants) and tests.
src/main.rs Moves event handling to a worker thread and introduces timeout-based processing for pending dynamic triggers.
src/input/simulator.rs Extends InputSimulator with collapse_selection() and implements it for Enigo/recording simulators.
src/input/controller.rs Tracks a pending dynamic-trigger deadline and finalizes pending triggers after debounce.
src/extraction/mod.rs Adds cleanup path for failed extractions to collapse selection and restore clipboard; updates tests.
RUNNING.md Links to the new Windows guide.
README.md Adds Windows documentation link.
docs/WINDOWS.md New Windows installation/usage/troubleshooting guide.
Cargo.toml Adds windows-sys as a Windows-only dependency.
Cargo.lock Locks windows-sys dependency.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/extraction/mod.rs Outdated
Comment on lines +98 to +104
thread::sleep(self.select_all_wait);
self.input.copy()?;
self.input.select_all().map_err(ExtractionError::from)?;
thread::sleep(self.select_all_wait);
if let Err(error) = self.input.copy() {
self.cleanup_failed_extraction(&original_clipboard);
return Err(error.into());
}
Comment thread src/input/controller.rs
Comment on lines 103 to 107
InputEvent::Backspace => {
self.pending_dynamic_deadline = None;
self.buffer.backspace();
Ok(InputControllerOutcome::BufferUpdated(
self.buffer.as_str().to_string(),
Comment thread src/main.rs Outdated
Comment on lines +66 to +67
let (event_sender, event_receiver) = mpsc::channel();
let worker_log_events = log_events;
Comment thread src/main.rs Outdated
Comment on lines 100 to 102
if event_sender.send((event, received_at)).is_err() {
eprintln!("Stringcast event error: input worker stopped");
}

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated 3 comments.

Comment thread src/main.rs Outdated
let log_events = log_events();
let (event_sender, event_receiver) = mpsc::sync_channel(INPUT_EVENT_QUEUE_CAPACITY);
let worker_log_events = log_events;
thread::spawn(move || loop {
Comment thread src/platform/windows.rs
Comment on lines +34 to +53
fn foreground_app() -> Result<ForegroundApp, PlatformContextError> {
let hwnd = unsafe { GetForegroundWindow() };
if hwnd.is_null() {
return Err(PlatformContextError::Unavailable);
}

let process_id = foreground_process_id(hwnd)?;
let process = ProcessHandle::open(process_id)?;
let process_image_path = query_process_image_path(process.raw())?;
let app_id = executable_name(&process_image_path)?;
let elevated = process_blocks_unelevated_access(process.raw());

Ok(ForegroundApp {
app_id,
window_id: Some(format!("{:p}", hwnd)),
display_name: Some(process_image_path),
secure_input: false,
elevated,
})
}
Comment thread src/extraction/mod.rs Outdated
}
};

self.clipboard.restore(&original_clipboard)?;
@abhinavgautam01

Copy link
Copy Markdown
Member

thanks @ArushKhasru

great work adding Windows support with foreground app detection, improving clipboard extraction error handling with graceful cleanup and implementing dynamic trigger debounce logic for commands like ?ask: / ?translate:. The main loop refactor to use a background worker thread is a nice touch too...

but as you said currently it runs with double ?? instead of single ?, we will check that out in a follow-up issue
merging for now...

@abhinavgautam01 abhinavgautam01 merged commit b40af3b into Lame-Coders:main Jun 19, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants