Page MenuHomePhabricator

IBus
Updated 1,294 Days AgoPublic

  • D-Bus 架構實做的輸入法架構
  • 不使用預設的 system bus 或 session bus, 另外用一個專屬的 bus 供元件之間的溝通使用。
  • IBus 包含了以下幾個元件:
    • IBus daemon (ibus-daemon): 主要服務入口
    • IBus client: 使用輸入法的應用程式
    • Engine: 輸入法的 object
    • Input context: Client 不會直接跟 engine 溝通,而是透過 input context。每個 client 會用幾個 input context 不一定,例如 GNOME terminal 是每個終端機就使用一個 context,Chromium 58 是一個視窗用一個 context,Firefox 53 是每個視窗兩個 context (猜測可能是 UI 元件一個,網頁輸入元件一個)。
    • Factory: 每次切換輸入法時,IBus 都會產生一個新的 engine,而製造 engine 的稱為 factory。原則上每種輸入法有一個 factory,但也有像 xkb (simple) 是一個 factory 製造所有 layout (xkb:us::eng, xkb:us:dvorak:eng, ...) 的 engine。
    • Panel 是 IBus 的 UI 部份(比如說以「語言條」來呈現),通常是由桌面環境(如 GNOME, KDE, Unity, etc.)提供實做。Panel 包含了:
      • Pre-edit text: 當前組字內容,常常以內嵌在內容視窗來呈現
      • Auxiliary text: 可用來顯示組字狀態等等
      • Lookup table: 選字表
      • Properties: 按鈕或選單
    • Config: 提供儲存設定的服務
  • IBus daemon 產生的 bus address 寫在 $HOME/.config/ibus/bus/XXXXXXXXX-unix-0 這個檔案中,範例:
# This file is created by ibus-daemon, please do not modify it
IBUS_ADDRESS=unix:abstract=/tmp/ibus/dbus-gj4mSVu0,guid=4bdac399fc305e7075c6bccc59159fe6
IBUS_DAEMON_PID=13344
  • IBus daemon 位在 bus name: org.freedesktop.IBus,object path: /org/freedesktop/IBus,主要的 interface 是 org.freedesktop.IBus:
<interface name="org.freedesktop.IBus">
  <method name="CreateInputContext">
    <arg type="s" name="client_name" direction="in"/>
    <arg type="o" name="object_path" direction="out"/>
  </method>
  <method name="RegisterComponent">
    <arg type="v" name="component" direction="in"/>
  </method>
  <method name="GetEnginesByNames">
    <arg type="as" name="names" direction="in"/>
    <arg type="av" name="engines" direction="out"/>
  </method>
  <method name="Exit">
    <arg type="b" name="restart" direction="in"/>
  </method>
  <method name="Ping">
    <arg type="v" name="data" direction="in"/>
    <arg type="v" name="data" direction="out"/>
  </method>
  <method name="SetGlobalEngine">
    <arg type="s" name="engine_name" direction="in"/>
  </method>
  <method name="GetAddress">
    <annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
    <arg type="s" name="address" direction="out"/>
  </method>
  <method name="CurrentInputContext">
    <annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
    <arg type="o" name="object_path" direction="out"/>
  </method>
   <method name="ListEngines">
    <annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
    <arg type="av" name="engines" direction="out"/>
  </method>
  <method name="ListActiveEngines">
    <annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
    <arg type="av" name="engines" direction="out"/>
  </method>
  <method name="GetUseSysLayout">
    <annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
    <arg type="b" name="enabled" direction="out"/>
  </method>
  <method name="GetUseGlobalEngine">
    <arg type="b" name="enabled" direction="out"/>
  </method>
  <method name="IsGlobalEngineEnabled">
    <annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
    <arg type="b" name="enabled" direction="out"/>
  </method>
  <method name="GetGlobalEngine">
    <annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
    <arg type="v" name="desc" direction="out"/>
  </method>
  <signal name="RegistryChanged"/>
  <signal name="GlobalEngineChanged">
    <arg type="s" name="engine_name"/>
  </signal>
  <property type="s" name="Address" access="read"/>
  <property type="o" name="CurrentInputContext" access="read"/>
  <property type="av" name="Engines" access="read"/>
  <property type="v" name="GlobalEngine" access="read"/>
  <property type="as" name="PreloadEngines" access="write">
    <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
  </property>
  <property type="b" name="EmbedPreeditText" access="readwrite">
    <annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
  </property>
  <property type="av" name="ActiveEngines" access="read"/>
