Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion apps/rsnap/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ mod shell;
#[cfg(target_os = "macos")]
use std::sync::{
Arc,
atomic::{AtomicBool, Ordering},
atomic::{AtomicBool, AtomicU64, Ordering},
};

use color_eyre::eyre::Result;
Expand Down Expand Up @@ -81,6 +81,10 @@ struct App {
#[cfg(target_os = "macos")]
overlay_stream_event_pending: Arc<AtomicBool>,
#[cfg(target_os = "macos")]
latest_deferred_ocr_generation: Arc<AtomicU64>,
#[cfg(target_os = "macos")]
pending_deferred_ocr_generation: Arc<AtomicU64>,
#[cfg(target_os = "macos")]
overlay_session_generation: u64,
#[cfg(target_os = "macos")]
startup_permissions_checked: bool,
Expand Down Expand Up @@ -132,6 +136,10 @@ impl App {
#[cfg(target_os = "macos")]
overlay_stream_event_pending: Arc::new(AtomicBool::new(false)),
#[cfg(target_os = "macos")]
latest_deferred_ocr_generation: Arc::new(AtomicU64::new(0)),
#[cfg(target_os = "macos")]
pending_deferred_ocr_generation: Arc::new(AtomicU64::new(0)),
#[cfg(target_os = "macos")]
overlay_session_generation: 0,
#[cfg(target_os = "macos")]
startup_permissions_checked: false,
Expand Down
118 changes: 117 additions & 1 deletion apps/rsnap/src/app/capture.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
#[cfg(target_os = "macos")]
use std::sync::Arc;
use std::sync::atomic::AtomicU64;
#[cfg(target_os = "macos")]
use std::sync::atomic::Ordering;
#[cfg(target_os = "macos")]
use std::sync::{Arc, Mutex};
#[cfg(target_os = "macos")]
use std::thread::Builder;
#[cfg(target_os = "macos")]
use std::time::Duration;
use std::time::Instant;

Expand All @@ -21,6 +25,8 @@ use crate::app::scroll_input_macos::{
};
#[cfg(target_os = "macos")]
use crate::permissions_macos;
#[cfg(target_os = "macos")]
use rsnap_overlay::DeferredTextRecognitionRequest;
use rsnap_overlay::{HudAnchor, OverlayConfig, OverlayControl, OverlayExit, OverlaySession};

#[cfg(target_os = "macos")]
Expand Down Expand Up @@ -119,6 +125,9 @@ impl App {
#[cfg(target_os = "macos")]
{
self.overlay_session_generation = self.overlay_session_generation.wrapping_add(1);

self.pending_deferred_ocr_generation
.store(self.overlay_session_generation, Ordering::Release);
}

let scroll_input_reset_ms = self.reset_scroll_input_for_capture_start();
Expand All @@ -133,6 +142,13 @@ impl App {
Ok(()) => {
let overlay_start_ms = overlay_start_started_at.elapsed().as_millis();

#[cfg(target_os = "macos")]
{
self.latest_deferred_ocr_generation
.store(self.overlay_session_generation, Ordering::Release);
self.pending_deferred_ocr_generation.store(0, Ordering::Release);
}

tracing::info!(
op = "capture.start_phase_timing",
requested_by = %requested_by,
Expand All @@ -157,6 +173,8 @@ impl App {
Err(err) => {
let overlay_start_ms = overlay_start_started_at.elapsed().as_millis();

#[cfg(target_os = "macos")]
self.pending_deferred_ocr_generation.store(0, Ordering::Release);
#[cfg(target_os = "macos")]
{
self.scroll_input_shared_state.set_enabled(false);
Expand Down Expand Up @@ -338,6 +356,73 @@ impl App {
"Recognized text copied to clipboard."
);
},
#[cfg(target_os = "macos")]
OverlayExit::DeferredTextRecognition(request) => {
let request_id = request.request_id;
let request_generation = self.overlay_session_generation;
let latest_deferred_ocr_generation =
Arc::clone(&self.latest_deferred_ocr_generation);
let pending_deferred_ocr_generation =
Arc::clone(&self.pending_deferred_ocr_generation);
let request_slot = Arc::new(Mutex::new(Some(request)));
let request_slot_for_worker = Arc::clone(&request_slot);
let latest_deferred_ocr_generation_for_worker =
Arc::clone(&latest_deferred_ocr_generation);
let pending_deferred_ocr_generation_for_worker =
Arc::clone(&pending_deferred_ocr_generation);

match Builder::new().name(format!("rsnap-ocr-{request_id}")).spawn(move || {
let Some(request) =
Self::take_deferred_text_recognition_request(&request_slot_for_worker)
else {
tracing::warn!(
request_id = request_id,
"Deferred OCR request was unavailable when the background worker started."
);

return;
};

Self::process_deferred_text_recognition_request(
request,
latest_deferred_ocr_generation_for_worker,
pending_deferred_ocr_generation_for_worker,
request_generation,
);
}) {
Ok(_handle) => {
tracing::info!(
request_id = request_id,
"Capture handed OCR work to the background worker."
);
},
Err(err) => {
tracing::warn!(
request_id,
Comment thread
yvette-carlisle marked this conversation as resolved.
error = %err,
"Failed to start the background OCR worker; running deferred OCR inline."
);

let Some(request) =
Self::take_deferred_text_recognition_request(&request_slot)
else {
tracing::warn!(
request_id = request_id,
"Deferred OCR request was unavailable after background worker startup failed."
);

return;
};

Self::process_deferred_text_recognition_request(
request,
latest_deferred_ocr_generation,
pending_deferred_ocr_generation,
request_generation,
);
},
}
},
OverlayExit::Saved(path) => {
tracing::info!(path = %path.display(), "Capture saved to file.");
},
Expand Down Expand Up @@ -365,6 +450,37 @@ impl App {
Ok(true)
}

#[cfg(target_os = "macos")]
fn process_deferred_text_recognition_request(
request: DeferredTextRecognitionRequest,
latest_deferred_ocr_generation: Arc<AtomicU64>,
pending_deferred_ocr_generation: Arc<AtomicU64>,
request_generation: u64,
) {
let _ = rsnap_overlay::process_deferred_text_recognition_for_latest_capture(
request,
latest_deferred_ocr_generation,
pending_deferred_ocr_generation,
request_generation,
);
}

#[cfg(target_os = "macos")]
fn take_deferred_text_recognition_request(
request_slot: &Mutex<Option<DeferredTextRecognitionRequest>>,
) -> Option<DeferredTextRecognitionRequest> {
match request_slot.lock() {
Ok(mut guard) => guard.take(),
Err(poisoned) => {
tracing::warn!(
"Deferred OCR request slot was poisoned while recovering the request."
);

poisoned.into_inner().take()
},
}
}

#[cfg(target_os = "macos")]
fn prepare_external_scroll_input(
shared_state: &Arc<SharedScrollInputState>,
Expand Down
Loading
Loading