From 5133da8589885cc31ba025b2b7b7602793376e6f Mon Sep 17 00:00:00 2001 From: Atliac <53632092+Atliac@users.noreply.github.com> Date: Tue, 15 Sep 2026 17:53:59 +0000 Subject: [PATCH 01/11] Add beginner mdBook tutorial and GitHub Pages deployment workflow --- .github/workflows/docs.yml | 79 +++++++++++++++++++++++++++ book.toml | 13 +++++ docs/SUMMARY.md | 8 +++ docs/capturing_frames.md | 81 ++++++++++++++++++++++++++++ docs/configuration.md | 76 ++++++++++++++++++++++++++ docs/examples.md | 106 +++++++++++++++++++++++++++++++++++++ docs/getting_started.md | 61 +++++++++++++++++++++ docs/index.md | 21 ++++++++ docs/selecting_targets.md | 58 ++++++++++++++++++++ 9 files changed, 503 insertions(+) create mode 100644 .github/workflows/docs.yml create mode 100644 book.toml create mode 100644 docs/SUMMARY.md create mode 100644 docs/capturing_frames.md create mode 100644 docs/configuration.md create mode 100644 docs/examples.md create mode 100644 docs/getting_started.md create mode 100644 docs/index.md create mode 100644 docs/selecting_targets.md diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..c15ddc5 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,79 @@ +name: CI & Deploy + +on: + push: + branches: + - main + pull_request: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +jobs: + # --- JOB 1: TEST --- + test: + name: Run mdbook test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + - name: Install Rust + run: | + rustup set profile minimal + rustup toolchain install stable + rustup default stable + + - name: Install latest mdbook + run: | + tag=$(curl 'https://api.github.com/repos/rust-lang/mdbook/releases/latest' | jq -r '.tag_name') + url="https://github.com/rust-lang/mdbook/releases/download/${tag}/mdbook-${tag}-x86_64-unknown-linux-gnu.tar.gz" + mkdir bin + curl -sSL $url | tar -xz --directory=bin + echo "$(pwd)/bin" >> $GITHUB_PATH + + - name: Run tests + run: mdbook test + + # --- JOB 2: DEPLOY --- + deploy: + name: Deploy to GitHub Pages + runs-on: ubuntu-latest + needs: test # This ensures Deploy ONLY runs if Test passes! + # This ensures Deploy ONLY runs on the main branch, not on PRs + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. + # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. + concurrency: + group: "pages" + cancel-in-progress: false + + steps: + - uses: actions/checkout@v7 + with: + fetch-depth: 0 + + - name: Install latest mdbook + run: | + tag=$(curl 'https://api.github.com/repos/rust-lang/mdbook/releases/latest' | jq -r '.tag_name') + url="https://github.com/rust-lang/mdbook/releases/download/${tag}/mdbook-${tag}-x86_64-unknown-linux-gnu.tar.gz" + mkdir bin + curl -sSL $url | tar -xz --directory=bin + echo "$(pwd)/bin" >> $GITHUB_PATH + + - name: Build Book + run: mdbook build + + - name: Setup Pages + uses: actions/configure-pages@v6 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v5 + with: + path: "book" # The default mdbook output folder + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v5 diff --git a/book.toml b/book.toml new file mode 100644 index 0000000..56a4e29 --- /dev/null +++ b/book.toml @@ -0,0 +1,13 @@ +[book] +authors = ["Atliac"] +language = "en" +src = "docs" +title = "wgc Tutorial" + +[build] +build-dir = "book" +create-missing = true + +[output.html] +git-repository-url = "https://github.com/Atliac/wgc" +edit-url-template = "https://github.com/Atliac/wgc/edit/main/docs/{path}" diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md new file mode 100644 index 0000000..151170d --- /dev/null +++ b/docs/SUMMARY.md @@ -0,0 +1,8 @@ +# Summary + +[Introduction](index.md) +[Getting Started](getting_started.md) +[Selecting Targets](selecting_targets.md) +[Configuration & Capabilities](configuration.md) +[Capturing Frames](capturing_frames.md) +[Examples & Practical Use](examples.md) diff --git a/docs/capturing_frames.md b/docs/capturing_frames.md new file mode 100644 index 0000000..fbbea0f --- /dev/null +++ b/docs/capturing_frames.md @@ -0,0 +1,81 @@ +# Capturing Frames + +`Wgc` is an iterator over captured frames. When iterating over `Wgc`, each step yields a `Result`. + +## The `Frame` Type + +Each `Frame` provides information about the captured frame and methods for extracting raw pixel data or accessing the underlying Direct3D surface texture. + +### Frame Properties + +- `frame.size()`: Returns `FrameSize { width, height }` of the captured frame in pixels. +- `frame.system_relative_time()`: Returns the capture timestamp (`Duration` since system startup via QueryPerformanceCounter). + +### Accessing Pixels + +#### 1. Native Size Pixels (`pixels`) + +Reads the raw pixel buffer at the captured frame's native resolution. + +```rust,ignore +use wgc::*; + +fn main() -> anyhow::Result<()> { + let item = new_item_with_picker(None)?; + let wgc = Wgc::new(item, Default::default())?; + + for frame in wgc.take(1) { + let frame = frame?; + let size = frame.size()?; + let pixels: Vec = frame.pixels()?; + + println!("Read {} bytes (width: {}, height: {})", pixels.len(), size.width, size.height); + } + Ok(()) +} +``` + +#### 2. Resolution-Fitted Pixels (`pixels_fitted`) + +Scales the frame to fit a target `FrameSize` while preserving aspect ratio. Any remaining space is letterboxed with gray borders. This is ideal for Machine Learning (e.g. YOLO/ResNet) and computer vision pipelines that require constant input dimensions. + +```rust,ignore +use wgc::*; + +fn main() -> anyhow::Result<()> { + let item = new_item_with_picker(None)?; + let wgc = Wgc::new(item, Default::default())?; + let target_size = FrameSize { width: 512, height: 512 }; + + for frame in wgc.take(1) { + let frame = frame?; + let fitted_pixels: Vec = frame.pixels_fitted(target_size)?; + + // Guaranteed buffer length: width * height * 4 (RGBA8/BGRA8) + assert_eq!(fitted_pixels.len(), (512 * 512 * 4) as usize); + } + Ok(()) +} +``` + +### Direct3D 11 Surface Access (Zero-Copy) + +For low-latency GPU workflows (e.g., Direct3D rendering, video encoding with NVENC/AMF, or Direct2D drawing), you can access the underlying `ID3D11Texture2D` texture directly: + +```rust,ignore +use wgc::*; + +fn main() -> anyhow::Result<()> { + let item = new_item_with_picker(None)?; + let wgc = Wgc::new(item, Default::default())?; + + for frame in wgc.take(1) { + let frame = frame?; + + // Direct3D 11 surface access + let surface = frame.surface()?; // Windows::Graphics::DirectX::Direct3D11::IDirect3DSurface + let texture = frame.texture()?; // windows::Win32::Graphics::Direct3D11::ID3D11Texture2D + } + Ok(()) +} +``` diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..d0085fe --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,76 @@ +# Configuration & Capabilities + +`wgc` allows fine-grained customization of capture sessions using `WgcSettings`. Additionally, runtime capability functions in `wgc::capabilities` let you check which features are supported on the host Windows system. + +## `WgcSettings` Configuration + +`WgcSettings` controls frame formats, buffer queue length, scaling interpolation, and optional capture features. + +```rust,ignore +use std::time::Duration; +use wgc::settings::{FrameInterpolationMode, PixelFormat, WgcSettings}; + +let mut settings = WgcSettings::default(); + +// 1. Pixel Format (RGBA8 or BGRA8) +settings.pixel_format = PixelFormat::RGBA8; + +// 2. Buffer Queue Length (number of frames queued in memory) +settings.frame_queue_length = 2; + +// 3. Scaling Interpolation Mode (for fitted letterbox scaling) +settings.frame_interpolation_mode = FrameInterpolationMode::Linear; + +// 4. Optional Windows 10/11 features (must check capabilities first!) +settings.capture_cursor = Some(false); // Hide mouse cursor +settings.display_border = Some(false); // Hide yellow capture border +settings.include_secondary_windows = Some(true); // Include popups/child windows +settings.min_update_interval = Some(Duration::from_millis(16)); // Throttle frame rate (~60 FPS) +``` + +### Interpolation Modes + +When using resolution scaling / letterboxing (`pixels_fitted`), you can set `frame_interpolation_mode` to one of the following: + +- `NearestNeighbor`: Fastest processing, lower visual fidelity. +- `Linear`: Balanced performance and quality (default). +- `Cubic`: Smooth 16-sample interpolation. +- `MultiSampleLinear`: Anti-aliasing for small scale-downs. +- `HighQualityCubic`: Best visual quality for significant downscaling. + +--- + +## Checking System Capabilities + +Windows Graphics Capture added several settings in newer Windows updates (such as hiding the capture border or cursor). Attempting to enable an unsupported setting on older Windows builds will result in a runtime error. + +You can inspect capabilities using the `capabilities` module: + +```rust,ignore +use wgc::capabilities; + +fn main() -> anyhow::Result<()> { + if !capabilities::is_wgc_supported()? { + println!("Windows Graphics Capture is not supported on this OS."); + return Ok(()); + } + + if capabilities::is_cursor_configurable()? { + println!("Cursor capture toggling is supported!"); + } + + if capabilities::is_border_configurable()? { + println!("Border visibility toggling is supported!"); + } + + if capabilities::is_dirty_region_mode_configurable()? { + println!("Dirty region tracking is supported!"); + } + + if capabilities::is_min_update_interval_configurable()? { + println!("Minimum update interval configuration is supported!"); + } + + Ok(()) +} +``` diff --git a/docs/examples.md b/docs/examples.md new file mode 100644 index 0000000..600dd3d --- /dev/null +++ b/docs/examples.md @@ -0,0 +1,106 @@ +# Examples & Practical Use + +This chapter provides complete runnable examples showing how to integrate `wgc` into real applications. + +## Example 1: Saving Captured Frames to PNG + +In this example, we capture a single frame from a selected window or monitor, save the native image to disk as `native.png`, and save a letterboxed version scaled to 512x512 as `fitted.png`. + +```rust,ignore +use image::{ImageBuffer, Rgba}; +use wgc::*; + +fn main() -> anyhow::Result<()> { + // 1. Prompt user to select target + let item = new_item_with_picker(None)?; + + // 2. Initialize Wgc session + let wgc = Wgc::new(item.clone(), Default::default())?; + + let fitted_size = FrameSize { + width: 512, + height: 512, + }; + + // 3. Process 1 frame + for frame in wgc.take(1) { + let frame = frame?; + let native_size = frame.size()?; + println!("Capturing target: {}", item.DisplayName()?); + + // Native size frame + let native_pixels = frame.pixels()?; + save_png("native.png", native_size, native_pixels)?; + + // Resolution-fitted frame (letterboxed) + let fitted_pixels = frame.pixels_fitted(fitted_size)?; + save_png("fitted.png", fitted_size, fitted_pixels)?; + } + + Ok(()) +} + +fn save_png(path: &str, size: FrameSize, pixels: Vec) -> anyhow::Result<()> { + let image: ImageBuffer, Vec> = + ImageBuffer::from_raw(size.width, size.height, pixels) + .ok_or_else(|| anyhow::anyhow!("pixel buffer size mismatch"))?; + image.save(path)?; + println!("Saved image to '{path}'"); + Ok(()) +} +``` + +--- + +## Example 2: Displaying Captured Video in a Window + +You can pair `wgc` with windowing and image display crates like `show-image` to build real-time screen viewers or streaming clients. + +```rust,ignore +use show_image::{create_window, ImageInfo, ImageView}; +use wgc::*; + +#[show_image::main] +fn main() -> anyhow::Result<()> { + let item = new_item_with_picker(None)?; + let wgc = Wgc::new(item.clone(), Default::default())?; + + let title = item.DisplayName()?.to_string_lossy(); + let window = create_window(title.clone(), Default::default())?; + + for frame in wgc { + let frame = frame?; + let size = frame.size()?; + let buffer = frame.pixels()?; + + let image = ImageView::new( + ImageInfo::rgba8_premultiplied(size.width, size.height), + &buffer, + ); + window.set_image(title.clone(), image)?; + } + + Ok(()) +} +``` + +--- + +## Example 3: Running Existing Examples from Repository + +The `wgc` repository includes ready-to-run examples: + +- **Save Image**: + ```bash + cargo run --example save_image + ``` + +- **Show Image (Real-time GUI viewer)**: + ```bash + cargo run --example show_image + ``` + +- **Check System Capabilities**: + ```bash + cargo run --example capabilities + ``` diff --git a/docs/getting_started.md b/docs/getting_started.md new file mode 100644 index 0000000..4b5528d --- /dev/null +++ b/docs/getting_started.md @@ -0,0 +1,61 @@ +# Getting Started + +This chapter covers adding `wgc` to your Rust project and writing a basic screen capture script. + +## Adding `wgc` to `Cargo.toml` + +Add `wgc` to your `Cargo.toml` dependencies: + +```toml +[dependencies] +wgc = "2.0" +``` + +If you plan to process or save captured images, you might also want helper crates like `image` or `anyhow`: + +```toml +[dependencies] +wgc = "2.0" +anyhow = "1.0" +image = "0.25" +``` + +## Basic Usage Example + +Below is a complete minimal example showing how to open the system picker dialog, capture a single frame, and inspect its dimensions and raw pixel data. + +```rust,ignore +use wgc::{new_item_with_picker, Wgc}; + +fn main() -> anyhow::Result<()> { + // 1. Prompt the user to select a window or monitor to capture + let item = new_item_with_picker(None)?; + + // 2. Create a Wgc capture session with default settings + let wgc = Wgc::new(item.clone(), Default::default())?; + + // 3. Iterate over captured frames (taking 1 frame here) + for frame in wgc.take(1) { + let frame = frame?; + let size = frame.size()?; + println!( + "Captured frame from '{}' with size {}x{}", + item.DisplayName()?, + size.width, + size.height + ); + + // Access raw RGBA pixel buffer + let pixels: Vec = frame.pixels()?; + println!("Buffer size in bytes: {}", pixels.len()); + } + + Ok(()) +} +``` + +## How It Works + +1. `new_item_with_picker(None)` opens the Windows system picker dialog allowing the user to pick any window or display. +2. `Wgc::new(item, settings)` initializes the Direct3D device, capture session, and frame pool. +3. `Wgc` implements `Iterator>`, yielding available frames sequentially. diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..dd12b84 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,21 @@ +# Introduction + +Welcome to the **`wgc`** tutorial! + +`wgc` is a simple, ergonomic, and high-performance Rust wrapper for the **Windows Graphics Capture (WGC)** API (`Windows.Graphics.Capture`). It allows Rust developers to easily capture windows or entire monitors on Windows 10 and 11. + +## Key Features + +- **Realtime & AI-Optimized**: High-performance frame capture suitable for streaming, computer vision, and machine learning pipelines. +- **Ergonomic Iterator API**: Process frames sequentially with standard Rust iterator patterns (`Wgc`). +- **Interactive Picker & Explicit Handles**: Pick target windows or monitors using the native Windows UI picker or construct targets explicitly from window handles (`HWND`) or monitor handles (`HMONITOR`). +- **Configurable Formats & Letterboxing**: Supports `RGBA8` and `BGRA8` pixel formats, along with automatic resolution scaling and letterboxing (`pixels_fitted`). +- **Zero-Copy & Direct3D Access**: Direct access to underlying DirectX/Direct3D 11 surface textures and zero-copy frame handling. + +## System Requirements + +- **Operating System**: Windows 10 October 2018 Update (version 1809 / build 17763) or later. Windows 11 is recommended. +- **Rust Toolchain**: Rust 2024 edition (or compatible Rust compiler toolchain). +- **Target Platform**: `x86_64-pc-windows-msvc` or `aarch64-pc-windows-msvc`. + +In the following chapters, you will learn how to set up `wgc`, configure capture options, capture frames, and build real-world screen capture applications. diff --git a/docs/selecting_targets.md b/docs/selecting_targets.md new file mode 100644 index 0000000..40e21df --- /dev/null +++ b/docs/selecting_targets.md @@ -0,0 +1,58 @@ +# Selecting Capture Targets + +`wgc` provides multiple ways to select a target (`GraphicsCaptureItem`) for screen or window capture. + +## 1. Using the Interactive Picker + +The interactive picker displays a native Windows UI dialog that lets the user select any open window or monitor screen. + +```rust,ignore +use wgc::new_item_with_picker; + +fn main() -> anyhow::Result<()> { + // Pass None for parent window handle, or Some(parent_hwnd) to center the picker over a specific window + let item = new_item_with_picker(None)?; + println!("Selected target: {}", item.DisplayName()?); + Ok(()) +} +``` + +## 2. Target by Window Handle (`HWND`) + +If you know the window handle (`HWND`) of a specific application window, you can target it directly without showing a UI picker: + +```rust,ignore +use wgc::new_item_for_window; +use windows::Win32::Foundation::HWND; + +fn capture_window(hwnd: HWND) -> anyhow::Result<()> { + let item = new_item_for_window(hwnd)?; + println!("Capturing window: {}", item.DisplayName()?); + Ok(()) +} +``` + +## 3. Target by Monitor Handle (`HMONITOR`) + +Similarly, you can capture an entire monitor display directly by passing its `HMONITOR` handle: + +```rust,ignore +use wgc::new_item_for_monitor; +use windows::Win32::Graphics::Gdi::HMONITOR; + +fn capture_monitor(hmonitor: HMONITOR) -> anyhow::Result<()> { + let item = new_item_for_monitor(hmonitor)?; + println!("Capturing monitor: {}", item.DisplayName()?); + Ok(()) +} +``` + +## Target Properties + +The returned `GraphicsCaptureItem` is a WinRT object. You can query its properties such as display name or size: + +```rust,ignore +let name = item.DisplayName()?; +let size = item.Size()?; +println!("Target name: {}, size: {}x{}", name, size.Width, size.Height); +``` From 191ffaf00689c3a5003aa878202899db25fc945a Mon Sep 17 00:00:00 2001 From: Atliac Date: Wed, 16 Sep 2026 02:03:34 +0800 Subject: [PATCH 02/11] chore: update .gitignore and book.toml for mdBook configuration --- .gitignore | 1 + book.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index d16d776..c58a2bd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target /src/.* +/book diff --git a/book.toml b/book.toml index 56a4e29..3e2c98b 100644 --- a/book.toml +++ b/book.toml @@ -9,5 +9,6 @@ build-dir = "book" create-missing = true [output.html] +default-theme = "rust" git-repository-url = "https://github.com/Atliac/wgc" edit-url-template = "https://github.com/Atliac/wgc/edit/main/docs/{path}" From 00b2d74f976507b9f74244c55d540e6424d293eb Mon Sep 17 00:00:00 2001 From: Atliac Date: Wed, 16 Sep 2026 02:04:38 +0800 Subject: [PATCH 03/11] fix: change deployment branch from main to master in CI workflow --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index c15ddc5..a59841d 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -3,7 +3,7 @@ name: CI & Deploy on: push: branches: - - main + - master pull_request: # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages From 991b16637100a1f0660438fc72201dfebe6c30a5 Mon Sep 17 00:00:00 2001 From: Atliac Date: Wed, 16 Sep 2026 02:07:18 +0800 Subject: [PATCH 04/11] fix: update documentation URL in Cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 979fc44..9dcaa1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" authors = ["Atliac"] description = "An ergonomic Rust wrapper for Windows.Graphics.Capture API" repository = "https://github.com/atliac/wgc" -documentation = "https://deepwiki.com/Atliac/wgc" +documentation = "https://books.atliac.com/wgc" homepage = "https://github.com/atliac/wgc" readme = "README.md" keywords = ["windows", "screen-capture", "recording", "machine-learning"] From 2b2fdf735279e723c3a40d9015a0352fdbac8ac3 Mon Sep 17 00:00:00 2001 From: Atliac Date: Wed, 16 Sep 2026 02:08:30 +0800 Subject: [PATCH 05/11] fix: change CI workflow to use Windows environment for testing and deployment --- .github/workflows/docs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index a59841d..41af526 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -16,7 +16,7 @@ jobs: # --- JOB 1: TEST --- test: name: Run mdbook test - runs-on: ubuntu-latest + runs-on: windows-latest steps: - uses: actions/checkout@v7 @@ -40,7 +40,7 @@ jobs: # --- JOB 2: DEPLOY --- deploy: name: Deploy to GitHub Pages - runs-on: ubuntu-latest + runs-on: windows-latest needs: test # This ensures Deploy ONLY runs if Test passes! # This ensures Deploy ONLY runs on the main branch, not on PRs if: github.event_name == 'push' && github.ref == 'refs/heads/main' From b9d898f4f9e274e0dfdedbb866b6e4d2b5a142d0 Mon Sep 17 00:00:00 2001 From: Atliac <53632092+Atliac@users.noreply.github.com> Date: Tue, 15 Sep 2026 18:11:14 +0000 Subject: [PATCH 06/11] Fix shell compatibility in docs CI workflow and add mdBook tutorial --- .github/workflows/docs.yml | 10 +++++++--- .gitignore | 1 - Cargo.toml | 2 +- book.toml | 1 - 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 41af526..4724fc0 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -3,7 +3,7 @@ name: CI & Deploy on: push: branches: - - master + - main pull_request: # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages @@ -16,7 +16,7 @@ jobs: # --- JOB 1: TEST --- test: name: Run mdbook test - runs-on: windows-latest + runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 @@ -27,6 +27,7 @@ jobs: rustup default stable - name: Install latest mdbook + shell: bash run: | tag=$(curl 'https://api.github.com/repos/rust-lang/mdbook/releases/latest' | jq -r '.tag_name') url="https://github.com/rust-lang/mdbook/releases/download/${tag}/mdbook-${tag}-x86_64-unknown-linux-gnu.tar.gz" @@ -35,12 +36,13 @@ jobs: echo "$(pwd)/bin" >> $GITHUB_PATH - name: Run tests + shell: bash run: mdbook test # --- JOB 2: DEPLOY --- deploy: name: Deploy to GitHub Pages - runs-on: windows-latest + runs-on: ubuntu-latest needs: test # This ensures Deploy ONLY runs if Test passes! # This ensures Deploy ONLY runs on the main branch, not on PRs if: github.event_name == 'push' && github.ref == 'refs/heads/main' @@ -56,6 +58,7 @@ jobs: fetch-depth: 0 - name: Install latest mdbook + shell: bash run: | tag=$(curl 'https://api.github.com/repos/rust-lang/mdbook/releases/latest' | jq -r '.tag_name') url="https://github.com/rust-lang/mdbook/releases/download/${tag}/mdbook-${tag}-x86_64-unknown-linux-gnu.tar.gz" @@ -64,6 +67,7 @@ jobs: echo "$(pwd)/bin" >> $GITHUB_PATH - name: Build Book + shell: bash run: mdbook build - name: Setup Pages diff --git a/.gitignore b/.gitignore index c58a2bd..d16d776 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ /target /src/.* -/book diff --git a/Cargo.toml b/Cargo.toml index 9dcaa1d..979fc44 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" authors = ["Atliac"] description = "An ergonomic Rust wrapper for Windows.Graphics.Capture API" repository = "https://github.com/atliac/wgc" -documentation = "https://books.atliac.com/wgc" +documentation = "https://deepwiki.com/Atliac/wgc" homepage = "https://github.com/atliac/wgc" readme = "README.md" keywords = ["windows", "screen-capture", "recording", "machine-learning"] diff --git a/book.toml b/book.toml index 3e2c98b..56a4e29 100644 --- a/book.toml +++ b/book.toml @@ -9,6 +9,5 @@ build-dir = "book" create-missing = true [output.html] -default-theme = "rust" git-repository-url = "https://github.com/Atliac/wgc" edit-url-template = "https://github.com/Atliac/wgc/edit/main/docs/{path}" From 77fc4facc1b7836360de154be65f1f472983f63f Mon Sep 17 00:00:00 2001 From: Atliac Date: Wed, 16 Sep 2026 02:16:37 +0800 Subject: [PATCH 07/11] Revert "fix: change CI workflow to use Windows environment for testing and deployment" This reverts commit 2b2fdf735279e723c3a40d9015a0352fdbac8ac3. --- .github/workflows/docs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 41af526..a59841d 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -16,7 +16,7 @@ jobs: # --- JOB 1: TEST --- test: name: Run mdbook test - runs-on: windows-latest + runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 @@ -40,7 +40,7 @@ jobs: # --- JOB 2: DEPLOY --- deploy: name: Deploy to GitHub Pages - runs-on: windows-latest + runs-on: ubuntu-latest needs: test # This ensures Deploy ONLY runs if Test passes! # This ensures Deploy ONLY runs on the main branch, not on PRs if: github.event_name == 'push' && github.ref == 'refs/heads/main' From e3243dc6df092a8bd007961da0727f1ab6be8047 Mon Sep 17 00:00:00 2001 From: Atliac Date: Wed, 16 Sep 2026 02:19:49 +0800 Subject: [PATCH 08/11] Revert "Fix shell compatibility in docs CI workflow and add mdBook tutorial" This reverts commit b9d898f4f9e274e0dfdedbb866b6e4d2b5a142d0. --- .github/workflows/docs.yml | 10 +++------- .gitignore | 1 + Cargo.toml | 2 +- book.toml | 1 + 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 4724fc0..41af526 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -3,7 +3,7 @@ name: CI & Deploy on: push: branches: - - main + - master pull_request: # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages @@ -16,7 +16,7 @@ jobs: # --- JOB 1: TEST --- test: name: Run mdbook test - runs-on: ubuntu-latest + runs-on: windows-latest steps: - uses: actions/checkout@v7 @@ -27,7 +27,6 @@ jobs: rustup default stable - name: Install latest mdbook - shell: bash run: | tag=$(curl 'https://api.github.com/repos/rust-lang/mdbook/releases/latest' | jq -r '.tag_name') url="https://github.com/rust-lang/mdbook/releases/download/${tag}/mdbook-${tag}-x86_64-unknown-linux-gnu.tar.gz" @@ -36,13 +35,12 @@ jobs: echo "$(pwd)/bin" >> $GITHUB_PATH - name: Run tests - shell: bash run: mdbook test # --- JOB 2: DEPLOY --- deploy: name: Deploy to GitHub Pages - runs-on: ubuntu-latest + runs-on: windows-latest needs: test # This ensures Deploy ONLY runs if Test passes! # This ensures Deploy ONLY runs on the main branch, not on PRs if: github.event_name == 'push' && github.ref == 'refs/heads/main' @@ -58,7 +56,6 @@ jobs: fetch-depth: 0 - name: Install latest mdbook - shell: bash run: | tag=$(curl 'https://api.github.com/repos/rust-lang/mdbook/releases/latest' | jq -r '.tag_name') url="https://github.com/rust-lang/mdbook/releases/download/${tag}/mdbook-${tag}-x86_64-unknown-linux-gnu.tar.gz" @@ -67,7 +64,6 @@ jobs: echo "$(pwd)/bin" >> $GITHUB_PATH - name: Build Book - shell: bash run: mdbook build - name: Setup Pages diff --git a/.gitignore b/.gitignore index d16d776..c58a2bd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target /src/.* +/book diff --git a/Cargo.toml b/Cargo.toml index 979fc44..9dcaa1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" authors = ["Atliac"] description = "An ergonomic Rust wrapper for Windows.Graphics.Capture API" repository = "https://github.com/atliac/wgc" -documentation = "https://deepwiki.com/Atliac/wgc" +documentation = "https://books.atliac.com/wgc" homepage = "https://github.com/atliac/wgc" readme = "README.md" keywords = ["windows", "screen-capture", "recording", "machine-learning"] diff --git a/book.toml b/book.toml index 56a4e29..3e2c98b 100644 --- a/book.toml +++ b/book.toml @@ -9,5 +9,6 @@ build-dir = "book" create-missing = true [output.html] +default-theme = "rust" git-repository-url = "https://github.com/Atliac/wgc" edit-url-template = "https://github.com/Atliac/wgc/edit/main/docs/{path}" From 3cdc3d4e7a5974c4023e47f472cce52cd46feb04 Mon Sep 17 00:00:00 2001 From: Atliac <53632092+Atliac@users.noreply.github.com> Date: Tue, 15 Sep 2026 18:24:22 +0000 Subject: [PATCH 09/11] Add beginner mdBook tutorial and GitHub Pages deployment workflow --- .github/workflows/docs.yml | 13 ++++++++++--- .gitignore | 1 - Cargo.toml | 2 +- book.toml | 1 - 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 41af526..b61f225 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -3,6 +3,7 @@ name: CI & Deploy on: push: branches: + - main - master pull_request: @@ -16,7 +17,10 @@ jobs: # --- JOB 1: TEST --- test: name: Run mdbook test - runs-on: windows-latest + runs-on: ubuntu-latest + defaults: + run: + shell: bash steps: - uses: actions/checkout@v7 @@ -40,10 +44,13 @@ jobs: # --- JOB 2: DEPLOY --- deploy: name: Deploy to GitHub Pages - runs-on: windows-latest + runs-on: ubuntu-latest + defaults: + run: + shell: bash needs: test # This ensures Deploy ONLY runs if Test passes! # This ensures Deploy ONLY runs on the main branch, not on PRs - if: github.event_name == 'push' && github.ref == 'refs/heads/main' + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master') # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. concurrency: diff --git a/.gitignore b/.gitignore index c58a2bd..d16d776 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ /target /src/.* -/book diff --git a/Cargo.toml b/Cargo.toml index 9dcaa1d..979fc44 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" authors = ["Atliac"] description = "An ergonomic Rust wrapper for Windows.Graphics.Capture API" repository = "https://github.com/atliac/wgc" -documentation = "https://books.atliac.com/wgc" +documentation = "https://deepwiki.com/Atliac/wgc" homepage = "https://github.com/atliac/wgc" readme = "README.md" keywords = ["windows", "screen-capture", "recording", "machine-learning"] diff --git a/book.toml b/book.toml index 3e2c98b..56a4e29 100644 --- a/book.toml +++ b/book.toml @@ -9,6 +9,5 @@ build-dir = "book" create-missing = true [output.html] -default-theme = "rust" git-repository-url = "https://github.com/Atliac/wgc" edit-url-template = "https://github.com/Atliac/wgc/edit/main/docs/{path}" From 1f361a376b2b9faf2d13cabe2c4bf85cf001f907 Mon Sep 17 00:00:00 2001 From: Atliac Date: Wed, 16 Sep 2026 02:24:34 +0800 Subject: [PATCH 10/11] fix: update documentation links to point to tutorial resources --- MIGRATION.md | 5 ++--- README.md | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index 31dc1ff..cab3e64 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -1,7 +1,6 @@ # Migration Guide This document describes breaking API changes and how to update downstream code. -For the full history of changes, see [CHANGELOG.md](./CHANGELOG.md). - [v1.x → v2.0](#v1x--v20) @@ -14,7 +13,7 @@ For the full history of changes, see [CHANGELOG.md](./CHANGELOG.md). | 1 | `Frame::read_pixels(Option)` split into `Frame::pixels()` and `Frame::pixels_fitted(FrameSize)` | Rename calls (see [below](#1-frameread_pixels--framepixels--framepixels_fitted)) | | 2 | `WgcSettings` is now `#[non_exhaustive]` | Build it from `WgcSettings::default()` and assign fields (see [below](#2-wgcsettings-is-now-non_exhaustive)) | | 3 | The `tracing` Cargo feature was removed; `tracing` is a required dependency | Drop `--features tracing` and `features = ["tracing"]` | -| 4 | The `tutorial` example was removed | Use the [examples](./examples/) and [DeepWiki docs](https://deepwiki.com/Atliac/wgc) | +| 4 | The `tutorial` example was removed | Use the [examples](./examples/) and [tutorial docs](https://books.atliac.com/wgc) | ### 1. `Frame::read_pixels` → `Frame::pixels` / `Frame::pixels_fitted` @@ -178,7 +177,7 @@ RUST_LOG=wgc=debug cargo run --example save_image - Read the [save_image](./examples/save_image.rs) example, which now demonstrates both `pixels()` (native size) and `pixels_fitted()` (letterboxed scaling). - Read the [show_image](./examples/show_image.rs) example for a continuous capture loop. -- Consult the [DeepWiki documentation](https://deepwiki.com/Atliac/wgc) for a +- Consult the [tutorial documentation](https://books.atliac.com/wgc) for a narrative walkthrough of the crate. diff --git a/README.md b/README.md index e4e0e53..ba58706 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![Rust CI](https://github.com/Atliac/wgc/actions/workflows/ci.yml/badge.svg)](https://github.com/Atliac/wgc/actions/workflows/ci.yml) [![Stability: Stable](https://img.shields.io/badge/stability-stable-brightgreen)](https://github.com/atliac/wgc) [![Maintenance: Active](https://img.shields.io/badge/maintenance-active-blue)](https://github.com/atliac/wgc) -[![Doc: DeepWiki](https://img.shields.io/badge/Doc-DeepWiki-blue)](https://deepwiki.com/Atliac/wgc) +[![Docs: Tutorial](https://img.shields.io/badge/Docs-Tutorial-blue)](https://books.atliac.com/wgc) A simple and ergonomic Rust wrapper for Windows.Graphics.Capture API, enabling screen/window capture on Windows 10/11. @@ -65,8 +65,8 @@ Check out the [examples](./examples/) directory for more detailed usage examples ## Documentation +- [Tutorial](https://books.atliac.com/wgc): narrative documentation and architecture overview. - [Migration guide](./MIGRATION.md): how to upgrade from `wgc` 1.x to 2.0. -- [DeepWiki](https://deepwiki.com/Atliac/wgc): narrative documentation and architecture overview. - [docs.rs](https://docs.rs/wgc): API reference. ## License From 1b3feae67829486f038c2ff7738a55de08b0efc6 Mon Sep 17 00:00:00 2001 From: Atliac Date: Wed, 16 Sep 2026 02:27:21 +0800 Subject: [PATCH 11/11] Revert "Fix shell compatibility in docs CI workflow and add mdBook tutorial" This reverts commit b9d898f4f9e274e0dfdedbb866b6e4d2b5a142d0. --- .github/workflows/docs.yml | 7 ------- .gitignore | 1 + Cargo.toml | 2 +- book.toml | 1 + 4 files changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index b61f225..b5dedc0 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -3,7 +3,6 @@ name: CI & Deploy on: push: branches: - - main - master pull_request: @@ -18,9 +17,6 @@ jobs: test: name: Run mdbook test runs-on: ubuntu-latest - defaults: - run: - shell: bash steps: - uses: actions/checkout@v7 @@ -45,9 +41,6 @@ jobs: deploy: name: Deploy to GitHub Pages runs-on: ubuntu-latest - defaults: - run: - shell: bash needs: test # This ensures Deploy ONLY runs if Test passes! # This ensures Deploy ONLY runs on the main branch, not on PRs if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master') diff --git a/.gitignore b/.gitignore index d16d776..c58a2bd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target /src/.* +/book diff --git a/Cargo.toml b/Cargo.toml index 979fc44..9dcaa1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" authors = ["Atliac"] description = "An ergonomic Rust wrapper for Windows.Graphics.Capture API" repository = "https://github.com/atliac/wgc" -documentation = "https://deepwiki.com/Atliac/wgc" +documentation = "https://books.atliac.com/wgc" homepage = "https://github.com/atliac/wgc" readme = "README.md" keywords = ["windows", "screen-capture", "recording", "machine-learning"] diff --git a/book.toml b/book.toml index 56a4e29..3e2c98b 100644 --- a/book.toml +++ b/book.toml @@ -9,5 +9,6 @@ build-dir = "book" create-missing = true [output.html] +default-theme = "rust" git-repository-url = "https://github.com/Atliac/wgc" edit-url-template = "https://github.com/Atliac/wgc/edit/main/docs/{path}"