</interface>
  • Client 透過 input context 跟 engine 溝通。Client 呼叫 IBus daemon 的 CreateInputContext method 來產生 input context,並回傳該 context 的 object path (bus name 跟 IBus daemon 相同)。Input context 的主要 interface 是 org.freedesktop.IBus.InputContext:
<interface name="org.freedesktop.IBus.InputContext">
  <method name="ProcessKeyEvent">
    <arg type="u" name="keyval" direction="in"/>
    <arg type="u" name="keycode" direction="in"/>
    <arg type="u" name="state" direction="in"/>
    <arg type="b" name="handled" direction="out"/>
  </method>
  <method name="SetCursorLocation">
    <arg type="i" name="x" direction="in"/>
    <arg type="i" name="y" direction="in"/>
    <arg type="i" name="w" direction="in"/>
    <arg type="i" name="h" direction="in"/>
  </method>
  <method name="SetCursorLocationRelative">
    <arg type="i" name="x" direction="in"/>
    <arg type="i" name="y" direction="in"/>
    <arg type="i" name="w" direction="in"/>
    <arg type="i" name="h" direction="in"/>
  </method>
  <method name="ProcessHandWritingEvent">
    <arg type="ad" name="coordinates" direction="in"/>
  </method>
  <method name="CancelHandWriting">
    <arg type="u" name="n_strokes" direction="in"/>
  </method>
  <method name="FocusIn"/>
  <method name="FocusOut"/>
  <method name="Reset"/>
  <method name="SetCapabilities">
    <arg type="u" name="caps" direction="in"/>
  </method>
  <method name="PropertyActivate">
    <arg type="s" name="name" direction="in"/>
    <arg type="u" name="state" direction="in"/>
  </method>
  <method name="SetEngine">
    <arg type="s" name="name" direction="in"/>
  </method>
  <method name="GetEngine">
    <arg type="v" name="desc" direction="out"/>
  </method>
  <method name="SetSurroundingText">
    <arg type="v" name="text" direction="in"/>
    <arg type="u" name="cursor_pos" direction="in"/>
    <arg type="u" name="anchor_pos" direction="in"/>
  </method>
  <signal name="CommitText">
    <arg type="v" name="text"/>
  </signal>
  <signal name="ForwardKeyEvent">
    <arg type="u" name="keyval"/>
    <arg type="u" name="keycode"/>
    <arg type="u" name="state"/>
  </signal>
  <signal name="UpdatePreeditText">
    <arg type="v" name="text"/>
    <arg type="u" name="cursor_pos"/>
    <arg type="b" name="visible"/>
  </signal>
  <signal name="ShowPreeditText"/>
  <signal name="HidePreeditText"/>
  <signal name="UpdateAuxiliaryText">
    <arg type="v" name="text"/>
    <arg type="b" name="visible"/>
  </signal>
  <signal name="ShowAuxiliaryText"/>
  <signal name="HideAuxiliaryText"/>
  <signal name="UpdateLookupTable">
    <arg type="v" name="table"/>
    <arg type="b" name="visible"/>
  </signal>
  <signal name="ShowLookupTable"/>
  <signal name="HideLookupTable"/>
  <signal name="PageUpLookupTable"/>
  <signal name="PageDownLookupTable"/>
  <signal name="CursorUpLookupTable"/>
  <signal name="CursorDownLookupTable"/>
  <signal name="RegisterProperties">
    <arg type="v" name="props"/>
  </signal>
  <signal name="UpdateProperty">
    <arg type="v" name="prop"/>
  </signal>
  <property type="(uu)" name="ContentType" access="write"/>
</interface>
  • Client 呼叫 IBus daemon 的 SetGlobalEngine (全域輸入法)或 input context 的 SetEngine (非全域輸入法)來切換輸入法,此時 IBus daemon 使用 factory 來產生 engine。Factory 的 bus name 由自己決定,例如酷音位在 org.freedesktop.IBus.Chewing,factory 透過設定檔或是 RegisterComponent 來告訴 IBus daemon 它的 bus name。Factory 產生 engine 時回傳該 engine 的 object path,bus name 則跟 factory 本身相同。Factory 主要的 interface 是 org.freedesktop.IBus.Factory:
