Commit Graph
4844 Commits
Author SHA1 Message Date
mtlcl410andClaude Opus 5.5 5b813ce985 fix(sign): explain 0xC0000225 when a token's key provider can't find the key (#1535)
STATUS_NOT_FOUND passed through by a smart card or token provider (an A3
certificate whose token isn't connected) was shown as a bare code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RUNQSPVXx3dDBabRZHAnjz
2026-10-17 16:39:54 +08:00
NetterSilverandClaude Haiku 5.5 84ee69b507 Render month and weekday names in XFA date patterns
Found while testing crates/xfa/src/data.rs:265-281 (iso_to_pattern, with date_tokens at :242 and pattern_to_iso at :285; pattern built in crates/xfa/src/layout.rs:396 date_pattern)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-17 10:13:39 +02:00
hcchung1 db1102185a docs: record how Acrobat prints a page area that is not relevant for print (#2574)
Observed in Acrobat Pro on the public ISCIII form: the once-only page keeps
its place when printing (7 pages with nothing typed) but is printed blank.
PdfCraft draws its content, and has no relevant attribute or print-off
layer yet; the note says so.
2026-10-17 16:01:39 +08:00
mtlcl410andClaude Opus 5.5 07524f5e8c fix(sign): explain 0x8009001D when a store key's provider fails to load (#2207)
Windows reports NTE_PROVIDER_DLL_FAIL when the key storage provider
holding a certificate's private key can't load its DLL: smart card or
token middleware that is missing or broken, or a provider that exists
only as 32-bit code a 64-bit process can't load. The certificate list
showed it only as "Windows error 0x8009001D"; it now says what that
means, as it already did for a missing card or provider.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RUNQSPVXx3dDBabRZHAnjz
2026-10-17 15:29:59 +08:00
Combiler01 2f53d0f0e2 Chore:Fixed Cl cargo test -p pdfcraft-automation 2026-10-17 10:12:27 +05:30
magdale76andClaude Opus 5.5 428cbc083d M10: doc_print takes duplex "printer", leaving two-sided to the printer (#2422)
The headless counterpart of the Print dialog's Printer default: duplex
"printer" sends no two-sided setting, so the printer's own default applies.
The default stays "off", so existing scripts behave as before. Cut and stack
with "printer" sends single-sided sheets, as the dialog does, and still
refuses an explicit edge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 06:42:10 +02:00
magdale76andClaude Opus 5.5 3fbfa4e2af M10: Two-sided starts at Printer default, so the printer's own duplex applies (#2422)
The Print dialog always sent its Two-sided choice, Off unless changed, so a
two-sided default set in the printer's Properties never applied. Acrobat has no
default of its own here and follows the printer's. Two-sided now starts at
Printer default, which sends no duplex setting (craft-print's Job::duplex =
None). Off and the two edges still override it. Cut and stack still sends Off,
since it needs single-sided sheets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 06:42:10 +02:00
hcchung1 c5708e1cc6 fix(xfa): a page area's occur min gets its pages after the body (#2574)
A page area with <occur min="1" max="1"> that the body never reached was
never laid out, so the public ISCIII form lost the page that holds its
finishing instructions and the TERMINAR MEMORIA button once the repeated
copies over the body pages were removed.

PageArea records occur min (0 without an <occur>). When the body has been
laid out, an area used fewer times than its minimum gets the pages it still
needs, in template order, after the body's pages. The form is 7 pages with
the once-only page last, which is what Acrobat Pro shows.
2026-10-17 11:58:50 +08:00
alehelandClaude Opus 5.5 0b63f5a4ba fix(edit): check page backdrops with one page-tree walk per batch
Review of #2815: `page_of` built every page to return one, and the Add
Background dialog checked 24 pages a frame that way, so a frame cost
24 page-tree walks (93 ms at 5,000 pages, 385 ms at 20,000).

- `page_backdrops(doc, pages)` walks the tree once for a batch; the
  dialog checks one batch a frame and `doc_backdrops` one batch in all.
  A page past the end answers None without hiding the others (the
  viewer's page count can disagree with the page tree's).
- `scan` and `replace` take the page; `add_background` no longer walks
  the tree twice more per page to replace a backdrop.
- Tests: 4,000 pages checked in one batch under a generous bound (17.6 s
  with the old lookup), batch order and missing pages, and a background
  over several pages sharing streams, replaced and restored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 05:43:46 +02:00
sanches d6a27cd746 i18n: restore the upstream Vietnamese entry dropped during the main merge 2026-10-17 05:52:50 +03:00
NetterSilverandClaude Haiku 5.5 5157e0421b Keep seconds in FormCalc Time2Num/IsoTime2Num for ISO 8601 times
Found while testing crates/js/src/formcalc.rs:2348-2352 ("time2num" | "isotime2num")

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-17 02:24:39 +00:00
aiongg 77776ca2c6 Build: use craft-docpath from craft-libs 2026-10-17 02:21:34 +00:00
aiongg ed1ab63cd0 Merge upstream main 924c4da4a into next 2026-10-17 01:59:44 +00:00
jonathanwxh-cell 22ec11cd28 Keep lines with footnote references in paragraph reading order (#2929) 2026-10-17 09:57:47 +08:00
MarekSpodBiedry aa5473e014 fix(ui): keep a closed right panel closed when a PDF asks to open on its outline (#2884) 2026-10-17 00:25:24 +02:00
skylar taylor-barrick 924c4da4ac Merge pull request #2698 from mtlcl410/fix/audit-one-word-2662
M8: the redaction audit finds a cover over one word of a long line (#2662)
2026-10-16 16:05:39 -06:00
Bode512 02b9a69242 chore(contributors): add Bode512's people.toml entry (sync_github_name) 2026-10-16 23:42:35 +02:00
Bode512 725828438c fix(cli): bad option values name the option and the value, before any file is read 2026-10-16 23:21:00 +02:00
enes yıldızandClaude Opus 5.5 06c4a970a2 fix(cli): info, text, render and audit take the owner password of R2–R4 files
`pdfcraft-cli info`, `text`, `render` and `audit` rejected the owner
password of RC4-40, RC4-128 and AES-128 files with "the password is
incorrect", while `run doc_open` accepted it (#2670, item 8). The renderer
authenticates only the user password of revisions 2–4. `Session::open`
works around that by handing it the user password that owner
authentication recovers, but the CLI passed the typed password straight to
`inspect` and `PageRenderer`.

`pdfcraft_engine::render_password_for` now gives any render path outside a
session the password the renderer takes, sharing the recovery with
`Session::open`. The CLI uses it for the renderer and keeps the typed
password for the engine session and the cos document, so the owner
password still lifts copy restrictions in `text`.

The render test decodes the PNG and checks its dimensions and that it
has non-white pixels, for every algorithm with either password.

Refs #2670 (item 8 only).

Checks: cargo fmt --check; cargo clippy -p pdfcraft-cli -p pdfcraft-engine
--all-targets -- -D warnings; cargo test -p pdfcraft-cli; cargo test -p
pdfcraft-engine (and --lib); cargo xtask layers, assets, parity.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 00:15:22 +03:00
aiongg c7a6feb393 i18n: translate the new link and file-name messages 2026-10-16 21:02:39 +00:00
Guillem Hermida 91ce75ecb1 fix(ui): on-page text editors leave the mode tabs their pointer
Follows up #2755, which fixed the Edit text paragraph editor. The form
text field editor, the Fill & Sign text box and the Add text box are
foreground Areas placed on the page too. Scrolled up under the mode bar
with the All tools panel closed, they were drawn over the Read, Edit,
Convert and E-Sign tabs: the tabs showed the editor's I-beam and a
click on one went to the editor, so the mode didn't change.

The three Areas are now constrained to the document viewport without
being pushed back into it, as the paragraph editor is: they are clipped
and hit-tested only where the document shows, and stay on their field
or point. The form field cursor and Add text's I-beam, move and resize
cursors read the raw pointer against the page's whole rectangle, which
runs on under the chrome; they are now set only while the pages' widget
contains the pointer, as Fill & Sign already does.
2026-10-16 22:10:24 +02:00
Guillem Hermida d9eb39d6e8 fix(render): draw each ICC profile through itself when two have the same stream dictionary (vendored hayro-interpret patch 40)
hayro-interpret cached the colour space built from an /ICCBased profile
stream under the hash of the stream's dictionary bytes alone. Two
different profiles with the same /N and /Length (any two uncompressed
RGB profiles of one size) shared whichever was read first, so colours in
the second space were drawn through the first profile for the rest of
the document. Found while fixing #1201.

The space is now keyed by what its profile is read from (IccProfileKey):
the stream object a space names, looked up without reading the stream,
and on a miss the old dictionary key plus the stream's own bytes
(decrypted, not decoded), so byte-for-byte copies in other objects still
share one parsed profile and a lookup never decodes. A stream written
directly in the colour space array reports the object holding the array,
as every other stream written there does; it is recognised by its
dictionary lying within the array's bytes and keyed by content only.

InterpreterCache::icc_profile_reads counts the profiles read, so the
tests can check that the cache still hits. Tests: two synthetic RGB
profiles of one length (linear sRGB, and red and blue swapped) as
objects, a reused object, a copy and direct streams on one page.
2026-10-16 21:58:32 +02:00
midasmatterhorn 1390ea4111 Audit: a Square the renderer never draws is not a cover
Hidden (/F bit 2) and NoView (/F bit 32) annotations are not drawn on
screen, so the text under them is in plain view; the audit now skips
them the way the renderer does. A Print-only square still covers.
2026-10-16 21:59:59 +03:00
aiongg 265403813b fix(links): resolve remote document paths with the shared path check
GoToR file specifications go through craft-docpath: network, device and
object-manager paths (\??\, /??/) are refused without touching the
filesystem, relative targets resolve against the source document's
folder, and a result that is not absolute is refused rather than read
against the working directory. Files named on the command line open
under their absolute path, so their relative links keep resolving.
2026-10-16 18:16:50 +00:00
aiongg 08b44e858b fix(ui): keep output file names taken from documents inside the chosen folder
An attachment opened as a tab is named with the same plain file name as
its Save suggestion, and Export certificate names the file the same way
from the certificate subject. Writing files into a chosen folder refuses
any name with a separator, a drive, or that is . or .., so no caller can
write outside the folder.
2026-10-16 18:03:46 +00:00
mtlcl410andClaude Opus 5.5 f5a2376c86 fix(redact): a structure tree too large to walk goes whole (#2447)
Review follow-up on #2532: drop_object_refs stopped visiting at 2,000,000
references and still reported success, so a reference beyond that could
keep a removed annotation reachable. A tree the walk can't finish is now
removed whole, with /MarkInfo: fail-closed, at the cost of the tags. The
limit is a parameter of drop_object_refs_within so the test can reach it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RUNQSPVXx3dDBabRZHAnjz
2026-10-17 02:02:23 +08:00
mtlcl410andClaude Opus 5.5 4d6812503d fix(redact): flattened widgets and far pop-ups leave the structure tree too (#2447)
Review follow-up on #2532:
- the structure-tree references dropped are those of every annotation no
  page lists any more after Sanitize, so widgets flattened with "form
  fields" go too, with their field value;
- the annotations to remove are collected on every page first, so a
  pop-up listed on another page than its parent goes with it;
- an element left with nothing to tag drops /Alt, /ActualText, /T and /E,
  which can repeat the URL or comment;
- the test's byte search saves without object streams, so it can see the
  strings it looks for.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RUNQSPVXx3dDBabRZHAnjz
2026-10-17 02:02:23 +08:00
mtlcl410andClaude Opus 5.5 b7b6e6fe09 fix(redact): removed links and comments leave the structure tree too (#2447)
Remove Hidden Information and Sanitize took a link or comment off its
page's /Annots, but a tagged PDF's structure tree still referenced it
through an /OBJR, so the full rewrite kept the annotation, its URL or
text included, while link_list reported none. The annotations removed
from every page are now collected, and tags::drop_object_refs drops the
structure elements' object references to them (direct or indirect,
array or single kid), with the same seen-set bound as tags::clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RUNQSPVXx3dDBabRZHAnjz
2026-10-17 02:02:23 +08:00
skylar taylor-barrick 9e5b70d1c2 Merge pull request #2067 from storytold/test/pdf-open-and-fixture-regressions
test: retain open regressions and deterministic fixtures
2026-10-16 11:51:58 -06:00
sanches 6496dc6f47 Merge remote-tracking branch 'origin/main' into i18n-id-vi
# Conflicts:
#	ATTRIBUTION.md
#	ATTRIBUTION.toml
#	ROADMAP.md
#	crates/engine/src/dates.rs
#	crates/oracle/src/pixels.rs
#	crates/ui-egui/src/i18n/mod.rs
#	crates/ui-egui/src/i18n/ru.tsv
#	crates/ui-egui/src/i18n/vi.tsv
#	crates/ui-egui/src/system_fonts.rs
#	crates/ui-egui/src/theme.rs
#	crates/ui-egui/tests/fonts.rs
#	docs/gaps.md
#	docs/localization-parity.md
#	docs/localization.md
#	docs/roadmap.md
#	docs/target-app-parity.md
2026-10-16 20:50:35 +03:00
FredApps 66a7667aca Merge current main into idle autosave branch
Preserve the idle repaint and second-edit recovery regression while refreshing already-merged upstream work. Validated exact tree with full local CI and native Linux idle recovery.
2026-10-16 19:50:09 +02:00
Guillem Hermida 743b3861d0 fix(render): draw device colour in the resources' /DefaultGray, /DefaultRGB and /DefaultCMYK (vendored hayro-interpret patch 38)
A resource dictionary's DefaultGray, DefaultRGB and DefaultCMYK colour
spaces replace the device space content selects (ISO 32000-2 §8.6.5.6).
hayro ignored them: g/G, rg/RG and k/K set the device space directly,
cs/CS resolved the device names before looking at the resources, and
images took their /ColorSpace as written. Pages that calibrate device
colour this way, common in PDF/A, came out in the wrong colours.

The interpreter now looks the defaults up once per content window
(DefaultColorSpaces), in the resources and those they inherit, so a form
XObject without its own draws in its page's. They replace DeviceGray,
DeviceRGB and DeviceCMYK selected by the colour operators, by cs/CS (by
name or through a /ColorSpace resource that is a device space), and as
the /ColorSpace of image XObjects and inline images. A default that is a
Lab, Indexed, Pattern or device space, has another number of components
or is not a colour space is ignored, and device colour is drawn as
before. Device spaces nested in other spaces, shading dictionaries,
masks and transparency group spaces are unchanged. The decoded-image
cache keys a decode by the default it was drawn in, since one image can
be drawn with and without one.

Part of #1201.
2026-10-16 19:41:22 +02:00
Marco Arnulfo b2150f3ffd Forms: measure a field's own simple font, not Helvetica, when laying out its text (fixes #2894) 2026-10-16 19:37:00 +02:00
mtlcl410andClaude Opus 5.5 4a35a1cb23 M9: rewriting a certified form's XFA data is a form fill (#2759)
The IRCC IMM forms are certified (DocMDP P=2) and then saved once more
with Reader Extensions: a later revision adds the UR3 usage-rights
signature and rewrites the XFA `datasets` packet. The diff classified any
rewritten stream that wasn't page content or the catalog's XMP as "other
changes", so these untouched forms validated as invalid.

A stream the signed revision's /AcroForm /XFA array names `datasets` or
`form` (the form's data and state) is now a form fill when rewritten,
permitted at P=2 and P=3 and refused at P=1 as before. The roles come from
the signed revision, so a later revision that names the template
"datasets" doesn't make rewriting it a form fill.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RUNQSPVXx3dDBabRZHAnjz
2026-10-17 01:21:28 +08:00
Guillem Hermida f4ee74db05 fix(comments): the note editor takes the keyboard once, so V and H pick tools again
After a highlight, its note editor in the Comments panel kept the
keyboard, so V and H were typed into the note (#2669, item 2).

- The editor asked for the keyboard on every frame when no other widget
  had it, so it took it back after every click elsewhere. It now takes
  it once, when it opens (CommentView::open_editor, EditorFocus::Take).
- Adding another comment left the editor open, and drawing is a drag,
  which egui doesn't treat as a click elsewhere. An empty editor on
  another comment now closes when a comment is added; one with text
  stays open with it but gives the keyboard back (EditorFocus::Release).

Part of #2669.
2026-10-16 18:59:04 +02:00
Guillem Hermida 437b691eb7 fix(ui): the Read mode command leaves Edit as the Edit tab does
#2241 made leaving the Edit tab put Edit text & images down and apply a
paragraph still open in the editor, but only in select_mode, which only
the mode bar reaches. The Read mode command (View > Read mode, Ctrl+H,
the command search) went through switch_mode's other branch, which only
set the mode: Read mode then kept Edit text & images on, every paragraph
boxed, and an open paragraph editor floating over the page with its edit
not applied.

enter_mode now sets the workspace together with its tool, and both
routes go through it, so they can't drift apart again. The command still
leaves the panels as they were.

Test: editing.rs::the_read_mode_command_applies_an_open_paragraph_and_puts_edit_text_down
2026-10-16 18:25:57 +02:00
Harrison BoothandClaude Sonnet 5.5 f976adeb17 M3: the "Save changes?" prompt opens on Save and moves between buttons by keyboard
Save is chosen when the prompt opens, so Enter saves as before. The arrow keys
and Tab / Shift+Tab move the choice between Don't save, Cancel and Save, shown
with a focus ring; Enter or Space press the chosen button, Escape cancels.
Before, Enter always saved, even with another button reached by Tab.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-16 11:20:11 -05:00
Combiler01 9e78afa9c2 merge: reconcile upstream/main with 8-handle image interaction and arrange fixes 2026-10-16 21:44:43 +05:30
Combiler01 035183777a fix:implement 8 point non destructive crop, image resize and Arrange extraction bugs 2026-10-16 21:24:49 +05:30
Guillem Hermida fbd9911d76 fix(forms): renaming a nested field checks the full name it would take
Renaming a field changes only its own /T, so MASTER.a renamed to b
becomes MASTER.b. set_props compared the bare new partial name with the
other fields' fully qualified names: renaming MASTER.a to b succeeded
while MASTER.b existed, leaving two fields with one fully qualified
name, which are one field with a shared value (ISO 32000-2 §12.7.4.2);
and renaming MASTER.a to c was refused because of an unrelated
top-level field c.

The check now compares the new full name, leaving the field itself out
so a kid keeping its own partial name still succeeds, and the error
names that full name. Top-level renames are checked as before.
2026-10-16 17:48:47 +02:00
Tiago KielandClaude Opus 5.5 2c4645de41 fix(cos): check object-stream member numbers and offsets (#1815)
Object-stream members were indexed with unchecked casts: `/First` and each
offset went through `as usize` and an unchecked addition, which truncate or
wrap on 32-bit targets such as the wasm32 build, and the member number went
through `as u32` on every target, so a member numbered 2^32 + 3 was read as
object 3. A negative offset was clamped to zero and read the stream's first
member instead.

Each member is now converted and added with checks, and kept as an unusable
slot (preserving positions, which cross-reference entries refer to) when its
number is not an object number or its start falls outside the decoded data.
Looking such a member up is a MissingObject error, as for any other absent
object.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 11:43:25 -04:00
Guillem Hermida 359a3f2f09 M11: Optimize keeps a JPEG's colour transform (#1201)
Optimize decoded DCT images with the generic JPEG decoder, which converts
three components from YCbCr to RGB whenever the JPEG itself doesn't say
otherwise, and then dropped /DecodeParms. An RGB JPEG stored untransformed
(/ColorTransform 0 and no Adobe marker) therefore came out in other colours
when recompressed, resampled or merged from strips.

The samples are now read with the colour transform ISO 32000-2 §7.4.8
gives them: an Adobe APP14 marker's flag, else /ColorTransform (default 1).
Untransformed samples are taken as stored, and the result is written as a
plain YCbCr JPEG (or Flate), which needs no /DecodeParms. When the marker
and /ColorTransform disagree, a value is out of range, the parameters are
not paired with the filter as §7.4 pairs them, or the decoder reads the
components otherwise (named R, G and B), the image is left as it is.

The tests draw each image with PdfCraft's renderer before and after
Optimize: RGB JPEGs with and without an Adobe marker under each
/ColorTransform, CMYK JPEGs (still left alone) and JPEG strips merged into
one picture.

Part of #1201.
2026-10-16 17:28:19 +02:00
Guillem Hermida 282ce56675 M12: the page side of a measuring scale takes a unit, so 1:50 is 1 mm = 50 mm (#2752)
The Measure panel's drawing scale had its page side fixed in PDF points, so
"1 = 50 mm" was stored as 1 pt = 50 mm and every length came out
72 / 25.4 = 2.835 times too big (a 1:50 plan needed 50 x 25.4 / 72 = 17.64).

The page side now carries a unit (pt, in, mm, cm). It defaults to the
real-world unit, and to the display unit when that is not one of the four.
Scale::ratio converts it to points before building the /X, /D and /A number
formats (ISO 32000-2 12.9) and writes /R as entered ("1 mm = 50 mm").
measure_scale takes the same ratio through page_distance and page_unit.
Scales read from files, Scale::calibrate and units_per_point are unchanged.

Fixes #2752
2026-10-16 17:25:26 +02:00
FredApps 8b5ecf8b04 fix #2444: cancel typed font-size edits on Escape and refresh main
Preserve already-merged upstream work and add the focus-loss/Escape regression. Exact candidate tree qualified with workspace tests, 31 WASM checks and a separate successful dependency audit.
2026-10-16 16:54:31 +02:00
mtlcl410andClaude Opus 5.5 aea1d3d127 M1: put valid_xref_range's doc comment back, and no trailing spaces in the tests (#2676)
Review nits on #2717: the new doc comment had been inserted inside
valid_xref_range's; the tests' xref tables are now one-line literals with
\n escapes, so git diff --check is clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RUNQSPVXx3dDBabRZHAnjz
2026-10-16 22:30:55 +08:00
mtlcl410andClaude Opus 5.5 c6acaefd35 M1: read an xref table numbered from 1 that begins with object 0 (#2676)
Some producers head a classic xref table "1 n" and then write object 0's
free entry first, so every row is one number off and object 1 reads as
free. The renderer coped, but cos did not: printing a scanned invoice
built from cos dropped object 1 (page 1's image) and printed the page
blank. Such a subsection is now read from 0 when its second row locates
an object that is numbered 1, in both xref readers, and the repair is
logged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RUNQSPVXx3dDBabRZHAnjz
2026-10-16 22:30:55 +08:00
Guillem Hermida 3d567bd732 fix(ui): mode tabs keep the hand over a page scrolled under them (#2755)
With the All tools panel closed, page text scrolled up under the mode bar
gave the Read, Edit, Convert and E-Sign tabs the page's cursor: the
Select tool's I-beam, or Edit text's four-way arrow (the I-beam once a
paragraph was open). The page code tested egui's raw hover position
against the page's whole rectangle, which runs on under the chrome when
the page is scrolled, and it sets the cursor after the mode bar does.

The text layer and Edit text now set their cursor only while the pages'
widget contains the pointer, as Fill & Sign already does; a selection
being dragged keeps the I-beam past the edge. The open paragraph's
editor, a foreground Area placed on its paragraph, also floated over the
tabs and took their clicks: it is now clipped and hit-tested to the
document viewport and stays on its paragraph instead of being pushed
back into the window.

Fixes #2755
2026-10-16 16:27:41 +02:00
aiongg a18aa1414c Integration: #2793 parity notes say malformed Decode keeps the default mapping 2026-10-16 14:24:04 +00:00
aiongg 832402ba64 Integration: #2809 the Read mode command applies an open paragraph
switch_mode put the tool down by assigning Select, so Ctrl+H/⌃⌘H from Edit text left the
paragraph editor open and unapplied in Read mode.
2026-10-16 14:24:04 +00:00
aiongg 934a10740d Merge track r1-core (fredapps-r1)
ROADMAP.md, docs/roadmap.md: keep next's status line
2026-10-16 14:17:52 +00:00