Skip to content

[Portable core 3] Deliver the Linux offline input-method frontend #36

Description

@nervouna

Tracking issue: #32

Sequence

Daily-use completion depends on #35; a minimal adapter can overlap that phase once the engine interface is usable.

Scope

  • Use Fcitx5, targeting Omarchy/Hyprland first and Steam Deck Desktop Mode (KDE Plasma) with a physical keyboard. GNOME/IBus remains planned after Windows; it is not required to close this Fcitx5 issue.
  • Implement desktop-native preedit, candidate selection, paging, and exactly-once commit delivery through the shared core.
  • Handle focus/reset, modifiers, input-context lifetime, surrounding-text capability, and sensitive fields.
  • Fall back safely when context is missing or invalid.
  • Add minimum daily-use configuration, explicit macOS personal-data import, and packaging with required native resources and notices.
  • Keep resource/configuration paths appropriate for Linux.
  • Verify the actual SteamOS session and Flatpak application compatibility. Evaluate Deck packaging without disabling system protection and check persistence across OS updates.

Completion criteria

  • An installable Linux build supports agreed offline Pinyin, Chinese-first mixing/personal learning, custom phrases, candidate navigation, Emoji, and script/input options.
  • Focused automated coverage checks adapter behavior and core integration.
  • Packaged typing works without network access or optional services.
  • Installation is explicit and does not alter the user's input configuration during ordinary tests.

User check

Try typing and focus in the usual browser, editor, and terminal, including switching applications mid-composition and sensitive fields.

Boundaries

A minimal frontend may start while phase 2 is underway; daily-use completion depends on its required behavior and data support. Steam Deck Gaming Mode and controller/on-screen keyboard integration are out of scope. AI, voice, visual effects, and a second Linux adapter are not first-release requirements.