<interface name="org.freedesktop.IBus.Factory">
  <method name="CreateEngine">
    <arg type="s" name="name" direction="in"/>
    <arg type="o" name="arg_1" direction="out"/>
  </method>
</interface>
  • Engine 是真正作輸出入處理的元件,主要 interface 是 org.freedeskstop.IBus.Engine:
<interface name="org.freedesktop.IBus.Engine">
  <method name="ProcessKeyEvent">
    <arg type="u" name="keyval" direction="in"/>
    <arg type="u" name="keycode" direction="in"/>
    <arg type="u" name="state" direction="in"/>
    <arg type="b" name="arg_3" direction="out"/>
  </method>
  <method name="SetCursorLocation">
    <arg type="i" name="x" direction="in"/>
    <arg type="i" name="y" direction="in"/>
    <arg type="i" name="w" direction="in"/>
    <arg type="i" name="h" direction="in"/>
  </method>
  <method name="ProcessHandWritingEvent">
    <arg type="ad" name="coordinates" direction="in"/>
  </method>
  <method name="CancelHandWriting">
    <arg type="u" name="n_strokes" direction="in"/>
  </method>
  <method name="SetCapabilities">
    <arg type="u" name="caps" direction="in"/>
  </method>
  <method name="PropertyActivate">
    <arg type="s" name="name" direction="in"/>
    <arg type="u" name="state" direction="in"/>
  </method>
  <method name="PropertyShow">
    <arg type="s" name="name" direction="in"/>
  </method>
  <method name="PropertyHide">
    <arg type="s" name="name" direction="in"/>
  </method>
  <method name="CandidateClicked">
    <arg type="u" name="index" direction="in"/>
    <arg type="u" name="button" direction="in"/>
    <arg type="u" name="state" direction="in"/>
  </method>
  <method name="FocusIn"/>
  <method name="FocusOut"/>
  <method name="Reset"/>
  <method name="Enable"/>
  <method name="Disable"/>
  <method name="PageUp"/>
  <method name="PageDown"/>
  <method name="CursorUp"/>
  <method name="CursorDown"/>
  <method name="SetSurroundingText">
    <arg type="v" name="text" direction="in"/>
    <arg type="u" name="cursor_pos" direction="in"/>
    <arg type="u" name="anchor_pos" direction="in"/>
  </method>
  <signal name="CommitText">
    <arg type="v" name="text"/>
  </signal>
  <signal name="UpdatePreeditText">
    <arg type="v" name="text"/>
    <arg type="u" name="cursor_pos"/>
    <arg type="b" name="visible"/>
    <arg type="u" name="mode"/>
  </signal>
  <signal name="UpdateAuxiliaryText">
    <arg type="v" name="text"/>
    <arg type="b" name="visible"/>
  </signal>
  <signal name="UpdateLookupTable">
    <arg type="v" name="table"/>
    <arg type="b" name="visible"/>
  </signal>
  <signal name="RegisterProperties">
    <arg type="v" name="props"/>
  </signal>
  <signal name="UpdateProperty">
    <arg type="v" name="prop"/>
  </signal>
  <signal name="ForwardKeyEvent">
    <arg type="u" name="keyval"/>
    <arg type="u" name="keycode"/>
    <arg type="u" name="state"/>
  </signal>
  <property type="(uu)" name="ContentType" access="write"/>
</interface>
  • Panel 位在 bus name: org.freedesktop.IBus.Panel,object path: /org/freedesktop/IBus/Panel,主要 interace 是 org.freedesktop.IBus.Panel:
