From 22eaa6b17447ac0f94fd7c8dbb1bb869b54aeab4 Mon Sep 17 00:00:00 2001 From: Sven Assmann Date: Tue, 17 Nov 2020 23:21:36 +0100 Subject: [PATCH] fix(window-id): closes #13 - check for window id very early - grab a screenshot before recording starts, to verify it works - present a nice error message to show what is wrong --- CHANGELOG.md | 6 ++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 9 ++++++--- src/macos/screenshot.rs | 5 ++++- src/macos/window_id.rs | 5 ++--- src/main.rs | 29 ++++++++++++++++++++--------- 7 files changed, 40 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1450408..568fd5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## 🎯 [Unreleased] +## [0.2.1] - 2020-11-17 +- improve error handling for invalid window id [issue/13] / [pull/14] + +[issue/13]: https://github.com/sassman/t-rec-rs/issues/13 +[pull/14]: https://github.com/sassman/t-rec-rs/pull/14 + ## [0.2.0] - 2020-10-12 ### Added - command line parameter for natural recording `-n` or `--natural` diff --git a/Cargo.lock b/Cargo.lock index d75eac9..9060abf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -525,7 +525,7 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "t-rec" -version = "0.2.0" +version = "0.2.1" dependencies = [ "anyhow", "clap", diff --git a/Cargo.toml b/Cargo.toml index 5ee2890..5213931 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "t-rec" -version = "0.2.0" +version = "0.2.1" authors = ["Sven Assmann "] edition = "2018" license = "GPL-3.0-only" diff --git a/README.md b/README.md index 6e9f5e6..5a6b7a7 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Blazingly fast terminal recorder that generates animated gif images for the web ## Install -**NOTE** for now `t-rec` depends on `imagemagick`, but this is going to change soon. +**NOTE** for now `t-rec` depends on `imagemagick`. ```sh ❯ brew install imagemagick @@ -53,7 +53,7 @@ or with specifying a different program to launch ```sh ❯ t-rec --help -t-rec 0.2.0 +t-rec 0.2.1 Sven Assmann Blazingly fast terminal recorder that generates animated gif images for the web written in rust. @@ -89,9 +89,11 @@ You can record not only the terminal but also every other window. There 2 ways t ```sh ❯ TERM_PROGRAM="google chrome" t-rec + Frame cache dir: "/var/folders/m8/084p1v0x4770rpwpkrgl5b6h0000gn/T/trec-74728.rUxBx3ohGiQ2" +Recording window: "Google Chrome 2" Press Ctrl+D to end recording -Recording Window: "Google Chrome 2" + ``` this is how it looks then: @@ -111,6 +113,7 @@ Code | 27600 ❯ WINDOWID=27600 t-rec Frame cache dir: "/var/folders/m8/084p1v0x4770rpwpkrgl5b6h0000gn/T/trec-77862.BMYiHNRWqv9Y" +Recording window id: 27600 Press Ctrl+D to end recording ``` diff --git a/src/macos/screenshot.rs b/src/macos/screenshot.rs index 8416fa5..5f24c8a 100644 --- a/src/macos/screenshot.rs +++ b/src/macos/screenshot.rs @@ -17,7 +17,10 @@ pub fn capture_window_screenshot(win_id: u32) -> Result { | kCGWindowImageShouldBeOpaque, ) } - .context("Cannot gather screenshot")?; + .context(format!( + "Cannot grab screenshot from CGDisplay of window id {}", + win_id + ))?; let img_ref: &CGImageRef = ℑ let (_wrong_width, h) = (img_ref.width() as u32, img_ref.height() as u32); diff --git a/src/macos/window_id.rs b/src/macos/window_id.rs index 34721c8..ab20fac 100644 --- a/src/macos/window_id.rs +++ b/src/macos/window_id.rs @@ -137,7 +137,7 @@ pub fn ls_win() -> anyhow::Result<()> { /// https://stackoverflow.com/questions/60117318/getting-window-owner-names-via-cgwindowlistcopywindowinfo-in-rust /// then some more PRs where needed: /// https://github.com/servo/core-foundation-rs/pulls?q=is%3Apr+author%3Asassman+ -pub fn get_window_id_for(terminal: String) -> Result { +pub fn get_window_id_for(terminal: String) -> Result<(u32, String)> { for term in terminal.to_lowercase().split('.') { for (window_owner, window_id, _) in window_list()? { if let DictEntryValue::_Number(window_id) = window_id { @@ -145,8 +145,7 @@ pub fn get_window_id_for(terminal: String) -> Result { let window = &window_owner.to_lowercase(); let terminal = &terminal.to_lowercase(); if window.contains(term) || terminal.contains(window) { - println!("Recording Window: {:?}", window_owner); - return Ok(window_id as u32); + return Ok((window_id as u32, window_owner)); } } } diff --git a/src/main.rs b/src/main.rs index 8380b60..e5e08dc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -52,6 +52,9 @@ fn main() -> Result<()> { env::var("SHELL").unwrap_or(default) } }; + let (win_id, window_name) = + current_win_id().context("Cannot retrieve the window id of the to be recorded window.")?; + capture_window_screenshot(win_id)?; let force_natural = args.is_present("natural-mode"); @@ -68,7 +71,7 @@ fn main() -> Result<()> { let time_codes = time_codes.clone(); let force_natural = force_natural; thread::spawn(move || -> Result<()> { - capture_thread(&rx, time_codes, tempdir, force_natural) + capture_thread(&rx, win_id, time_codes, tempdir, force_natural) }) }; let interact = thread::spawn(move || -> Result<()> { sub_shell_thread(&program).map(|_| ()) }); @@ -78,6 +81,11 @@ fn main() -> Result<()> { "Frame cache dir: {:?}", tempdir.lock().expect("Cannot lock tempdir resource").path() ); + if let Some(window) = window_name { + println!("Recording window: {:?}", window); + } else { + println!("Recording window id: {}", win_id); + } println!("Press Ctrl+D to end recording"); interact @@ -110,11 +118,11 @@ fn clear_screen() { /// stops once receiving something in rx fn capture_thread( rx: &Receiver<()>, + win_id: u32, time_codes: Arc>>, tempdir: Arc>, force_natural: bool, ) -> Result<()> { - let win_id = current_win_id()?; let duration = Duration::from_millis(250); let start = Instant::now(); let mut idle_duration = Duration::from_millis(0); @@ -192,19 +200,22 @@ fn sub_shell_thread + Clone>(program: T) -> Result { /// or by the env var 'TERM_PROGRAM' and then asking the window manager for all visible windows /// and finding the Terminal in that list /// panics if WindowId was not was not there -fn current_win_id() -> Result { +fn current_win_id() -> Result<(u32, Option)> { if env::var("WINDOWID").is_ok() { - env::var("WINDOWID") + let win_id = env::var("WINDOWID") .unwrap() .parse::() - .context("Cannot parse env variable 'WINDOWID' as number") + .context("Cannot parse env variable 'WINDOWID' as number")?; + Ok((win_id, None)) } else { let terminal = env::var("TERM_PROGRAM").context( - "Env variable 'TERM_PROGRAM' was empty but is needed for figure out the WindowId", + "Env variable 'TERM_PROGRAM' was empty but it is needed for determine the window id", + )?; + let (win_id, name) = get_window_id_for(terminal.to_owned()).context( + format!( + "Cannot determine the window id of {}. Please set env variable 'WINDOWID' and try again.", terminal), )?; - get_window_id_for(terminal).context( - "Cannot determine the WindowId of this terminal. Please set env variable 'WINDOWID' and try again.", - ) + Ok((win_id, Some(name))) } }