Skip to content

Commit 0b1715d

Browse files
committed
Add optional exit-after-capture config
1 parent 08eece3 commit 0b1715d

File tree

10 files changed

+61
-6
lines changed

10 files changed

+61
-6
lines changed

config.example.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,9 @@ format = "png"
332332
# Shortcut-specific actions may override this
333333
copy_to_clipboard = true
334334

335+
# Exit overlay after a capture completes
336+
exit_after_capture = false
337+
335338
# ═══════════════════════════════════════════════════════════════════════════════
336339
# SESSION PERSISTENCE
337340
# ═══════════════════════════════════════════════════════════════════════════════

configurator/src/app.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,12 @@ impl ConfiguratorApp {
937937
self.draft.capture_copy_to_clipboard,
938938
self.defaults.capture_copy_to_clipboard,
939939
ToggleField::CaptureCopyToClipboard,
940+
),
941+
toggle_row(
942+
"Exit overlay after capture",
943+
self.draft.capture_exit_after,
944+
self.defaults.capture_exit_after,
945+
ToggleField::CaptureExitAfter,
940946
)
941947
]
942948
.spacing(12),

configurator/src/models/config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ pub struct ConfigDraft {
6666
pub capture_filename_template: String,
6767
pub capture_format: String,
6868
pub capture_copy_to_clipboard: bool,
69+
pub capture_exit_after: bool,
6970

7071
pub session_persist_transparent: bool,
7172
pub session_persist_whiteboard: bool,
@@ -151,6 +152,7 @@ impl ConfigDraft {
151152
capture_filename_template: config.capture.filename_template.clone(),
152153
capture_format: config.capture.format.clone(),
153154
capture_copy_to_clipboard: config.capture.copy_to_clipboard,
155+
capture_exit_after: config.capture.exit_after_capture,
154156

155157
session_persist_transparent: config.session.persist_transparent,
156158
session_persist_whiteboard: config.session.persist_whiteboard,
@@ -369,6 +371,7 @@ impl ConfigDraft {
369371
config.capture.filename_template = self.capture_filename_template.clone();
370372
config.capture.format = self.capture_format.clone();
371373
config.capture.copy_to_clipboard = self.capture_copy_to_clipboard;
374+
config.capture.exit_after_capture = self.capture_exit_after;
372375

373376
config.session.persist_transparent = self.session_persist_transparent;
374377
config.session.persist_whiteboard = self.session_persist_whiteboard;
@@ -434,6 +437,7 @@ impl ConfigDraft {
434437
ToggleField::BoardAutoAdjust => self.board_auto_adjust_pen = value,
435438
ToggleField::CaptureEnabled => self.capture_enabled = value,
436439
ToggleField::CaptureCopyToClipboard => self.capture_copy_to_clipboard = value,
440+
ToggleField::CaptureExitAfter => self.capture_exit_after = value,
437441
ToggleField::SessionPersistTransparent => {
438442
self.session_persist_transparent = value;
439443
}

configurator/src/models/fields.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ pub enum ToggleField {
229229
BoardAutoAdjust,
230230
CaptureEnabled,
231231
CaptureCopyToClipboard,
232+
CaptureExitAfter,
232233
SessionPersistTransparent,
233234
SessionPersistWhiteboard,
234235
SessionPersistBlackboard,

docs/CONFIG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,9 @@ format = "png"
333333

334334
# Copy captures to clipboard in addition to saving files
335335
copy_to_clipboard = true
336+
337+
# Exit the overlay after a capture completes
338+
exit_after_capture = false
336339
```
337340

338341
**Tips:**

src/backend/mod.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,14 @@ pub mod wayland;
1010
/// # Arguments
1111
/// * `initial_mode` - Optional board mode to start in (overrides config default)
1212
/// * `freeze_on_start` - Whether to start with the overlay frozen for immediate capture pause
13-
pub fn run_wayland(initial_mode: Option<String>, freeze_on_start: bool) -> Result<()> {
14-
let mut backend = wayland::WaylandBackend::new(initial_mode, freeze_on_start)?;
13+
/// * `exit_after_capture` - Whether to exit the overlay after a capture completes
14+
pub fn run_wayland(
15+
initial_mode: Option<String>,
16+
freeze_on_start: bool,
17+
exit_after_capture: bool,
18+
) -> Result<()> {
19+
let mut backend =
20+
wayland::WaylandBackend::new(initial_mode, freeze_on_start, exit_after_capture)?;
1521
backend.init()?;
1622
backend.show()?; // show() calls run() internally
1723
backend.hide()?;
@@ -27,6 +33,6 @@ mod tests {
2733
eprintln!("WAYLAND_DISPLAY not set; skipping Wayland smoke test");
2834
return;
2935
}
30-
super::run_wayland(None, false).expect("Wayland backend should start");
36+
super::run_wayland(None, false, false).expect("Wayland backend should start");
3137
}
3238
}

src/backend/wayland/backend.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,17 +139,23 @@ fn resume_override_from_env() -> Option<bool> {
139139
pub struct WaylandBackend {
140140
initial_mode: Option<String>,
141141
freeze_on_start: bool,
142+
exit_after_capture_override: bool,
142143
/// Tokio runtime for async capture operations
143144
tokio_runtime: tokio::runtime::Runtime,
144145
}
145146

146147
impl WaylandBackend {
147-
pub fn new(initial_mode: Option<String>, freeze_on_start: bool) -> Result<Self> {
148+
pub fn new(
149+
initial_mode: Option<String>,
150+
freeze_on_start: bool,
151+
exit_after_capture_override: bool,
152+
) -> Result<Self> {
148153
let tokio_runtime = tokio::runtime::Runtime::new()
149154
.context("Failed to create Tokio runtime for capture operations")?;
150155
Ok(Self {
151156
initial_mode,
152157
freeze_on_start,
158+
exit_after_capture_override,
153159
tokio_runtime,
154160
})
155161
}
@@ -259,6 +265,8 @@ impl WaylandBackend {
259265
(Config::default(), ConfigSource::Default)
260266
}
261267
};
268+
let exit_after_capture =
269+
self.exit_after_capture_override || config.capture.exit_after_capture;
262270

263271
info!("Configuration loaded");
264272
debug!(" Color: {:?}", config.drawing.default_color);
@@ -514,6 +522,7 @@ impl WaylandBackend {
514522
capture_manager,
515523
session_options,
516524
tokio_handle,
525+
exit_after_capture,
517526
frozen_enabled: frozen_supported,
518527
preferred_output_identity,
519528
xdg_fullscreen,
@@ -773,6 +782,8 @@ impl WaylandBackend {
773782
state.show_overlay();
774783
state.capture.clear_in_progress();
775784

785+
let exit_on_success =
786+
state.exit_after_capture && matches!(&outcome, CaptureOutcome::Success(_));
776787
match outcome {
777788
CaptureOutcome::Success(result) => {
778789
// Build notification message
@@ -821,6 +832,9 @@ impl WaylandBackend {
821832
log::info!("Capture cancelled: {}", reason);
822833
}
823834
}
835+
if exit_on_success {
836+
state.input_state.should_exit = true;
837+
}
824838
}
825839

826840
// Render if configured and needs redraw, but only if no frame callback pending

src/backend/wayland/state.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ pub(in crate::backend::wayland) struct WaylandStateInit {
109109
pub capture_manager: CaptureManager,
110110
pub session_options: Option<SessionOptions>,
111111
pub tokio_handle: tokio::runtime::Handle,
112+
pub exit_after_capture: bool,
112113
pub frozen_enabled: bool,
113114
pub preferred_output_identity: Option<String>,
114115
pub xdg_fullscreen: bool,
@@ -150,6 +151,9 @@ pub(super) struct WaylandState {
150151
pub(super) frozen: FrozenState,
151152
pub(super) zoom: ZoomState,
152153

154+
// Overlay behavior
155+
pub(super) exit_after_capture: bool,
156+
153157
// Pointer cursor
154158
pub(super) themed_pointer: Option<ThemedPointer<PointerData>>,
155159
pub(super) locked_pointer: Option<ZwpLockedPointerV1>,

src/config/types.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,10 @@ pub struct CaptureConfig {
767767
/// Automatically copy screenshots to clipboard
768768
#[serde(default = "default_capture_clipboard")]
769769
pub copy_to_clipboard: bool,
770+
771+
/// Exit the overlay after a capture completes
772+
#[serde(default = "default_capture_exit_after")]
773+
pub exit_after_capture: bool,
770774
}
771775

772776
impl Default for CaptureConfig {
@@ -777,6 +781,7 @@ impl Default for CaptureConfig {
777781
filename_template: default_capture_filename(),
778782
format: default_capture_format(),
779783
copy_to_clipboard: default_capture_clipboard(),
784+
exit_after_capture: default_capture_exit_after(),
780785
}
781786
}
782787
}
@@ -802,6 +807,10 @@ fn default_capture_clipboard() -> bool {
802807
true
803808
}
804809

810+
fn default_capture_exit_after() -> bool {
811+
false
812+
}
813+
805814
/// Session persistence configuration.
806815
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
807816
pub struct SessionConfig {

src/main.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ struct Cli {
9797
)]
9898
freeze: bool,
9999

100+
/// Exit the overlay after a capture completes
101+
#[arg(long, action = ArgAction::SetTrue)]
102+
exit_after_capture: bool,
103+
100104
/// Force session resume on (persist/restore all boards + history/tool state)
101105
#[arg(long, action = ArgAction::SetTrue, conflicts_with = "no_resume_session")]
102106
resume_session: bool,
@@ -211,7 +215,7 @@ fn run() -> anyhow::Result<()> {
211215
set_runtime_session_override(session_override);
212216

213217
// Run Wayland backend
214-
backend::run_wayland(cli.mode, cli.freeze)?;
218+
backend::run_wayland(cli.mode, cli.freeze, cli.exit_after_capture)?;
215219

216220
log::info!("Annotation overlay closed.");
217221
} else {
@@ -223,13 +227,14 @@ fn run() -> anyhow::Result<()> {
223227
" wayscriber -d, --daemon Run as background daemon (bind a toggle like Super+D)"
224228
);
225229
println!(" wayscriber -a, --active Show overlay immediately (one-shot mode)");
230+
println!(" wayscriber --freeze Start overlay already frozen");
231+
println!(" wayscriber --exit-after-capture Exit overlay after a capture completes");
226232
println!(" wayscriber --no-tray Skip system tray (headless daemon)");
227233
println!(" wayscriber --about Show the About window");
228234
println!(
229235
" wayscriber --resume-session Force session resume on (all boards/history/tool state)"
230236
);
231237
println!(" wayscriber --no-resume-session Disable session resume for this run");
232-
println!(" wayscriber --freeze Start overlay already frozen");
233238
println!(" wayscriber -h, --help Show help");
234239
println!();
235240
println!("Daemon mode (recommended). Example Hyprland setup:");

0 commit comments

Comments
 (0)