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
81 changes: 80 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ repository = "https://github.com/RustCastLabs/rustcast"
[dependencies]
arboard = "3.6.1"
# xdg-desktop-portal ScreenCast (Wayland window/monitor recording)
ashpd = { version = "0.13.13", default-features = false, features = ["tokio", "screencast"] }
ashpd = { version = "0.13.13", default-features = false, features = ["tokio", "screencast", "screenshot"] }
crossbeam-channel = "0.5.15"
dirs = "5.0"
emojis = "0.8.0"
Expand All @@ -22,6 +22,8 @@ log = "0.4.29"
minreq = { version = "2.14.1", features = ["https"] }
once_cell = "1.21.3"
rand = "0.9.2"
# QR / barcode reading in the screenshot editor (pure Rust, tiny)
rqrr = "0.11"
rayon = "1.11.0"
rfd = "0.17.2"
serde = { version = "1.0.228", features = ["derive"] }
Expand All @@ -38,6 +40,9 @@ x11rb = { version = "0.13.2", features = ["xtest", "randr", "composite", "shm",
# tray-icon on Linux drives a GTK event loop
[target.'cfg(target_os = "linux")'.dependencies]
gtk = "0.18"
# Text rendering (font fallback, any script, emoji) in the screenshot editor;
# links the pango-cairo library GTK already loads.
pangocairo = "0.18"

[dev-dependencies]
tempfile = "3.23.0"
6 changes: 6 additions & 0 deletions FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,9 @@
1. Jev — a plain-words command operator (`jev open downloads`, `jev record firefox`, …)
1. Screen recorder with window lock, aspect lock, minimize-proof recording and
adding extra windows into a locked recording (`Super+Shift+R`)
1. Screenshot studio (`Super+Shift+S`): frozen-screen region / window / full-screen
capture with a pixel magnifier, 12 annotation tools (arrow, line, rectangle,
ellipse, pen, highlighter, text, numbered steps, pixelate/blur/solid censor,
spotlight, colour picker, select & move), undo/redo, copy / save / save as,
pin to screen, beautify, delayed capture, quick capture, annotate existing images
1. Copy text from screen — OCR (`Super+Shift+T`) with translate, search and QR codes
71 changes: 62 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,43 @@ Rust-powered productivity launcher, plus these new features:
a large preview with details, All / Text / Images filters (`←` `→`), typing
to search, `↑` `↓` to browse, `Enter` to copy, `Ctrl+1…9` for quick picks. History is **persisted to disk** under
`~/.local/share/rustcast/clipboard` and survives restarts.
2. **Screenshot thumbnail with real drag-and-drop** — take a region screenshot with
`Super+Shift+S` (or use PrintScreen). A thumbnail pops up in the **bottom-left
corner**; click it to copy the image, or **drag it straight into any application**
(browser, chat, file manager) as a PNG file via the XDND protocol.

3. **Jev, the command operator** — type `jev` and say what you want in plain words.
2. **Screenshots with a built-in editor** — `Super+Shift+S` freezes the screen.
Drag to select an area or click a window (`F` for the whole screen); a magnifier
shows exact pixels and colours. Then annotate in place:

| Key | Tool | Key | Tool |
|---|---|---|---|
| `A` | Arrow | `T` | Text (click again to re-edit) |
| `L` | Line | `N` | Numbered steps 1, 2, 3… |
| `R` | Rectangle (outline / filled) | `B` | Censor: pixelate · blur · solid |
| `O` | Ellipse | `H` | Spotlight (dim everything else) |
| `P` | Pen | `I` | Colour picker (copies `#RRGGBB`) |
| `M` | Highlighter | `V` | Select, move, recolour, delete |

`1`–`8` pick a colour, `Shift` draws straight lines / squares, arrow keys nudge
the selection, `Ctrl+Z` / `Ctrl+Shift+Z` undo / redo. Finish with
`Enter` / `Ctrl+C` (copy), `Ctrl+S` (save), `Ctrl+Shift+S` (save as),
`Ctrl+P` (**pin** it on top of all windows), `Ctrl+T` (**copy the text**, OCR)
or `Ctrl+B` (**beautify**: gradient backdrop, padding, rounded corners, shadow).

Every capture then pops up as a thumbnail in the **bottom-left corner** —
**drag it straight into any application**, double-click to annotate it again,
or right-click for Copy / Pin / Copy Text / Show in Folder / Delete.
Captures also land in the clipboard history.

3. **Copy text from anywhere (OCR)** — `Super+Shift+T`, select the text, done: it
is on your clipboard (and in clipboard history) and shown in a small window
where you can fix it, **translate** it or search it. QR codes in the selection
are decoded too. Works on dark themes and terminals, any Tesseract language
(`ocr_languages = "eng+hin"`). Built for low-end machines: the engine runs only
for the fraction of a second it needs (~40 MB, then fully released), the crop is
piped in as compact grayscale — nothing stays in memory.

More capture modes in the launcher: *Capture Window*, *Capture Full Screen*,
*Quick Capture* (copy instantly), *Capture Area in 3 / 5 / 10 Seconds*,
*Open Screenshots Folder*.

4. **Jev, the command operator** — type `jev` and say what you want in plain words.
Jev turns it into actions you run with Enter:

| You type | Jev does |
Expand All @@ -32,7 +63,7 @@ Rust-powered productivity launcher, plus these new features:
| `jev open downloads and firefox then show desktop` | several steps → a "Run all" row |

Type just `jev` for examples.
4. **Screen recorder** (`Super+Shift+R`) — opens a recorder view laid out for the
5. **Screen recorder** (`Super+Shift+R`) — opens a recorder view laid out for the
job: screen cards, a grid of window cards, switches for the options, and — while
recording — a live banner with the timer and a big Stop button:
- **Lock onto a window**: the recording follows that one app. Windows dragged
Expand Down Expand Up @@ -109,13 +140,16 @@ cargo build --release
Runtime/build dependencies (Debian/Ubuntu names):

```sh
sudo apt install libgtk-3-dev libxcb1-dev libxtst-dev gnome-screenshot \
sudo apt install libgtk-3-dev libxcb1-dev libxtst-dev tesseract-ocr \
ffmpeg gstreamer1.0-tools gstreamer1.0-pipewire libnotify-bin
```

- `libgtk-3-dev` / `ayatana-appindicator` — tray icon
- `libxtst` — paste injection (XTEST)
- `gnome-screenshot` — region capture for the screenshot feature
- `tesseract-ocr` — text recognition (add `tesseract-ocr-<lang>` for more
languages); optional `translate-shell` translates OCR text in place
- `xdg-desktop-portal` — screen capture on Wayland (fallbacks: `grim`,
`gnome-screenshot`, `spectacle`); on X11 the screen is read directly
- `ffmpeg` — video encoding for the screen recorder
- `gstreamer1.0-pipewire` — Wayland (portal) recordings
- X11/XCB — windowing, EWMH tiling, XDND drag source (via the pure-Rust `x11rb`)
Expand All @@ -127,6 +161,7 @@ sudo apt install libgtk-3-dev libxcb1-dev libxtst-dev gnome-screenshot \
| Toggle launcher | `Alt+Space` |
| Clipboard history | `Super+Shift+C` |
| Screenshot capture | `Super+Shift+S` |
| Copy text from screen (OCR) | `Super+Shift+T` |
| Screen recorder (again to stop) | `Super+Shift+R` |

All are configurable in `~/.config/rustcast/config.toml`.
Expand All @@ -138,8 +173,19 @@ the same schema as upstream RustCast, with these added fields:

```toml
screenshot_hotkey = "SUPER+SHIFT+S"
ocr_hotkey = "SUPER+SHIFT+T"
recorder_hotkey = "SUPER+SHIFT+R"

[screenshot]
save_dir = "~/Pictures/Screenshots"
format = "png" # png, jpg or webp
jpeg_quality = 90
enter_action = "copy" # what Enter does in the overlay: copy or save
show_magnifier = true
window_snap = true # click a window to capture it (X11)
ocr_languages = "eng" # Tesseract codes, e.g. "eng+hin+deu"
translate_to = "" # empty = system language

[recorder]
fps = 30
aspect_lock = true # fit every frame into output_width × output_height
Expand Down Expand Up @@ -182,6 +228,13 @@ minimized and other-workspace windows keep recording and are restored.
RustCast can't paint itself out: the ● REC pill is not shown (stop with the
hotkey) and opening the launcher mid-recording will appear in the video.
- App launching uses `.desktop` entries (`gio launch`) and `xdg-open`.
- **Screenshots on Wayland** are taken through the desktop portal; clicking a
window to capture it needs X11 (on Wayland, drag around the window instead).
The overlay covers the monitor under the pointer.

Any capture mode can be bound to a key of your own (e.g. Print) by running
`rustcast rustcast://capture/<mode>` with `<mode>` = `area`, `window`,
`fullscreen`, `quick` or `ocr`.

## Brand

Expand Down
6 changes: 6 additions & 0 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,9 @@ pub enum FileDialogAction {
pub enum ResetField {
ToggleHotkey,
ClipboardHotkey,
ScreenshotHotkey,
OcrHotkey,
OcrLanguages,
Placeholder,
SearchUrl,
DebounceDelay,
Expand Down Expand Up @@ -381,6 +384,9 @@ pub enum SetConfigFields {
ToDefault,
ToggleHotkey(String),
ClipboardHotkey(String),
ScreenshotHotkey(String),
OcrHotkey(String),
OcrLanguages(String),
PlaceHolder(String),
SearchUrl(String),
ClipboardHistory(bool),
Expand Down
74 changes: 74 additions & 0 deletions src/app/apps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,80 @@ impl App {
]
}

/// Screenshot, annotation and OCR commands.
pub fn capture_apps() -> Vec<App> {
let icons = icns_data_to_handle(ICNS_ICON.to_vec());
let actions: &[(&str, &str, &str, u64)] = &[
("Capture Area", "screenshot capture area region", "area", 0),
("Capture Window", "screenshot capture window", "window", 0),
(
"Capture Full Screen",
"screenshot capture full screen",
"fullscreen",
0,
),
(
"Quick Capture (copy instantly)",
"screenshot quick capture copy",
"quick",
0,
),
(
"Copy Text from Screen (OCR)",
"ocr copy text from screen extract read scan",
"ocr",
0,
),
(
"Capture Area in 3 Seconds",
"screenshot timer delay 3 seconds",
"area",
3,
),
(
"Capture Area in 5 Seconds",
"screenshot timer delay 5 seconds",
"area",
5,
),
(
"Capture Area in 10 Seconds",
"screenshot timer delay 10 seconds",
"area",
10,
),
];
let mut apps: Vec<App> = actions
.iter()
.map(|(name, search, mode, delay)| App {
ranking: 0,
open_command: AppCommand::Function(Function::Capture {
mode: mode.to_string(),
delay: *delay,
}),
desc: "Screenshot".to_string(),
icons: icons.clone(),
display_name: name.to_string(),
search_name: search.to_string(),
})
.collect();
apps.push(App {
ranking: 0,
open_command: AppCommand::Function(Function::OpenRawUrl(
crate::snap::load_config()
.screenshot
.save_dir()
.to_string_lossy()
.to_string(),
)),
desc: "Screenshot".to_string(),
icons,
display_name: "Open Screenshots Folder".to_string(),
search_name: "screenshots folder open".to_string(),
});
apps
}

/// Window tiling actions (12 positions)
pub fn window_apps() -> Vec<App> {
use crate::platform::window::TilePosition;
Expand Down
Loading
Loading