# Technical Documentation: osfans/trime

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/osfans/trime)

### Overview (`README.md`)

# Trime

Rime IME for Android


[](https://www.gnu.org/licenses/gpl-3.0)
[](https://github.com/osfans/trime/releases)
[](https://f-droid.org/packages/com.osfans.trime)
[](http://osfans.github.io/trime/)

English | [简体中文](README_sc.md) | [繁體中文](README_tc.md)

## About

Trime is originally a frontend of open-source [Android Traditional Chinese IME], based on [RIME] input method framework and written in Java/Kotlin with JNI. It is designed to protect the native language of various local dialects of Chinese and is a universal shape-based and phonetic-based input method platform.

[Documentation](https://github.com/osfans/trime/wiki)

## Download

- Stable Channel <br>
  [<img alt='Get it on F-Droid' src='https://fdroid.gitlab.io/artwork/badge/get-it-on.png' height='80px'/>](https://f-droid.org/packages/com.osfans.trime)
  [<img alt='Google Play Download Now' src='https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png' height='80px'/>](https://play.google.com/store/apps/details?id=com.osfans.trime)

- Nightly Channel [Download](https://github.com/osfans/trime/releases/tag/nightly)

- Canary Channel [Download](https://github.com/osfans/trime/actions)

- Configurations [rimerc](https://github.com/Bambooin/rimerc)

## History

TRIME is the abbreviation of _Tongwen RIME_ or _ThaeRv Input Method_.

From the beginning, TRIME was written for TaeRv Pinyin, and named _TaeRv Input Method (泰如输入法)_.

Then, we created an input method platform with some code tables, such as Wu dialect (吴语). We renamed it to _Chinese Character Dialect Input Method (汉字方言输入法)_.

Later, it supports Wubi and Liangbi and other shape-based input method, we branded it [_Tongwen Input Method Platform 2.0 (同文输入法平台 2.0)_](https://github.com/osfans/trime-legacy), which implies that the phonetic-based and shape-based input method on one platform, while dialects and Mandrain share one kind of characters.

Benefit from the [librime](https://github.com/rime/librime) project by JNI, we are now in version 3.0 of TRIME aka _Tongwen Input Method (同文输入法)_.

Your are now welcome to [contribution](CONTRIBUTING.md) ~ !

## Getting Started for developer

### Prepare

#### Requirements:

- Android SDK and Android NDK
  * If you are new to Android development, please install [Android Studio](https://developer.android.com/studio).

- JDK (OpenJDK) 17
- Python 3 (required by OpenCC to generate dictionary text files)

#### Prerequisites for Windows

Symbolic links will be created according to current build configurations, developers need:

- Enable [Developer Mode](https://learn.microsoft.com/en-us/windows/apps/get-started/enable-your-device-for-development) so that symlinks can be created without administrator privilege.

- Enable symlink support for `git`:

  ```powershell
  git config --global core.symlinks true
  ```

If you cannot or wouldn't like to enable anything, it doesn't matter. Copying will be used instead when error on creating symbolic links.

### Build

#### 1. Clone this project and fetch all submodules:

```sh
git clone git@github.com:osfans/trime.git
git submodule update --init --recursive
# use partial clone to save time
git submodule update --init --recursive --filter=blob:none
```

#### 2. Debug version without signature:

```sh
# On Linux or macOS
make debug

# On Windows
.\gradlew assembleDebug
```

#### 3. Release version with signture:

Create `keystore.properties` file which contains following contents for [signing information](https://developer.android.com/studio/publish/app-signing.html):

```gradle.properties
storePassword=myStorePassword
keyPassword=mykeyPassword
keyAlias=myKeyAlias
storeFile=myStoreFileLocation
```

Then, you may run:

```sh
# On Linux or macOS
make release

# On Windows
.\gradlew assembleRelease
```

### Troubleshooting

```
Target "boost_log_setup" links to target "Boost::coroutine" but the target was not found.
```

Run `make clean` on Linux or macOS, or run `.\gradlew clean` on Windows.

Other issues:

1. Try `make clean`
2. Make sure your repo is up-to-date. If one or more submodules are modified, also make sure they are compatible with the current version.
3. If the problem still exists(very unlikely), try to make a new clone.
4. Check if this is there is an issue/PR related to your problem. If yes, try their solutions.
5. If none of them works, you may make an issue to ask for help.(optional)

## Acknowledgments

- Developer: [osfans](https://github.com/osfans)
- Contributors: [boboIqiqi](https://github.com/boboIqiqi)、[Bambooin](https://github.com/Bambooin)、[senchi96](https://github.com/senchi96)、[heiher](https://github.com/heiher)、[abay](https://github.com/a342191555)、[iovxw](https://github.com/iovxw)、[huyz-git](https://github.com/huyz-git)、[tumuyan](https://github.com/tumuyan)、[WhiredPlanck](https://github.com/WhiredPlanck)、[nopdan](https://github.com/nopdan)...
- [Wiki Editors](https://github.com/osfans/trime/wiki): [xiaoqun2016](https://github.com/xiaoqun2016)、[boboIqiqi](https://github.com/boboIqiqi)...
- Translators: 天真可爱的满满 (Chinese Traditional), 点解 (English) ...
- Keyboard Designers: 天真可爱的满满、皛筱晓小笨鱼、吴琛 11、熊猫阿 Bo、默默ㄇㄛ ˋ...
- Donations: See QR Code in [Releases](https://github.com/osfans/trime/releases)
- Community: Netizens who feedback in [Issues](https://github.com/osfans/trime/issues)、[QQ Group (811142286)](https://jq.qq.com/?_wv=1027&k=AXdR80HN)、[QQ Group (224230445)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=pg_q7UVumWYLq1Rk8kIAqkK1xGt64VnX&authKey=04m9l7OBO5H5vgrEL8IbpsmtnptWM60xy%2FUwYCfyvw9VcRhe8zRzAS1ezoemZdFr&noverify=0&group_code=224230445)、[Tieba](http://tieba.baidu.com/f?kw=rime)、[Google Play](https://play.google.com/store/apps/details?id=com.osfans.trime)、[Telegram](https://t.me/trime_dev)...
- Projects: [RIME]、[OpenCC]、[Android Traditional Chinese IME] and so on.

## Third Party Libraries

- [Boost C++ Libraries](https://www.boost.org/) (Boost Software License)
- [darts-clone](https://github.com/s-yata/darts-clone) (New BSD License)
- [LevelDB](https://github.com/google/leveldb) (New BSD License)
- [libiconv](https://www.gnu.org/software/libiconv/) (LGPL License)
- [marisa-trie](https://github.com/s-yata/marisa-trie) (BSD License)
- [glog](https://github.com/google/glog) (New BSD License)
- [OpenCC](https://github.com/BYVoid/OpenCC) (Apache License 2.0)
- [RIME](https://rime.im) (BSD License)
- [snappy](https://github.com/google/snappy)(BSD License)
- [utfcpp](https://github.com/nemtrif/utfcpp) (Boost Software License)
- [yaml-cpp](https://github.com/jbeder/yaml-cpp) (MIT License)
- [Android Traditional Chinese IME](https://code.google.com/p/android-traditional-chinese-ime/) (Apache License 2.0)

[Android Traditional Chinese IME]: https://code.google.com/p/android-traditional-chinese-ime/
[RIME]: http://rime.im
[OpenCC]: https://github.com/BYVoid/OpenCC

---

### Overview (`app/src/main/jni/cmake/README.md`)

Please format CMake file with https://github.com/cheshirekow/cmake_format
```
make cmake-format
```

---

### Doc Keyboard (`doc/Keyboard.md`)

# Liquid Keyboard 參數

(3.2.17), 只有使用 `single_width` 。其餘的還未有作用。

- `single_width` : 在 `SINGLE` 類別中，每項的闊度 (和高度相等)。

新增一些参数 `fixed_key_bar:` 用于自定义液态键盘中的固定按键条：

例：
```yaml
liquid_keyboard:
  fixed_key_bar:  # 固定按键条
    position: bottom  # 摆放位置（在滚动区域的……） top|bottom|left|right （上/下/左/右）
    keys:  # 按键（显示名称为对应的label，不能放太多）
      - liquid_keyboard_exit  # 返回键（在preset_keys内定义，同下）
      - space1  # 空格键
      - BackSpace  # 退格键
      - Return2  # 回车键
      - liquid_keyboard_clipboard  # “剪贴板”跳转按键
      - liquid_keyboard_switch  # “更多”跳转按键
```

# 藍芽鍵盤問題
https://github.com/osfans/trime/issues/1058#issuecomment-1672635413

# 橫屏鍵盤

(3.2.17) 新增兩個參數到 `preset_keyboards` :

- `landscape_keyboard`: 橫屏時轉用的 keyboard id。當判定需顯示橫屏鍵盤時，會顯示此值代表的鍵盤。該 id 需包含在 `style/keyboards`中。
- `landscape_split_percent`:  0 - 200。此值只在橫屏時生效，優先等級高於「鍵盤設定」>「自動分割鍵盤比例」。此值代表鍵盤自動分割時中間的空白闊度比例。如：
	- `100` 代表 100%，即空白的闊度與鍵盤的總闊度比例為 1:1。
	- `150` 的話，代表空白的闊度與鍵盤的總闊度比例為 1.5:1。
	- `0` 代表不做自動分割。

例：
```
patch:
  "style/keyboard": [my_keyboard, my_landscape_keyboard, mini, .....]
  "preset_keyboards/my_keyboard":
    name: My Keyboard
    landscape_keyboard: my_landscape_keyboard
    ...
    keys:
      - ......
  "preset_keyboards/my_landscape_keyboard":
    name: My Landscape Keyboard
    landscape_split_percent: 0
    ...
    keys:
      - ......
```
以上例子代表：
直屏時使用 `my_keyboard` 
橫屏時使用 `my_landscape_keyboard`，並且不做自動分割。若 `landscape_split_percent` > 0，則會分割顯示。

---

### Doc Trime Schema.Json (`doc/trime-schema.json`)

{
  "$id": "https://github.com/osfans/trime/blob/develop/doc/trime-schema.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "JSON schema for Trime theme configuration",
  "definitions": {
    "ToolBar.Button.Background": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "default": "rectangle"
        },
        "corner_radius": {
          "type": "number",
          "default": 10
        },
        "bg_normal": {
          "type": "string",
          "default": ""
        },
        "bg_highlight": {
          "type": "string",
          "default": ""
        },
        "vertical_inset": {
          "type": "integer",
          "default": 4
        },
        "horizontal_inset": {
          "type": "integer",
          "default": 0
        }
      }
    },
    "ToolBar.Button.Foreground": {
      "type": "object",
      "properties": {
        "style": {
          "type": "string",
          "default": ""
        },
        "option_styles": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": []
        },
        "fg_normal": {
          "type": ["string", "null"],
          "default": null
        },
        "fg_highlight": {
          "type": ["string", "null"],
          "default": null
        },
        "font_size": {
          "type": "number",
          "default": 15
        },
        "size": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "default": []
        },
        "padding": {
          "type": "integer",
          "default": 5
        }
      }
    },
    "ToolBar.Button": {
      "type": "object",
      "properties": {
        "background": {
          "$ref": "#/definitions/ToolBar.Button.Background"
        },
        "foreground": {
          "$ref": "#/definitions/ToolBar.Button.Foreground"
        },
        "action": {
          "type": "string",
          "default": ""
        }
      }
    }
  },
  "type": "object",
  "properties": {
    "config_version": {
      "type": "string",
      "pattern": "\\d+(\\.\\d+)*",
      "description": "config version"
    },
    "name": {
      "type": "string",
      "description": "方案名稱"
    },
    "author": {
      "type": "string",
      "description": "作者資訊"
    },
    "style": {
      "type": "object",
      "properties": {
        "auto_caps": {
          "enum": [true, false, "ascii"],
          "default": false,
          "description": "自动句首大写"
        },
        "candidate_font": {
          "type": "string",
          "description": "候選字型"
        },
        "candidate_padding": {
          "type": "integer",
          "description": "候選項內邊距"
        },
        "candidate_spacing": {
          "type": "number",
          "description": "候選間距"
        },
        "candidate_text_size": {
          "type": "integer",
          "description": "候選字號"
        },
        "candidate_view_height": {
          "type": "integer",
          "description": "候選區高度"
        },
        "comment_font": {
          "type": "string",
          "description": "編碼提示字型"
        },
        "comment_height": {
          "type": "integer",
          "description": "編碼提示區高度"
        },
        "comment_on_top": {
          "type": "boolean",
          "description": "編碼提示在上方或右側"
        },
        "comment_text_size": {
          "type": "integer",
          "description": "編碼提示字號"
        },
        "hanb_font": {
          "type": "string",
          "description": "擴充字型"
        },
        "horizontal_gap": {
          "type": "integer",
          "description": "鍵水平間距"
        },
        "keyboard_padding": {
          "type": "integer",
          "description": "竖屏模式下，屏幕左右两侧与键盘的距离（曲面屏减少误触）"
        },
        "keyboard_padding_left": {
          "type": "integer",
          "description": "竖屏屏模式下，左手键盘布局，屏幕左侧与键盘的距离"
        },
        "keyboard_padding_right": {
          "type": "integer",
          "description": "竖屏屏模式下，左手键盘布局，屏幕右侧与键盘的距离"
        },
        "keyboard_padding_bottom": {
          "type": "integer",
          "description": "竖屏模式下，屏幕下边缘与键盘的距离（避免误触发全面屏手势）"
        },
        "keyboard_padding_land": {
          "type": "integer",
          "description": "横屏模式下，屏幕左右两侧与键盘的距离（避免横屏按键过度拉伸变形）"
        },
        "keyboard_padding_land_bottom": {
          "type": "integer",
          "description": "横屏模式下，屏幕下侧与键盘的距离"
        },
        "key_font": {
          "type": "string",
          "description": "鍵盤字型"
        },
        "key_height": {
          "type": "integer",
          "description": "鍵高"
        },
        "key_text_size": {
          "type": "integer",
          "description": "鍵字號"
        },
        "key_width": {
          "type": "number",
          "description": "鍵寬，佔螢幕寬的百分比"
        },
        "keyboards": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "鍵盤配置"
        },
        "label_text_size": {
          "type": "integer",
          "description": "標籤字號"
        },
        "label_font": {
          "type": "string",
          "description": "編標籤字型"
        },
        "latin_font": {
          "type": "string",
          "description": "西文字型"
        },
        "keyboard_height": {
          "type": "integer",
          "description": "锁定键盘高度，避免切换时键盘高度变化而造成闪烁"
        },
        "keyboard_height_land": {
          "type": "integer",
          "description": "锁定横屏下键盘高度，避免切换时键盘高度变化而造成闪烁"
        },
        "preview_font": {
          "type": "string",
          "description": "按鍵提示字型"
        },
        "preview_height": {
          "type": "integer",
          "description": "按鍵提示高度"
        },
        "preview_offset": {
          "type": "integer",
          "default": "-12",
          "description": "按鍵提示縱向偏移"
        },
        "preview_text_size": {
          "type": "integer",
          "description": "按鍵提示字號"
        },
        "proximity_correction": {
          "type": "boolean",
          "description": "按鍵糾錯"
        },
        "reset_ascii_mode_on_focus_change": {
          "type": "boolean",
          "description": "焦点变更弹起输入法软键盘时，重置 ascii_mode"
        },
        "round_corner": {
          "type": "number",
          "description": "按鍵圓角半徑"
        },
        "shadow_radius": {
          "type": "number",
          "description": "按鍵陰影半徑"
        },
        "symbol_font": {
          "type": "string",
          "description": "符號字型"
        },
        "symbol_text_size": {
          "type": "integer",
          "description": "編碼字型"
        },
        "vertical_correction": {
          "type": "number",
          "default": "-10",
          "description": "触摸位置校正（竖直方向）。为了提升打字手感，可将按键的实际触摸位置相对其显示位置上下偏移一点点"
        },
        "vertical_gap": {
          "type": "number",
          "description": "鍵盤行距"
        },
        "background_folder": {
          "type": "string",
          "description": "背景图保存在background目录下的哪个子目录"
        },
        "enter_label_mode": {
          "type": "integer",
          "minimum": 0,
          "maximum": 3,
          "description": "是否使用App提供的ActionLabel内容作为Enter键的文本（由于多数App没有适配ActionLable，实际影响不大）。0不使用，1只使用actionlabel，2优先使用，3当其他方式没有获得label时才读取actionlabel"
        },
        "enter_labels": {
          "type": "object",
          "description": "定义Enter键的文本",
          "properties": {
            "go": {
              "type": "string",
              "default": "前往"
            },
            "done": {
              "type": "string",
              "default": "完成"
            },
            "next": {
              "type": "string",
              "default": "下个"
            },
            "pre": {
              "type": "string",
              "default": "上个"
            },
            "search": {
              "type": "string",
              "default": "搜索"
            },
            "send": {
              "type": "string",
              "default": "发送"
            },
            "default": {
              "type": "string",
              "default": "Enter"
            }
          }
        }
      }
    },
    "preedit": {
      "type": "object",
      "properties": {
        "horizontal_padding": {
          "type": "integer",
          "minimum": 0,
          "maximum": 64,
          "default": 8
        },
        "top_start_radius": {
          "type": "number",
          "minimum": 0.0,
          "maximum": 48,
          "default": 0.0
        },
        "top_end_radius": {
          "type": "number",
          "minimum": 0.0,
          "maximum": 48,
          "default": 0.0
        },
        "alpha": {
          "type": "number",
          "minimum": 0.0,
          "maximum": 1.0,
          "default": 1.0
        },
        "foreground": {
          "type": "object",
          "properties": {
            "font_size": {
              "type": "number",
              "minimum": 0.0,
              "maximum": 64,
              "default": 16
            }
          }
        }
      }
    },
    "window": {
      "type": "object",
      "properties": {
        "insets": {
          "type": "object",
          "properties": {
            "vertical": {
              "type": "integer",
              "minimum": 0,
              "maximum": 64,
              "default": 0
            },
            "horizontal": {
              "type": "integer",
              "minimum": 0,
              "maximum": 64,
              "default": 0
            }
          }
        },
        "item_padding": {
          "type": "object",
          "properties": {
            "vertical": {
              "type": "integer",
              "minimum": 0,
              "maximum": 64,
              "default": 0
            },
            "horizontal": {
              "type": "integer",
              "minimum": 0,
              "maximum": 64,
              "default": 0
            }
          }
        },
        "min_width": {
          "type": "integer",
          "minimum": 0,
          "maximum": 640,
          "default": 0
        },
        "corner_radius": {
          "type": "number",
          "minimum": 0,
          "maximum": 48,
          "default": 0
        },
        "border": {
          "type": "integer",
          "minimum": 0,
          "maximum": 24,
          "default": 0
        },
        "shadow": {
          "type": "number",
          "minimum": 0,
          "maximum": 64,
          "default": 0
        },
        "alpha": {
          "type": "number",
          "minimum": 0.0,
          "maximum": 1.0,
          "default": 1.0
        },
        "foreground": {
          "type": "object",
          "properties": {
            "label_font_size": {
              "type": "number",
              "minimum": 0.0,
              "maximum": 64,
              "default": 20
            },
            "text_font_size": {
              "type": "number",
              "minimum": 0.0,
              "maximum": 64,
              "default": 20
            },
            "comment_font_size": {
              "type": "number",
              "minimum": 0.0,
              "maximum": 64,
              "default": 16
            }
          }
        }
      }
    },
    "tool_bar": {
      "properties": {
        "primary_button": {
          "$ref": "#/definitions/ToolBar.Button"
        },
        "buttons": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/ToolBar.Button"
          },
          "default": []
        },
        "button_spacing": {
          "type": "integer",
          "default": 18
        },
        "button_font": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "default": []
        }
      }
    },
    "fallback_colors": {
      "type": "object",
      "properties": {
        "candidate_text_color": {
          "type": "string",
          "default": "text_color"
        },
        "comment_text_color": {
          "type": "string",
          "default": "candidate_text_color"
        },
        "border_color": { "type": "string", "default": "back_color" },
        "candidate_separator_color": {
          "type": "string",
          "default": "border_color"
        },
        "hilited_text_color": { "type": "string", "default": "text_color" },
        "hilited_back_color": { "type": "string", "default": "back_color" },
        "hilited_candidate_text_color": {
          "type": "string",
          "default": "hilited_text_color"
        },
        "hilited_candidate_back_color": {
          "type": "string",
          "default": "hilited_back_color"
        },
        "hilited_label_color": {
          "type": "string",
          "default": "hilited_candidate_text_color",
          "description": "高亮候选序号"
        },
        "hilited_comment_text_color": {
          "type": "string",
          "default": "comment_text_color"
        },
        "hilited_key_back_color": {
          "type": "string",
          "default": "hilited_candidate_back_color"
        },
        "hilited_key_border_color": {
          "type": "string",
          "default": "key_border_color"
        },
        "hilited_key_text_color": {
          "type": "string",
          "default": "hilited_candidate_text_color"
        },
        "hilited_key_symbol_color": {
          "type": "string",
          "default": "hilited_comment_text_color"
        },
        "hilited_off_key_back_color": {
          "type": "string",
          "default": "hilited_key_back_color"
        },
        "hilited_off_key_border_color": {
          "type": "string",
          "default": "hilited_key_border_color"
        },
        "hilited_on_key_back_color": {
          "type": "string",
          "default": "hilited_key_back_color"
        },
        "hilited_on_key_border_color": {
          "type": "string",
          "default": "hilited_key_border_color"
        },
        "hilited_off_key_text_color": {
          "type": "string",
          "default": "hilited_key_text_color"
        },
        "hilited_off_key_symbol_color": {
          "type": "string",
          "default": "hilited_key_symbol_color"
        },
        "hilited_on_key_text_color": {
          "type": "string",
          "default": "hilited_key_text_color"
        },
        "hilited_on_key_symbol_color": {
          "type": "string",
          "default": "hilited_key_symbol_color"
        },
        "key_back_color": { "type": "string", "default": "back_color" },
        "key_border_color": { "type": "string", "default": "border_color" },
        "key_text_color": {
          "type": "string",
          "default": "candidate_text_color"
        },
        "key_symbol_color": {
          "type": "string",
          "default": "comment_text_color"
        },
        "label_color": { "type": "string", "default": "candidate_text_color" },
        "off_key_back_color": { "type": "string", "default": "key_back_color" },
        "off_key_border_color": { "type": "string", "default": "key_border_color" },
        "off_key_text_color": { "type": "string", "default": "key_text_color" },
        "off_key_symbol_color": { "type": "string", "default": "key_symbol_color" },
        "on_key_back_color": {
          "type": "string",
          "default": "hilited_key_back_color"
        },
        "on_key_border_color": {
          "type": "string",
          "default": "hilited_key_border_color"
        },
        "on_key_text_color": {
          "type": "string",
          "default": "hilited_key_text_color"
        },
        "on_key_symbol_color": {
          "type": "string",
          "default": "hilited_key_symbol_color"
        },
        "preview_back_color": { "type": "string", "default": "key_back_color" },
        "preview_text_color": { "type": "string", "default": "key_text_color" },
        "shadow_color": { "type": "string", "default": "border_color" },
        "root_background": {
          "type": "string",
          "default": "back_color",
          "description": "整个键盘区+候选栏的背景图/色"
        },
        "candidate_background": {
          "type": "string",
          "default": "back_color",
          "description": "候选栏的整体背景图/色"
        },
        "keyboard_back_color": {
          "type": "string",
          "default": "border_color",
          "description": "键盘区的背景图/色"
        },
        "liquid_keyboard_background": {
          "type": "string",
          "default": "keyboard_back_color",
          "description": "liquidKeyboard 的背景图/色"
        },
        "text_back_color": {
          "type": "string",
          "default": "back_color",
          "description": "编码区背景，即悬浮窗背景"
        },
        "long_text_back_color": {
          "type": "string",
          "default": "key_back_color",
          "description": "长文本按键的背景(剪贴板）"
        }
      }
    },
    "preset_color_schemes": {
      "type": "object",
      "patternProperties": {
        "\\w+": {
          "name": {
            "type": "string",
            "description": "方案名稱"
          },
          "author": {
            "type": "string",
            "description": "作者資訊"
          },
          "back_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0xe4e7e9",
            "description": "候選區背景"
          },
          "border_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0xc1c7ca",
            "description": "邊框"
          },
          "candidate_separator_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0xc1c7ca",
            "description": "候選分割背景"
          },
          "candidate_text_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0x5a676e",
            "description": "候選文字"
          },
          "comment_text_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0x7b868c",
            "description": "提示"
          },
          "hilited_back_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0xccd3d7da",
            "description": "標明編碼背景"
          },
          "hilited_candidate_back_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0xd3d7da",
            "description": "標明候選背景"
          },
          "hilited_candidate_text_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "標明候選文字"
          },
          "hilited_comment_text_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "標明提示"
          },
          "hilited_key_back_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0xd3d7da",
            "description": "標明按鍵背景"
          },
          "hilited_key_border_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "標明按鍵邊框"
          },
          "hilited_key_symbol_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "標明按鍵符號"
          },
          "hilited_key_text_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "標明按鍵文字"
          },
          "hilited_off_key_back_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0xd3d7da",
            "description": "標明按鍵關閉狀態背景"
          },
          "hilited_off_key_border_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "標明按鍵關閉狀態邊框"
          },
          "hilited_off_key_text_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "標明按鍵關閉狀態文字"
          },
          "hilited_off_key_symbol_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "標明按鍵關閉狀態符號"
          },
          "hilited_on_key_back_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0xd3d7da",
            "description": "標明按鍵打開狀態背景"
          },
          "hilited_on_key_border_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "標明按鍵打開狀態邊框"
          },
          "hilited_on_key_text_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "標明按鍵打開狀態文字"
          },
          "hilited_on_key_symbol_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "標明按鍵打開狀態符號"
          },
          "hilited_text_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0x23948e",
            "description": "標明編碼"
          },
          "key_back_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0xeceff1",
            "description": "按鍵背景"
          },
          "key_border_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0xeceff1",
            "description": "按鍵邊框"
          },
          "key_symbol_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0x5f6b73",
            "description": "按鍵符號"
          },
          "key_text_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0x37474f",
            "description": "按鍵文字"
          },
          "keyboard_back_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0xffffff",
            "description": "鍵盤背景"
          },
          "label_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "標籤"
          },
          "off_key_back_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0xd3d7da",
            "description": "按鍵關閉狀態背景"
          },
          "off_key_border_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "按鍵關閉狀態邊框"
          },
          "off_key_text_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "按鍵關閉狀態文字"
          },
          "off_key_symbol_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "按鍵關閉狀態符號"
          },
          "on_key_back_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0x23948e",
            "description": "按鍵打開狀態背景"
          },
          "on_key_border_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "按鍵打開狀態邊框"
          },
          "on_key_text_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0x37474f",
            "description": "按鍵打開狀態文字"
          },
          "on_key_symbol_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "按鍵打開狀態符號"
          },
          "preview_back_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0x55bfbfbf",
            "description": "按鍵提示背景"
          },
          "preview_text_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0x23948e",
            "description": "按鍵提示文字"
          },
          "shadow_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "description": "按鍵文字陰影"
          },
          "text_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0x5a676e",
            "description": "編碼"
          },
          "text_back_color": {
            "type": "number",
            "minimum": 0,
            "maximum": 16777215,
            "default": "0xcce4e7e9",
            "description": "編碼區背景"
          }
        }
      }
    },
    "liquid_keyboard": {
      "type": "object",
      "properties": {
        "author": {
          "type": "string"
        },
        "row": { "type": "integer", "description": "每屏最多显示多少行按键" },
        "row_land": {
          "type": "integer",
          "description": "横屏每屏最多显示多少行按键"
        },
        "key_height": { "type": "integer", "description": "按键高度" },
        "key_height_land": {
          "type": "integer",
          "description": "横屏模式按键高度"
        },
        "single_width": {
          "type": "integer",
          "description": "single类型的按键宽度"
        },
        "vertical_gap": { "type": "integer", "description": "纵向按键间隙" },
        "margin_x": { "type": "number", "description": "左右按键间隙的1/2" },
        "fixed_key_bar": {
          "type": "object",
          "properties": {
            "position": {
              "enum": ["top", "bottom", "left", "right"],
              "description": "固定按键条摆放位置（相对滚动区域的上/下/左/右方位）"
            },
            "keys": {
              "type": "array",
              "description": "固定按键条的按键（显示名称为对应的label，不能放太多）"
            }
          }
        },
        "keyboards": { "type": "array", "items": { "type": "string" } }
      }
    },
    "preset_keys": {
      "type": "object",
      "patternProperties": {
        "\\w+": {
          "type": "object",
          "properties": {
            "label": { "oneOf": [{ "type": "string" }, { "type": "integer" }] },
            "send": { "oneOf": [{ "type": "string" }, { "type": "integer" }] }
          }
        }
      }
    },
    "preset_keyboards": {
      "type": "object",
      "patternProperties": {
        "\\w+": {
          "type": "object",
          "properties": {
            "name": { "type": "string" },
            "author": { "type": "string" },
            "ascii_mode": { "type": "integer" },
            "width": { "type": "number" },
            "height": { "type": "number" },
            "lock": { "type": "boolean" },
            "keys": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "click": {
                    "oneOf": [
                      { "type": "string" },
                      { "type": "integer" },
                      { "type": "boolean" }
                    ]
                  },
                  "long_click": {
                    "oneOf": [{ "type": "string" }, { "type": "integer" }]
                  },
                  "label": { "type": "string" },
                  "width": { "type": "number" },
                  "swipe_left": { "type": "string" },
                  "swipe_right": { "type": "string" },
                  "swipe_up": { "type": "string" },
                  "swipe_down": { "type": "string" },
                  "composing": { "type": "string" },
                  "send_bindings": { "type": "boolean" }
                }
              }
            }
          }
        }
      }
    }
  }
}

---

--- METRICS ---
- Files Extracted: 4
- Estimated Token Budget: ~9166 tokens
- Canonical Reference: https://codewiki.google/github.com/osfans/trime
