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
4 changes: 2 additions & 2 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wayscriber"
version = "0.9.25"
version = "0.9.26"
edition = "2024"
rust-version = "1.98.1"
description = "Screen annotation tool for Wayland compositors"
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ The v0.9.23+ prebuilt `wayscriber` packages require glibc 2.39 and GTK 4.12. See

### Drawing and editing
- Freehand pen, highlighter, eraser (circle/rect)
- Shape pen: draw naturally and confident strokes preview and become editable lines, circles, ovals, or rectangles; other strokes remain freehand. Choose **Live Shaping Tool** in the command palette or the toolbar's Shapes picker. Adjust recognition with `[drawing] shape_recognition_sensitivity` (0-4) or the configurator's Drawing page.
- Pen smoothing: finished pen and marker strokes are cleaned up on release, so the live line never lags the cursor (`[drawing] pen_smoothing`, 0-6, or the toolbar's **Smoothing** stepper); tablet pressure values are preserved, and the level is remembered with the session
- Shapes: lines, rectangles, ellipses, polygons (with fill toggle)
- Arrows in four styles - standard, pointy, curved (drag its handle to route around what is in the way), and double-ended - with optional auto-numbered labels; step markers for walkthroughs
Expand Down
7 changes: 7 additions & 0 deletions config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ decrease_marker_opacity = ["Ctrl+Alt+ArrowDown"]
# Tool selection shortcuts (optional; keep empty to rely on modifiers)
select_selection_tool = ["V"]
select_pen_tool = ["F"]
select_live_shape_tool = []
select_marker_tool = ["H"]
select_step_marker_tool = []
select_eraser_tool = ["D"]
Expand Down Expand Up @@ -696,6 +697,7 @@ shown = []
top_tools = [
"top.tool.select",
"top.tool.pen",
"top.tool.live-shape",
"top.tool.marker",
"top.tool.step-marker",
"top.tool.eraser",
Expand Down Expand Up @@ -1116,6 +1118,11 @@ font_cycle = ["Sans", "Monospace", "Serif"]
# A session remembers the level it was saved at; this is the starting value.
pen_smoothing = 3

# Shape Pen recognition sensitivity (0 - 4): 0 is precise, 2 is balanced,
# and 4 accepts rougher lines and closed shapes. Applies to lines, ellipses,
# and rectangles; it does not change the dedicated shape tools or grid spacing.
shape_recognition_sensitivity = 2

# Default fill state for fill-capable shapes
default_fill_enabled = false

Expand Down
2 changes: 1 addition & 1 deletion configurator/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wayscriber-configurator"
version = "0.9.25"
version = "0.9.26"
edition = "2024"
rust-version = "1.98.1"

Expand Down
12 changes: 12 additions & 0 deletions configurator/src/app/pages/drawing/defaults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ pub(super) fn build(page: &mut PageBuilder) {
|value| Message::TextChanged(TextField::DrawingPenSmoothing, value),
|app| validate_usize_range(&app.draft.drawing_pen_smoothing, 0, 6),
)
.entry_row_validated(
"Shape Pen sensitivity (0-4)",
|app| app.draft.drawing_shape_recognition_sensitivity.clone(),
|value| Message::TextChanged(TextField::DrawingShapeRecognitionSensitivity, value),
|app| {
validate_usize_range(
&app.draft.drawing_shape_recognition_sensitivity,
0,
usize::from(wayscriber::config::MAX_SHAPE_RECOGNITION_SENSITIVITY),
)
},
)
.entry_row_validated(
"Undo stack limit",
|app| app.draft.drawing_undo_stack_limit.clone(),
Expand Down
3 changes: 3 additions & 0 deletions configurator/src/app/search/terms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ pub(super) const DRAWING_DEFAULT_TERMS: &[&str] = &[
"polygon",
"polygon sides",
"shape",
"shape pen sensitivity",
"shape recognition",
"recognition sensitivity",
"marker",
"marker opacity",
"fill",
Expand Down
2 changes: 2 additions & 0 deletions configurator/src/app/search/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ fn exact_drawing_default_labels_match_defaults_section() {
for query in [
"font size pt",
"eraser size px",
"shape pen sensitivity",
"shape recognition",
"enable text background",
"enable text halo",
] {
Expand Down
4 changes: 4 additions & 0 deletions configurator/src/models/config/draft/from_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ impl ConfigDraft {
drawing_polygon_sides: config.drawing.polygon_sides.to_string(),
drawing_marker_opacity: format_float(config.drawing.marker_opacity),
drawing_pen_smoothing: config.drawing.pen_smoothing.to_string(),
drawing_shape_recognition_sensitivity: config
.drawing
.shape_recognition_sensitivity
.to_string(),
drawing_font_cycle: FontCycleDraft::from_entries(config.drawing.font_cycle.clone()),
drawing_hit_test_tolerance: format_float(config.drawing.hit_test_tolerance),
drawing_hit_test_linear_threshold: config.drawing.hit_test_linear_threshold.to_string(),
Expand Down
1 change: 1 addition & 0 deletions configurator/src/models/config/draft/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub struct ConfigDraft {
pub drawing_polygon_sides: String,
pub drawing_marker_opacity: String,
pub drawing_pen_smoothing: String,
pub drawing_shape_recognition_sensitivity: String,
/// Families `Shift+T` steps through, in order. A list rather than a
/// comma-separated line: a family name can contain a comma, and the row
/// editor picks from what is installed instead of asking for exact text.
Expand Down
3 changes: 3 additions & 0 deletions configurator/src/models/config/setters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ impl ConfigDraft {
TextField::DrawingPolygonSides => self.drawing_polygon_sides = value,
TextField::DrawingMarkerOpacity => self.drawing_marker_opacity = value,
TextField::DrawingPenSmoothing => self.drawing_pen_smoothing = value,
TextField::DrawingShapeRecognitionSensitivity => {
self.drawing_shape_recognition_sensitivity = value
}
TextField::DrawingFontFamily => self.drawing_font_family = value,
TextField::DrawingFontWeight => {
self.drawing_font_weight = value;
Expand Down
22 changes: 22 additions & 0 deletions configurator/src/models/config/tests.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
use super::super::color::ColorInput;

#[test]
fn shape_pen_sensitivity_round_trips_and_rejects_invalid_drafts() {
let mut config = Config::default();
config.drawing.shape_recognition_sensitivity = 3;
let mut draft = ConfigDraft::from_config(&config);
assert_eq!(draft.drawing_shape_recognition_sensitivity, "3");

draft.drawing_shape_recognition_sensitivity = "4".to_string();
assert_eq!(
draft
.to_config(&config)
.expect("valid sensitivity")
.drawing
.shape_recognition_sensitivity,
4
);

draft.drawing_shape_recognition_sensitivity = "5".to_string();
assert!(draft.to_config(&config).is_err());
assert_eq!(draft.drawing_shape_recognition_sensitivity, "5");
}

#[test]
fn board_grid_draft_preserves_patterns_and_rejects_invalid_spacing() {
let mut config = Config::default();
Expand Down
9 changes: 9 additions & 0 deletions configurator/src/models/config/to_config/drawing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use super::super::parse::{
};
use crate::models::error::FormError;
use wayscriber::config::Config;
use wayscriber::config::MAX_SHAPE_RECOGNITION_SENSITIVITY;
use wayscriber::domain::{DragBindableTool, DragTool};
use wayscriber::domain::{MAX_STROKE_THICKNESS, MIN_STROKE_THICKNESS};
use wayscriber::draw::{MAX_PEN_SMOOTHING, REGULAR_POLYGON_MAX_SIDES, REGULAR_POLYGON_MIN_SIDES};
Expand Down Expand Up @@ -59,6 +60,14 @@ impl ConfigDraft {
errors,
|value| config.drawing.pen_smoothing = value,
);
parse_u8_in_range(
&self.drawing_shape_recognition_sensitivity,
"drawing.shape_recognition_sensitivity",
0,
MAX_SHAPE_RECOGNITION_SENSITIVITY,
errors,
|value| config.drawing.shape_recognition_sensitivity = value,
);
parse_field_in_range(
&self.drawing_marker_opacity,
"drawing.marker_opacity",
Expand Down
1 change: 1 addition & 0 deletions configurator/src/models/fields/toggles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ pub enum TextField {
DrawingPolygonSides,
DrawingMarkerOpacity,
DrawingPenSmoothing,
DrawingShapeRecognitionSensitivity,
DrawingFontFamily,
DrawingFontWeight,
DrawingFontStyle,
Expand Down
11 changes: 11 additions & 0 deletions configurator/src/models/fields/tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ impl DragToolField {
pub enum ToolOption {
Select,
Pen,
LiveShape,
Line,
Rect,
Ellipse,
Expand All @@ -65,6 +66,7 @@ impl ToolOption {
vec![
Self::Select,
Self::Pen,
Self::LiveShape,
Self::Line,
Self::Rect,
Self::Ellipse,
Expand All @@ -87,6 +89,7 @@ impl ToolOption {
match self {
Self::Select => "Select",
Self::Pen => "Pen",
Self::LiveShape => "Shape pen",
Self::Line => "Line",
Self::Rect => "Rectangle",
Self::Ellipse => "Ellipse",
Expand All @@ -109,6 +112,7 @@ impl ToolOption {
match self {
Self::Select => Tool::Select,
Self::Pen => Tool::Pen,
Self::LiveShape => Tool::LiveShape,
Self::Line => Tool::Line,
Self::Rect => Tool::Rect,
Self::Ellipse => Tool::Ellipse,
Expand All @@ -131,6 +135,7 @@ impl ToolOption {
match tool {
Tool::Select => Self::Select,
Tool::Pen => Self::Pen,
Tool::LiveShape => Self::LiveShape,
Tool::Line => Self::Line,
Tool::Rect => Self::Rect,
Tool::Ellipse => Self::Ellipse,
Expand Down Expand Up @@ -165,6 +170,7 @@ pub enum DragToolOption {
Default,
Select,
Pen,
LiveShape,
Line,
Rect,
Ellipse,
Expand All @@ -186,6 +192,7 @@ impl DragToolOption {
Self::Default,
Self::Select,
Self::Pen,
Self::LiveShape,
Self::Line,
Self::Rect,
Self::Ellipse,
Expand Down Expand Up @@ -215,6 +222,7 @@ impl DragToolOption {
Self::Default => "Button default",
Self::Select => "Select",
Self::Pen => "Pen",
Self::LiveShape => "Shape pen",
Self::Line => "Line",
Self::Rect => "Rectangle",
Self::Ellipse => "Ellipse",
Expand All @@ -236,6 +244,7 @@ impl DragToolOption {
Self::Default => DragTool::Default,
Self::Select => DragTool::Select,
Self::Pen => DragTool::Pen,
Self::LiveShape => DragTool::LiveShape,
Self::Line => DragTool::Line,
Self::Rect => DragTool::Rect,
Self::Ellipse => DragTool::Ellipse,
Expand All @@ -257,6 +266,7 @@ impl DragToolOption {
DragTool::Default => Self::Default,
DragTool::Select => Self::Select,
DragTool::Pen => Self::Pen,
DragTool::LiveShape => Self::LiveShape,
DragTool::Line => Self::Line,
DragTool::Rect => Self::Rect,
DragTool::Ellipse => Self::Ellipse,
Expand All @@ -278,6 +288,7 @@ impl DragToolOption {
Self::Default => None,
Self::Select => Some(ToolOption::Select),
Self::Pen => Some(ToolOption::Pen),
Self::LiveShape => Some(ToolOption::LiveShape),
Self::Line => Some(ToolOption::Line),
Self::Rect => Some(ToolOption::Rect),
Self::Ellipse => Some(ToolOption::Ellipse),
Expand Down
1 change: 1 addition & 0 deletions configurator/src/models/keybindings/field/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const PREFERRED_ORDER: &[KeybindingField] = &[
KeybindingField::DecreaseMarkerOpacity,
KeybindingField::SelectSelectionTool,
KeybindingField::SelectPenTool,
KeybindingField::SelectLiveShapeTool,
KeybindingField::SelectEraserTool,
KeybindingField::ToggleEraserMode,
KeybindingField::CycleFontFamily,
Expand Down
6 changes: 6 additions & 0 deletions docs/CONFIG.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,9 @@ font_cycle = ["Sans", "Monospace", "Serif"]
# Smoothing applied to a finished freehand or marker stroke (0 - 6)
pen_smoothing = 3

# Shape Pen: 0 precise, 2 balanced (default), 4 more forgiving
shape_recognition_sensitivity = 2

# Default fill state for fill-capable shape tools
default_fill_enabled = false

Expand Down Expand Up @@ -378,6 +381,7 @@ drag_tool = "default"
- **Arrow style**: Run **Cycle Arrow Style** from the command palette to step through standard → pointy → curved → double (unbound by default; bind `cycle_arrow_style`). With arrows selected it restyles those in one undo step; with nothing selected it sets the style for the next arrow
- **Marker opacity**: Use <kbd>Ctrl+Alt</kbd> + <kbd>↑</kbd>/<kbd>↓</kbd>
- **Pen smoothing**: Run **Increase / Decrease Pen Smoothing** from the command palette, or bind `increase_pen_smoothing` / `decrease_pen_smoothing` (see [Pen smoothing](#pen-smoothing))
- **Live shaping**: Choose **Shape pen** from the Shapes picker or **Live Shaping Tool** from the command palette; bind `select_live_shape_tool` for a shortcut. Confident lines, circles, ovals, and axis-aligned rectangles preview as shapes and commit as editable shapes. Set `[drawing] shape_recognition_sensitivity` from 0 (precise) to 4 (forgiving), with 2 as the default, or edit **Shape Pen sensitivity** on the configurator's Drawing page. Reopen the overlay after changing it. The setting affects recognition by Shape Pen, not the dedicated shape tools. Lines close to Cartesian or isometric board-paper lines snap to them; without a nearby grid line, nearly horizontal or vertical strokes align to that axis and skew lines keep their angle. Other ink stays freehand.
- **Text font**: <kbd>Shift+T</kbd> steps through `font_cycle`; **Font Picker** in the command palette opens the full list (see [Font cycle](#font-cycle) and [Font picker](#font-picker))
- **Regular polygon sides**: Use the Shapes popover Sides control (range: 3-12)
- **Font size**: Use <kbd>Ctrl+Shift++</kbd>/<kbd>Ctrl+Shift+-</kbd> or <kbd>Shift</kbd> + scroll (range: 8-72px)
Expand Down Expand Up @@ -1364,6 +1368,7 @@ shown = []
top_tools = [
"top.tool.select",
"top.tool.pen",
"top.tool.live-shape",
"top.tool.marker",
"top.tool.step-marker",
"top.tool.eraser",
Expand Down Expand Up @@ -2163,6 +2168,7 @@ decrease_marker_opacity = ["Ctrl+Alt+ArrowDown"]
# Tool selection shortcuts (optional; keep empty to rely on modifiers)
select_selection_tool = ["V"]
select_pen_tool = ["F"]
select_live_shape_tool = [] # draw ink that snaps to lines or circles
select_marker_tool = ["H"]
select_step_marker_tool = []
select_eraser_tool = ["D"]
Expand Down
4 changes: 2 additions & 2 deletions packaging/.SRCINFO
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pkgbase = wayscriber
pkgdesc = Screen annotation tool for Wayland compositors
pkgver = 0.9.25
pkgver = 0.9.26
pkgrel = 1
url = https://wayscriber.com
arch = x86_64
Expand All @@ -21,7 +21,7 @@ pkgbase = wayscriber
depends = slurp
optdepends = tesseract: copy text from screen (OCR)
optdepends = tesseract-data-eng: English language data for OCR
source = wayscriber-0.9.25.tar.gz::https://github.com/devmobasa/wayscriber/archive/refs/tags/v0.9.25.tar.gz
source = wayscriber-0.9.26.tar.gz::https://github.com/devmobasa/wayscriber/archive/refs/tags/v0.9.26.tar.gz
sha256sums = SKIP

pkgname = wayscriber
2 changes: 1 addition & 1 deletion packaging/PKGBUILD
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Maintainer: wayscriber maintainers <hyprarcher@proton.me>
pkgname=wayscriber
pkgver=0.9.25
pkgver=0.9.26
pkgrel=1
pkgdesc='Screen annotation tool for Wayland compositors'
arch=('x86_64' 'aarch64')
Expand Down
1 change: 1 addition & 0 deletions src/backend/wayland/state/render/tool_preview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ fn draw_semantic_tool_icon(
match icon {
SemanticToolIcon::Select => toolbar_icons::draw_icon_select(ctx, x, y, size),
SemanticToolIcon::Pen => toolbar_icons::draw_icon_pen(ctx, x, y, size),
SemanticToolIcon::LiveShape => toolbar_icons::draw_icon_live_shape(ctx, x, y, size),
SemanticToolIcon::Line => toolbar_icons::draw_icon_line(ctx, x, y, size),
SemanticToolIcon::Rect => toolbar_icons::draw_icon_rect(ctx, x, y, size),
SemanticToolIcon::Circle => toolbar_icons::draw_icon_circle(ctx, x, y, size),
Expand Down
10 changes: 10 additions & 0 deletions src/config/action_meta/entries/tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ pub const ENTRIES: &[ActionMeta] = &[
true,
icon: crate::toolbar_icons::draw_icon_pen
),
meta!(
SelectLiveShapeTool,
"Live Shaping Tool",
Some("Shape Pen"),
"Turn confident ink lines and circles into shapes",
Tools,
true,
true,
true
),
meta!(
SelectLineTool,
"Line Tool",
Expand Down
3 changes: 3 additions & 0 deletions src/config/action_meta/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const HELP_ACTIONS: &[Action] = &[
Action::SetColorBlack,
Action::SelectSelectionTool,
Action::SelectPenTool,
Action::SelectLiveShapeTool,
Action::SelectLineTool,
Action::SelectRectTool,
Action::SelectEllipseTool,
Expand Down Expand Up @@ -100,6 +101,7 @@ const HELP_ACTIONS: &[Action] = &[

const TOOLBAR_ACTIONS: &[Action] = &[
Action::SelectPenTool,
Action::SelectLiveShapeTool,
Action::SelectLineTool,
Action::SelectRectTool,
Action::SelectEllipseTool,
Expand Down Expand Up @@ -161,6 +163,7 @@ const EXPECTED_COMMAND_PALETTE_ACTIONS: &[Action] = &[
Action::Redo,
Action::SelectSelectionTool,
Action::SelectPenTool,
Action::SelectLiveShapeTool,
Action::SelectLineTool,
Action::SelectRectTool,
Action::SelectEllipseTool,
Expand Down
Loading
Loading