The suite's egui-winit reports a letter key on a layout that is not Latin
as the Latin layout's letter, so on Dvorak + Russian the с key is
Dvorak's J. resolve takes that letter before the key's position; with
crates.io egui the letter is the position, as before.
A value with an embedding, override, isolate or mark (LRE RLE PDF LRO
RLO LRI RLI FSI PDI LRM RLM ALM) makes fmt isolate, even in text with no
right-to-left letter, so an ASCII file name with an RLO can't reorder
the sentence. Embeddings, overrides and isolates a value opens are
closed inside its isolate, and stray PDF and PDI are dropped.
While a drag offers a docking target, a hint under the pointer reads
"Hold Ctrl to float" ("Hold ⌘ to float" on macOS), from the
localizable float_hint_label (key dock.floatHint).
A side split replaced the anchor frame in place, so a split beside a
fixed-width frame such as a tool strip took the frame's fixed slot:
the two frames shared its width, and the parent's divider resized both.
The frame now keeps its size: on its outer side the new split wraps the
parent, on its inner side it halves the parent's other child. The drop
preview shows the half the new frame takes.
A side zone is a quarter of the frame deep, at least 32 pt and at most
half the frame, so a 64 pt tool strip offers its left and right edges
past the outer edge band. A pointer in the gap between frames resolves
to the nearest frame's edge instead of floating.
DockArea::float_bounds sets where floating windows, flyouts and drag ghosts may go; the default is the whole viewport. An app with its own title bar under a transparent macOS title bar passes the viewport below it, so a floating window can't be dropped, dragged or restored where pressing it moves the app window.
The interface faces in craft-fonts are full Regular TrueType sources. With the
subset feature (build-dependencies only), Embed::subset_to cuts each one with
skera to the catalogs' characters from U+2E80 up plus CJK punctuation, kana and
full-width forms, keeping every layout feature, and embeds the cut from OUT_DIR.
for_ui without catalogs leaves the interface faces out with a warning; a CFF
interface face is an error. check_text and the catalogs warn only about
characters no embedded face covers.
The manifest's optional ninth field, role, marks the UI subsets (ui). check_text reads
the selected faces' cmaps (formats 4 and 12) with a small reader, so the crate keeps
no dependencies.
* feat(window): shared crate deciding who draws the window frame
Add craft-window, which decides whether the desktop or the app draws the
window frame (titlebar, borders, window buttons) and applies it to an
egui ViewportBuilder. This fixes the drift where some Craft apps drew
their own titlebar on KDE while others kept KWin's.
The rule: macOS, Windows and X11 keep the desktop frame; a Wayland
compositor with zxdg_decoration_manager_v1 (KDE, Sway, Hyprland, COSMIC)
keeps its frame; one without it (GNOME) leaves the frame to the app.
<PREFIX>_TITLEBAR=app|system|desktop overrides. When the app draws the
frame, the decision carries the window-button Layout from GNOME's
button-layout so the app's header bar matches the desktop's order.
Decision logic only; drawing the buttons stays in each app. Extracted and
generalized from pdfcraft's decorations.rs. forbid(unsafe_code); default
build has no egui dependency (egui feature adds decorate()).
* style(window): rustfmt the Wayland probe and Dispatch impl
cargo fmt --check failed CI: collapse the thread-spawn builder chain and
the Dispatch::event signature onto the lines rustfmt wants (verified with
rustfmt 1.98 against the workspace rustfmt.toml).
* fix(window): address review — WAYLAND_SOCKET, bounded gsettings, checkout creds
- Skip the Wayland probe when WAYLAND_SOCKET is set: connect_to_env would
take ownership of the inherited fd and unset the variable, closing the
descriptor winit needs. Keep the desktop frame instead.
- Run the gsettings button-layout lookup behind the same 500 ms bounded
worker as the Wayland probe, so a stalled gsettings can't block startup.
Factored the worker into a shared bounded() helper.
- window.yml: set persist-credentials: false on checkout so the token
isn't left in .git/config while cargo runs dependency build scripts.
- README: document the socket guard and the bounded gsettings lookup.
Verified with rustfmt 1.98 and clippy -D warnings (both feature sets).
* fix(window): reap the gsettings child on timeout; document probe tradeoffs
Follow-up to review: the button-layout lookup now spawns gsettings with
piped output, reads it on a worker, and kills+reaps the child whether it
finishes or times out — so a stalled gsettings leaves neither a blocked
process nor a parked worker (it is a one-shot startup call).
Also document, on the Wayland probe, that an inherited WAYLAND_SOCKET
(rare; normal launches get WAYLAND_DISPLAY) deliberately falls back to the
desktop frame to protect winit's connection — the same frame an app that
doesn't probe would get, a safe default rather than a regression.
Verified: rustfmt 1.98 clean, clippy -D warnings clean (default + egui),
tests pass.
The suite's egui reports it from egui-winit on Linux. A report sets the
layout's Latin-ness; frames without one keep learning from typing. On
crates.io egui a private fallback trait reports nothing.
egui-winit reports AltGr with neither Ctrl nor Alt, so AltGr text read as plain
typing: German AltGr+M (µ) marked the layout as not Latin and Ctrl+Z resolved
by position as Ctrl+Y. µ, ª and º no longer count as a sign of another script.
han(zh-US), zh-AU and the other regions CLDR writes in Traditional
characters give Traditional, and pa-PK picks a pa-arab catalog, never
Gurmukhi pa, as pa-Arab-PK does.
Format::parse reads what a Format writes: its digits, its decimal and
grouping separators (the system's included) and the locale's Latin
marks in an Arabic-Indic format, plus every digit set. parse_number is
Format::from_tag(locale).parse, so the decimal marks come from CLDR's
data alone and the hand-made table is gone.
A lone . in a comma locale is the decimal mark when it can't be
grouping (1.5, 0.250, 1234.5, .5); 1.234 and 1.234.567 stay grouped in
German. The same holds for , in a point locale. Percent signs and units
are documented as the caller's to strip.
Plural rules are looked up by language alone: CLDR's parent of sr-Latn
and zh-Hant is the root, whose only category is other, so sr-latn rows
were rejected. The baked data covers every CLDR locale (10 KB): plural
rules for he, ro, nb, ca, sk, th, ms and the rest, and decimal symbols
for nb-NO, sk-SK, bn-BD, ar-MA and English in Europe. Format applies a
Region's separators only where the system set them, and an empty
grouping separator writes none.
trn_plain writes counts in 0-9 without grouping, for documents and file
names. reset_format goes back to the system region. trn_decimal and
Format write infinities and NaN as CLDR does and take the other form.
Tests that don't set a format use en-US, not the machine's region. The
ICU4X crates are pinned to ~2.3, the minor version the data is for.
Dvorak's ⇧, types <, which egui has no key for, so egui reports the
press as W and Ctrl+Shift+, ran Ctrl+Shift+W. Once typing shows the
layout's letters are not on QWERTY positions, such a press resolves to
nothing unless the position is known to type its own letter.
Collator::new takes sv_SE.UTF-8 and sr_RS@latin. Folding maps every
script's decimal digits to ASCII and, ignoring accents, Persian keheh,
Farsi yeh, alef maksura, teh marbuta and heh with hamza to the Arabic
letters. The collation data grows 4.8 KB (465 bytes gzipped).
Region::decimal and grouping are None unless Windows' or macOS's own
settings set them, so the number locale's CLDR data decides otherwise.
A cleared Windows sThousand is no grouping. LC_ALL=C and LC_NUMERIC=C
(and the other LC_* variables) mean the C locale; only LANG=C gives way
to the preferred language.
fmt and trn add isolates only when the template or an inserted value has
a strong RTL character (bidi class R or AL). Text with none comes out as
before, and a value's own isolate from ltr or isolate is taken off.
Format writes integers, decimals and percentages for a Region on ICU4X's
decimal formatter: the locale's digits (Arabic-Indic in Egypt, Persian in
Iran) or Latin ones on request, its separators and grouping sizes (Indian
12,34,567), CLDR's percent patterns, and the region's own separators where
the system sets them. I18n::format holds the one trn, file_size and
measure use, the system region's until set_format.
Plural rules move from intl_pluralrules to ICU4X, and trn_decimal picks
the form from the digits shown (1.0 files, 1,5 файла).
The CLDR data (decimal symbols, digits, plural rules, percent patterns)
covers the shipped languages and their regional variants; data/generate.sh
rebuilds it.
Matching, the recorder and labels share one rule (craft-libs#198, track 4):
letters by the layout's Latin letter, or by position on layouts that are not
Latin; digits as typed, else by position; punctuation as typed, without the
Shift the layout needs for it. Layout holds whether the layout is Latin and
its characters at punctuation positions, reported by the platform or learned
from typing. KeyInput holds what the toolkit reports for one press, so a
toolkit that knows the virtual-key code, the macOS command table or the
Shift level can pass it on.
`Folder` folds text for case- and accent-insensitive search (Turkish and
Azerbaijani i by locale, ß, final sigma, ligatures, full-width forms) and
maps matches back to the original text for highlighting. `Collator`
(feature `collate`) sorts lists in the locale's order with digits compared
by value, on ICU4X with collation data for the shipped locales only.
The Turkish i and sigma handling come from PdfCraft's `fold_case`.
Part of #198.
Co-authored-by: snipeTR <31975916+snipeTR@users.noreply.github.com>
Co-authored-by: nevicia2010-hub <nevicia2010@gmail.com>
I18n::file_size writes a byte count in steps of 1024 (KB or KiB) or 1000
(KB), with decimals per unit, no decimals from a given value up, a
smallest and largest unit, and bytes as B or in words. I18n::measure
writes any value with a unit template such as "{n} px". Unit names are
catalog rows in context `unit`, keyed by the English template, so a
translation can change the symbol and its spacing.
Reads any Unicode decimal digits, the locale's decimal mark plus ٫,
grouping by the locale's other mark, spaces, apostrophes or ٬ (threes
or Indian 2-2-3), and -/−/+ signs, ignoring bidi marks. Input that
fits no single reading is an error, not a guess.
Region holds the number and time locales, metric or US measurement, A4 or
Letter, the decimal separator, and the grouping separator and clock when
the system sets them. Region::system reads Windows' regional format with
the user's changes, Apple's current locale, the POSIX LC_* variables each
on their own, and the preferred language on the web and Android.
Region::from_setting takes an app's saved choice ("auto" or a tag).
Ported from WordCraft's Region (storytold/wordcraft#857, #1494).
Co-authored-by: Dmitrii Khlapov <dkhlapov@pm.me>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
fmt wraps each value in FSI…PDI and trn wraps {n} in LRI…PDI, so a
value's direction can't reorder the message around it. ltr() isolates
numbers and paths left to right; a value that already is one isolate
goes in unchanged, and a stray PDI can't close the isolate early.
fmt_plain and strip_isolates are for text that leaves the interface.
scripts(tag) lists the ISO 15924 scripts a language's interface text is
written in, direction(tag) follows the main script, and han(tag) gives
the regional Han forms (SC, TC, HK, JP, KR) for picking a CJK face.
I18n::rtl uses direction.