12 Commits
Author SHA1 Message Date
justme d8e780dfa1 Use native candidate actions and harden frontend resource loading 2026-10-20 11:52:39 +08:00
justmeandClaude Sonnet 5.5 99fe8f589f Fetch libmonet in build.sh and document monet colours
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 00:23:12 +08:00
justmeandClaude Sonnet 5.5 5bea01e224 Colour the candidate window from the desktop accent via libmonet
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 00:23:12 +08:00
justmeandClaude Sonnet 5.5 064ca6b4d4 Map a libmonet scheme onto candidate window colours
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 00:23:12 +08:00
justmeandClaude Sonnet 5.5 74959cd892 Drop the English README
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 23:38:13 +08:00
justmeandClaude Sonnet 5.5 62dd688261 Document how the block list is kept and how the sources are verified
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 23:37:09 +08:00
justmeandClaude Sonnet 5.5 9cb4134203 Build from commits that are checked, and refuse unsafe paths
The plugin runs inside the input method and sees everything that is typed, so
what it is built from matters. build.sh used to download a tag archive and a
yoga archive without checking them. It now fetches both by commit hash and
verifies the hash afterwards: a tag can be moved and an archive swapped, a
commit hash cannot be faked. A version without a pinned commit is refused
unless FCITX_COMMIT is given. Archive checksums were not used on purpose, GitHub
does not keep the bytes of generated archives stable.

enable-autostart.sh writes paths into an Exec line and a service file and now
refuses paths that would need quoting there.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 23:36:54 +08:00
justmeandClaude Sonnet 5.5 3bfbcb733a Keep the list of forgotten words safe, and keep the highlight where it was
The block list is now a BlockStore. The file is replaced atomically (temporary
file, fsync, rename), created readable by the owner only, picked up again when it
changes on disk, and a word whose save failed stays hidden in memory and is
written on the next attempt instead of being lost on restart. Words with line
breaks or NUL, over 256 bytes, and lists over 20000 entries are refused.

Removing candidates from the engine's list resets its cursor to the first
candidate when the removal is in front of it, so the highlight jumped while
arrowing through candidates. The filter now puts the cursor back on the
candidate it was on.

Both parts are in headers that the window and the tests include, so the tests
exercise the code that runs: tests/blockstore_test.cpp covers restarts, failed
writes, outside edits and bad input, tests/blockfilter_test.cpp runs the filter
on a real Fcitx5 candidate list.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 23:36:54 +08:00
justmeandClaude Sonnet 5.5 ce0d6ba9ae Only forget the candidate the user picked from the menu
The menu remembered the index of the candidate it was opened on. Cloud Pinyin
results arrive asynchronously, so the list can be refreshed between the right
click and the click on an action, and the index would then point at a different
word. That word would have been forgotten and added to the block list.

The word itself is stored when the menu opens and compared when an action is
clicked, nothing is done if it is no longer the same.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 23:36:54 +08:00
justmeandClaude Sonnet 5.5 bf3c88acc8 Fix the candidate window freezing the input method at 100% CPU
The animation frame timer was re-armed with setTime(), setOneShot() and then
setEnabled(true). In the systemd event loop backend setEnabled(true) means
SD_EVENT_ON, a repeating source, and setOneShot() had just set SD_EVENT_ONESHOT.
The re-armed timer was therefore repeating at a time that had already passed,
and the event loop fired it again on every iteration: the main thread of Fcitx5
sat at 100% CPU and typing froze. The first animation was not affected, the
timer is only re-armed from the second one on, which is why it showed up as a
sudden freeze after typing for a while.

setOneShot() alone is correct. tests/timer_rearm.cpp arms a timer twice the way
the window does: with the old calls it fires 198725 times in 200 ms, with the
fix exactly twice.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 23:36:54 +08:00
justmeandClaude Sonnet 5.5 8d14454bb9 Hide forgotten candidates, add autostart script, Chinese README
- Record words picked with "Forget candidate" in a block list and drop them
  from the candidate list before each refresh, so words from read only
  dictionaries stay gone.
- Add scripts/enable-autostart.sh for starting with m3ui at login.
- Make the Chinese README the default, keep the English one as README.en.md.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 22:09:23 +08:00
justmeandClaude Sonnet 5.5 0804634dc1 Add Material 3 candidate window addon for Fcitx5
Fork of the classicui addon (Fcitx5 5.1.23) with a Material 3 look, spring
based animations and a right click action menu for candidates.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 21:58:54 +08:00