git.lucas.co / cce-keyboard
on-screen keyboard
git clone https://git.lucas.co/cce-keyboard.git

CLAUDE.md (3.4K)

 1 # cce-keyboard
 2 
 3 The on-screen keyboard. Read the workspace guide (`../cce-compositor/WORKSPACE.md`)
 4 first; this file covers only what is particular to this crate.
 5 
 6 ## Shape
 7 
 8 - `src/main.rs` — the `Application`: an Overlay-layer surface anchored to the
 9   bottom edge, `keyboard_interactivity none`, root plate with one control
10   plate per key (raised keycap at rest, flush while held or latched, rim lit
11   while locked). Single instance via `cce_ui::ipc::instance`;
12   `cce-keyboard [toggle|show|hide]`, and hiding exits.
13 - `src/layout.rs` — the key table (evdev codes, unit widths, the Fn layer)
14   and the pure geometry (`place`, `hit`). Unit-tested; no Wayland.
15 - `src/keymap.rs` — compiles the session's default keymap with
16   libxkbcommon (empty RMLVO, the same defaults `cce-compositor`'s
17   `xkb_config.rs` uses) and reads the character keys' labels from it.
18 - `src/vkbd.rs` — `zwp_virtual_keyboard_v1` on a **second Wayland
19   connection** of its own. The protocol has no events, so nothing needs
20   dispatching, and keeping it off the runner's `EngineState` means cce-ui
21   needed no change.
22 
23 ## Things that are deliberate
24 
25 - **No key repeat here.** The compositor gives virtual keyboards repeat info
26   (`keyboard.rs` `DEFAULT_REPEAT_*`) and the focused client repeats a held
27   key itself; the board just keeps the key down while the pointer does.
28 - **Modifiers are pressed lazily**, around the next key, not when latched.
29   A latched Super must not hold the compositor in its Super-held adjust mode.
30   Both the modifier key events and an explicit `modifiers` mask are sent.
31 - **The board fits the smallest output** (`Config::fit`, via `ccectl outputs
32   --json`): the compositor *destroys* a layer surface whose exclusive zone
33   leaves less than half the output (`layer_shell.rs`, river's rule). A
34   280px board on a 360px-tall scale-2 shadow output vanished on map before
35   this.
36 - **The key gap is capped at 15% of the row pitch**, never wider than the
37   ladder's `control_gap()`: the ladder spaces rows of buttons, and on a
38   dense grid its gap ate a third of every key.
39 
40 ## Shown by a touched field
41 
42 The compositor runs `cce-keyboard show` when a touch activates a
43 text-input-v3 field and `cce-keyboard hide` when that field lets go
44 (`cce-compositor`'s `osk.rs`; `window_manager { osk_on_touch }`). cce-ui
45 widgets announce their fields through `cce_ui::text_input::claim`. The board
46 does not have to do anything for this: it stays a virtual keyboard, and a
47 tap on it does not take focus, so the field stays enabled while it types.
48 
49 ## Depends on a compositor fix
50 
51 A click on a layer surface used to give it keyboard focus whatever its
52 `keyboard_interactivity` (`cursor.rs`, button and touch paths), which took
53 focus off the window being typed into on the first key. Fixed by
54 `layer_takes_click_focus` in cce-compositor; a session on an older `cce-fx`
55 shows the board, latches modifiers, and types nothing.
56 
57 ## Verifying
58 
59 Shadow only (never run a build from the plain shell):
60 
61 ```sh
62 cce-shadow start --new --bin /abs/path/target/release/cce-fx
63 cce-shadow spawn /home/lsgalante/.local/bin/cce-text-editor
64 cce-shadow spawn env CCE_FONTS_DIR=… CCE_ICONS_DIR=… /abs/path/target/release/cce-keyboard
65 cce-shadow ctl pointer-move-to <x> <y>; cce-shadow ctl pointer-click
66 ```
67 
68 Check `ctl windows` still shows the editor `focused=true` after clicking keys,
69 and do a `--scale 2` pass (pointer coords are logical: shot px ÷ 2).