<interface name="org.freedesktop.IBus.Panel">
  <method name="UpdatePreeditText">
    <arg type="v" name="text" direction="in"/>
    <arg type="u" name="cursor_pos" direction="in"/>
    <arg type="b" name="visible" direction="in"/>
  </method>
  <method name="ShowPreeditText"/>
  <method name="HidePreeditText"/>
  <method name="UpdateAuxiliaryText">
    <arg type="v" name="text" direction="in"/>
    <arg type="b" name="visible" direction="in"/>
  </method>
  <method name="ShowAuxiliaryText"/>
  <method name="HideAuxiliaryText"/>
  <method name="UpdateLookupTable">
    <arg type="v" name="table" direction="in"/>
    <arg type="b" name="visible" direction="in"/>
  </method>
  <method name="ShowLookupTable"/>
  <method name="HideLookupTable"/>
  <method name="CursorUpLookupTable"/>
  <method name="CursorDownLookupTable"/>
  <method name="PageUpLookupTable"/>
  <method name="PageDownLookupTable"/>
  <method name="RegisterProperties">
    <arg type="v" name="props" direction="in"/>
  </method>
  <method name="UpdateProperty">
    <arg type="v" name="prop" direction="in"/>
  </method>
  <method name="FocusIn">
    <arg type="o" name="ic" direction="in"/>
  </method>
  <method name="FocusOut">
    <arg type="o" name="ic" direction="in"/>
  </method>
  <method name="DestroyContext">
    <arg type="o" name="ic" direction="in"/>
  </method>
  <method name="SetCursorLocation">
    <arg type="i" name="x" direction="in"/>
    <arg type="i" name="y" direction="in"/>
    <arg type="i" name="w" direction="in"/>
    <arg type="i" name="h" direction="in"/>
  </method>
  <method name="SetCursorLocationRelative">
    <arg type="i" name="x" direction="in"/>
    <arg type="i" name="y" direction="in"/>
    <arg type="i" name="w" direction="in"/>
    <arg type="i" name="h" direction="in"/>
  </method>
  <method name="Reset"/>
  <method name="StartSetup"/>
  <method name="StateChanged"/>
  <method name="HideLanguageBar"/>
  <method name="ShowLanguageBar"/>
  <method name="ContentType">
    <arg type="u" name="purpose" direction="in"/>
    <arg type="u" name="hints" direction="in"/>
  </method>
  <signal name="CursorUp"/>
  <signal name="CursorDown"/>
  <signal name="PageUp"/>
  <signal name="PageDown"/>
  <signal name="PropertyActivate">
    <arg type="s" name="prop_name"/>
    <arg type="i" name="prop_state"/>
  </signal>
  <signal name="PropertyShow">
    <arg type="s" name="prop_name"/>
  </signal>
  <signal name="PropertyHide">
    <arg type="s" name="prop_name"/>
  </signal>
  <signal name="CandidateClicked">
    <arg type="u" name="index"/>
    <arg type="u" name="button"/>
    <arg type="u" name="state"/>
  </signal>
</interface>
  • IBus Config 位在 bus name: org.freedesktop.IBus.Config,object path: /org/freedesktop/IBus/Config,主要的 interface 是 org.freedesktop.IBus.Config:
<interface name="org.freedesktop.IBus.Config">
  <method name="SetValue">
    <arg type="s" name="section" direction="in"/>
    <arg type="s" name="name" direction="in"/>
    <arg type="v" name="value" direction="in"/>
  </method>
  <method name="GetValue">
    <arg type="s" name="section" direction="in"/>
    <arg type="s" name="name" direction="in"/>
    <arg type="v" name="value" direction="out"/>
  </method>
  <method name="GetValues">
    <arg type="s" name="section" direction="in"/>
    <arg type="a{sv}" name="values" direction="out"/>
  </method>
  <method name="UnsetValue">
    <arg type="s" name="section" direction="in"/>
    <arg type="s" name="name" direction="in"/>
  </method>
  <signal name="ValueChanged">
    <arg type="s" name="section"/>
    <arg type="s" name="name"/>
    <arg type="v" name="value"/>
  </signal>
</interface>
  • org.freedesktop.IBus.Notifications: only for GTK2?
Last Author
iongchun
Last Edited
May 17 2017, 1:18 PM

Document Hierarchy

Event Timeline

iongchun changed the title from Localization to IBus.May 13 2017, 9:54 PM
iongchun edited the content of this document. (Show Details)
iongchun moved this document from Localization.
iongchun edited the content of this document. (Show Details)May 13 2017, 9:57 PM
iongchun edited the content of this document. (Show Details)May 14 2017, 10:28 AM
iongchun edited the content of this document. (Show Details)May 14 2017, 6:56 PM
iongchun edited the content of this document. (Show Details)May 14 2017, 9:53 PM
iongchun edited the content of this document. (Show Details)May 15 2017, 11:12 AM
iongchun edited the content of this document. (Show Details)May 15 2017, 12:17 PM
iongchun edited the content of this document. (Show Details)May 15 2017, 3:00 PM
iongchun edited the content of this document. (Show Details)May 15 2017, 3:12 PM
iongchun edited the content of this document. (Show Details)May 15 2017, 10:33 PM
iongchun edited the content of this document. (Show Details)May 17 2017, 1:18 PM