Activity

  1. nervouna commented on Oct 4, 2026

    @nervouna
    OwnerAuthor

    Started the Linux frontend preflight after merging #43. The development host is Linux x86_64, Ubuntu GNOME on Wayland, with gnome-shell and ibus-daemon running; ibus reports 1.5.34-rc2. pkg-config is absent, so development-library availability is not yet established. No installation or input-source configuration was changed.

    The existing Rust probe exposes session lifetime, process_key, clear, owned UTF-8 snapshots with byte offsets, and one-shot commit retrieval. It does not yet expose snapshot-identified candidate selection or the production settings/learning contract. First adapter work should use isolated fixture resources and cover preedit offset conversion, commit draining, focus/reset, and sensitive-field handling; it must not be presented as daily-use support. Candidate clicks need stale-action protection in the shared interface before they are wired through.

    Awaiting explicit confirmation of IBus/GNOME/Wayland as required by this issue before committing frontend implementation. #35 has been reopened for its unfinished scope; #43 remains correctly merged. Daily-use completion and production packaging remain dependent on #35.

  2. nervouna commented on Oct 8, 2026

    @nervouna
    OwnerAuthor

    Slice 1 of the Fcitx5 adapter work is at bf31bc3 on portable-core: the frontend-facing C ABI of the Rust engine. Core/Portable/include/inkflow_rime.h (src/abi.rs, ABI version 1) exports engine/session lifetime, Rime keysym events, immutable snapshots with UTF-8 byte offsets, token-identified candidate selection and highlight (stale snapshots and out-of-range indices are rejected), paging, exactly-once commit draining, preceding text, configuration (candidate count, input-option bitmask, custom phrases with stable error codes), ASCII mode, and the mutation observer as an optional C callback delivered outside the engine lock. Every export catches panics and returns a status with a thread-local message; outputs are written only on success; handles have no thread affinity and are serialized by the engine's locks. The crate now builds as cdylib and staticlib beside the rlib.

    Verified on macOS arm64: bash Core/Portable/test.sh (crate tests, Swift ranking reference, and the C consumer's fixture part, which drives the real runtime lifetime and resource validation with the tiny probe schema), bash Core/Portable/parity.sh on prepared production resources (21-sample baseline, engine regressions, personal data, and the C consumer's production part: lifetime with a released engine reference, keys, snapshots, selection, paging, digit selection, highlight, commits, custom phrases, ASCII, observer), and bash Core/scripts/check-boundaries.sh. No installation or activation occurred.

    Not exported yet: personal-learning management and personal-data import (planned for the configuration/import slice). Next: the Fcitx5 addon skeleton under Linux/fcitx5/, compilable on Linux only; its build is unverified from this Mac session until it runs on the Linux host.

  3. nervouna commented on Oct 8, 2026

    @nervouna
    OwnerAuthor

    Slice 2 is at 735f8c4 on portable-core: the Fcitx5 addon skeleton under Linux/fcitx5/ (CMake project, addon and input-method descriptors, InputMethodEngine). One engine session per input context; keys reach ifr_session_key synchronously on Fcitx5's thread with Rime keysyms and translated modifier masks (releases carry Rime's release mask), with no event-loop dependency. Every mutation drains the commit exactly once and rebuilds the preedit (client preedit when the client declares it, otherwise the panel) and the candidate list from a fresh snapshot, using the snapshot's UTF-8 byte offsets for caret and highlight. Digit selection and Up/Down are the engine's key policy; clicks, paging and cursor moves go back through the ABI with the snapshot they were shown from, so a late action on a superseded page is rejected and only redraws. Reset and focus changes clear the composition, switching input methods commits it first (matching the macOS deactivation behavior), password and Sensitive contexts never compose and get raw keys, and surrounding text is read only when a composition starts and only behind the client's SurroundingText capability with valid text. Resources resolve from INKFLOW_RESOURCES or inkflow/rime under XDG_DATA_HOME/XDG_DATA_DIRS; user data is $XDG_DATA_HOME/inkflow/rime. Without resources the addon logs and passes keys through.

    Verified on macOS arm64: bash Linux/fcitx5/test.sh runs the platform-independent helper tests (XDG resolution, preedit layout from byte offsets, modifier translation, bounded preceding text with invalid UTF-8 rejected) and, with FCITX5_SOURCE pointing at the fcitx5 5.1.14 source tree, compiles the addon syntax-only against those headers with -Wall -Wextra -Werror. bash Core/scripts/check-boundaries.sh passes. The CMake build, Fcitx5::Core linkage, addon loading and all runtime behavior are unverified until they run on the Linux host, as Linux/fcitx5/README.md states; it also records the Linux build steps. This is not daily-use support. No installation or activation occurred.

    Next: the minimum daily-use configuration surface and the explicit macOS personal-data import entry point, with the engine stopped during import.

  4. nervouna commented on Oct 8, 2026

    @nervouna
    OwnerAuthor

    Slice 3 is at 477d9d5 on portable-core: the minimum daily-use configuration surface and the explicit macOS personal-data import entry point.

    C ABI: ifr_backup_parse validates a macOS format-1 document and exposes its candidate count, input options, custom phrases and the non-portable preferences it skips (shortcuts, font size, layout, thunder mode, voice rules); ifr_backup_import and ifr_personal_recover run personal::import/recover and return IFR_ENGINE_ACTIVE while any engine or session is alive in the process. The C consumer also found a real defect through the panic boundary: Backup::from_json indexed a missing field and panicked; it now returns Incompatible, with a unit test.

    Fcitx5 addon: ~/.config/fcitx5/conf/inkflow.conf (also via fcitx5-configtool) carries candidates per page (3–9), the fourteen input options under their macOS names and custom phrases as code=text; settings reach every live session through ifr_session_set_configuration at the next composition boundary, and sessions are now created and configured on first use rather than per input context up front. ImportBackup=/path/to/backup.json plus a reload is the import entry point: the request is consumed first so a bad file cannot repeat, the document is parsed and its skipped preferences logged, every session and the engine are destroyed (Rime finalizes), the three dictionaries are imported with rollback, the backup's settings are written into the configuration, and the engine is recreated; an interrupted earlier import is recovered first.

    Verified on macOS arm64: bash Core/Portable/test.sh, bash Core/Portable/parity.sh on prepared production resources (21-sample baseline, engine regressions, personal data, and the C consumer: backup parsing with disclosure, import and recovery on an isolated directory, IFR_ENGINE_ACTIVE with a live engine and with a live session after the engine reference is released, import after teardown), bash Linux/fcitx5/test.sh (helper tests plus the syntax-only compile against fcitx5 5.1.14 headers) and bash Core/scripts/check-boundaries.sh. The addon's build and runtime behavior, including the configuration and import paths, remain unverified until they run on the Linux host. No installation or activation occurred.

    Remaining for this issue: build and run the addon on the Linux host (Omarchy/Hyprland, then Steam Deck Desktop Mode), packaging with the native resources and notices, and the user check of typing, focus and sensitive fields.

  5. nervouna commented on Oct 9, 2026

    @nervouna
    OwnerAuthor

    The ARM64 Omarchy installation is working. At 8a4c968, the addon built and loaded with Fcitx5 5.1.23 on Hyprland, and the user confirmed that it works. The US keyboard and existing Pinyin entry were retained.

    Target checks passed: native runtime, 291 ranking cases, production resources, the 21-sample initial/persisted learned baseline, engine and personal-data parity, C ABI consumers, and isolated installed-addon tests for preedit/candidates, commits, focus/reset, sensitive fields, configuration and backup import. Installation testing fixed raw-Pinyin commits on focus loss, a backup-path lifetime bug, and phrase text in a warning.

    Next is repeatable user-local installation, upgrade, rollback and uninstall. Steam Deck validation is deferred at the user’s request; KDE Plasma, Flatpak compatibility and persistence across SteamOS updates remain unverified. This does not complete #36. The macOS cutover remains a separate iteration.

  6. nervouna commented on Oct 9, 2026

    @nervouna
    OwnerAuthor

    PR #63 now contains the shared-core branch and the Omarchy installer work. The managed package at dec1f3f built on ARM64 Omarchy. All 20 installer tests passed, as did the real-package install/upgrade-fixture/rollback/uninstall exercise with addon loading on a private D-Bus after each switch and personal-data fixtures preserved.

    On the live device, the existing manual installation was upgraded, its original addon/input-method descriptors restored and compared byte-for-byte, and the managed package reinstalled. Fcitx5 loaded the library and resources from the managed release, retained US keyboard and Pinyin, and reported no automatic restarts. Packaging includes notices, corresponding sources and relative ELF runtime paths; installation needs neither sudo nor network access.

    The user already confirmed the original Omarchy bring-up works. Steam Deck/KDE Plasma, Flatpak compatibility and SteamOS update persistence remain deferred and unverified. Refs #36; not closing it. The macOS cutover remains for #37 in the next iteration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions