RFC-0096 - 使用者輸入架構

RFC-0096:使用者輸入架構
狀態已接受
區域
  • HCI
說明

透過具有圖形使用者介面和多個執行階段的系統,在 Fuchsia 上提供使用者輸入事件 (鍵盤、滑鼠、觸控等) 的整體架構。

問題
變更
  • 516176 年
作者
審查人員
提交日期 (年/月)2021-04-15
審查日期 (年/月)2021-05-26

摘要

這個 RFC 說明在具有圖形使用者介面和多個執行階段的系統上,在 Fuchsia 上提供使用者輸入事件 (鍵盤、滑鼠、觸控等) 的目標高階架構。使用者可透過各種方法/裝置 (包括鍵盤、滑鼠、觸控和按鈕) 將輸入內容提供給系統。這個 RFC 會說明 Fuchsia 上的輸入事件如何從驅動程式庫層級原始資料,到分派至使用者空間軟體 (例如 Flutter 應用程式) 的輸入事件。此處所述的元件在發布時處於開發階段。

提振精神

為了支援 Fuchsia 的多元包容理念,Fuchsia 輸入內容必須針對採用不同 UI 架構 (例如 Flutter、Chromium) 的不同執行階段建構的元件,提供平台層級的支援,並讓產品擁有者自訂輸入行為。在其他平台上,這些行為通常已納入特定 UI 架構的實作中。Fuchsia 想將平台輸入處理作業與特定 UI 架構的具體細節分開處理,面臨許多獨特的挑戰。

Fuchsia 程式碼目前有多個輸入路徑路徑 (根簡報者輸入管道),針對偏好的路徑和遷移計畫提供有限的公開指引。此 RFC 概述 Fuchsia 中使用者輸入轉送的目標架構,並提供相關指引,說明如何將輸入轉送延伸至未來用途。

相關規定

  • 安全性:Fuchsia 輸入堆疊可讓您輕鬆打造安全的產品。
    • 輸入事件可能包含密碼和付款資料等機密資料,以及使用者處於活動狀態的時間資訊。所有使用者輸入事件都應視為個人識別資訊,而且只透過可信任的系統元件分派給使用者軟體。
    • 如果不正確轉送使用者輸入內容,也可能會遭到濫用,例如惡意使用者介面導致使用者意外點選非預期點選的按鈕 (「點擊劫持」)。
    • 在可能的情況下,Fuchsia 平台應提供 API 介面,方便開發人員透過系統輕鬆瞭解及稽核使用者輸入事件的流程,藉此建構安全的產品。
  • 正確性:系統會根據使用者預期傳送輸入事件。
    • Fuchsia 輸入系統負責在情境中解讀輸入事件,並將這些事件傳送至系統上目前執行的正確目標元件。不過,「正確」的定義可能因事件和產品類型而異。
    • 即使 UI 為動畫狀態或變更大小,輸入事件傳送也應保持一致。
    • 事件有時可能會同時分派到多個元件,例如鍵盤快速鍵。
  • 效能:使用者輸入的速度很快 (夠多)。
    • 雖然確切的延遲時間要求因輸入裝置和產品類型而異,但輸入傳遞內容特別容易受到延遲影響,因此應力求夠快,讓使用者不會察覺到延遲。
    • 輸入架構應避免產生不必要的延遲。特別是,您應謹慎處理程序結構定義切換作業,以避免不必要的封鎖呼叫。
  • 可自訂:針對 Fuchsia 平台建構的不同產品,系統應支援不同的使用者輸入行為。* 不過,這項 RFC 中建議的初始實作僅可滿足自訂最終需求的部分要求。(請參閱「輸入管道自訂」一節)。
    • 有些產品需要鍵盤和滑鼠支援,而有些產品則主要著重於透過觸控和按鈕的互動。
    • Fuchsia 平台應針對產品專屬的輸入行為提供掛鉤 (例如,根據系統內容來不同的按鈕事件解讀方式)。
    • Fuchsia 應允許產品視需要將輸入事件對應至不同的類型,例如將觸控事件重新解讀為滑鼠事件,以便與不支援觸控手勢的軟體相容。
  • 可擴充:Fuchsia 可對新的輸入模式提供支援。
    • 雖然輸入需求差異很大的產品可能需要平台變更,但仍應能在不大幅重新編寫現有輸入堆疊的情況下,新增對新輸入法的支援。

激勵範例

這些用途尚未全面支援,但針對這個架構希望支援的行為類型提供深入見解。

  • 當來自多個架構的 UI 在螢幕上顯示時,可正確解讀觸控螢幕手勢。
  • 螢幕上有多個文字方塊 (由不同架構支援) 時,使用適當的版面配置資訊轉送鍵盤輸入內容。
  • 除了這些按鈕的一般功能以外,允許按下按鈕組合 (例如調高音量和調低音量按鈕) 來觸發恢復原廠設定。
  • 當裝置處於睡眠或關閉狀態時,隱藏筆電觸控螢幕的輸入。
  • 解讀筆電觸控板手勢 (雙指撥動縮放、雙指捲動)。

背景與術語

  • 人機介面裝置 (HID) – 可讓使用者輸入及輸出的裝置,例如鍵盤、滑鼠、觸控螢幕或消費者控制項 (按鈕)。通常是指使用 USB-HID 規格的裝置。
  • 輸入事件:單一使用者輸入事件,例如按鍵、滑鼠移動動作或觸控事件。當處理的事件發生時,可根據目前情境為事件加上註解。
  • 指標事件 - 對應至螢幕上位置的使用者輸入事件,例如觸控或滑鼠事件。指標事件是輸入事件的子集。
  • 事件串流:一組相關輸入事件,通常會在時間接近時發生。
  • 輸入處理常式:這是執行單一輸入處理階段的軟體。輸入處理常式會將輸入事件做為輸入內容,並發出輸入事件。可能會修改事件或與系統的其他部分通訊。
  • 輸入管道演算法 – 是結合一系列輸入處理常式來處理 Fuchsia 輸入的演算法。這可做為 Fuchsia 輸入內容的政策層。
  • 輸入管道實作 - 輸入管道演算法的實作。實務上,這是 fuchsia.git 中的元件,負責將驅動程式庫層級使用者輸入事件轉送至系統的其餘部分。
  • Scenic – Fuchsia 圖形引擎。View 指標也負責轉送指標事件。
  • 全球場景圖 – Scenic 算繪的圖形內容樹狀結構。
  • 檢視畫面 - 場景圖中的子空間。檢視區塊通常會與螢幕上的區域對應,但這個區域不一定是矩形。
  • ViewRef - 與特定檢視畫面相關聯的事件組合。這會用於識別多個 Fuchsia 元件中的檢視畫面。

架構總覽

這項設計提供 Fuchsia 使用者輸入事件的整體流程總覽,但不會涵蓋每種輸入類型的所有特定詳細資料。當中許多詳細資料以特定垂直設計為主,點選連結請見下方相關章節。

由下至上: dev/class/input-report -> 輸入管道 -> {scenic OR a11y Manager OR IME Manager OR Media button 事件監聽器} -> {Chromium OR flutter OR
carnelian} -> {View 1 OR view 2 OR view3 OR view 4} 側邊:產品畫面工作階段
元件/輸入管道 - 輸入管道 -

系統會根據幾項相關規則分派事件,包括但不限於:

  • 該事件類型的產品政策 (例如將所有音量事件分派到設定)
  • 事件在畫面上的位置 (例如觸控或滑鼠)
  • 目前的焦點檢視畫面 (例如文字輸入)

「輸入管道」是 Fuchsia 元件,負責管理這些規則及其互動,以及將使用者輸入事件以及處理這些事件所需的資訊,轉送至適當的系統服務。它會實作輸入管道演算法 (鏈結輸入處理常式系統,每個系統都會在裝置輸入處理中執行獨立的步驟)。這個元件會做為 Fuchsia 輸入內容的政策層。輸入管道會透過輸入驅動程式直接從驅動程式庫程式層擷取事件,也會從測試和軟體產生的事件 (例如虛擬鍵盤的事件) 擷取合成事件。

事件從全域的輸入管道移動時,會從全域低階事件 (沒有語意含義,但機密資料) 移至限定範圍,具有本機意義的已處理資料,可由使用者軟體 (手勢、字元等) 解譯。驅動程式層級輸入事件分為兩大類:

  • 對應螢幕上特定位置的指標事件。
  • 按鈕和切換事件。

但日後可能會擴大支援範圍。USB-HID 使用表廣泛且內含多重圖樣,包括飛行模擬模式、運動設備和虛擬實境裝置頁面。

驅動程式層級的輸入事件可轉換為:

  • 觸控手勢。
  • 滑鼠事件 (包括捲動)。
  • 文字輸入事件。
  • 語意無障礙動作。
  • 按鈕事件 (例如調整音量、開啟/關閉攝影機)。

每個事件通常會以下列方式分派:

Driver -> Input Pipeline -> UI System Component -> UI Framework-> UI View
  • 輸入管道元件包含多個名為 Input Handler 的內部階段。輸入管道可做為輸入政策層,可能會因產品類型而異。(請參閱下方的「輸入管道自訂」一節)。
  • UI 系統元件包括 View、無障礙管理工具和 IME 管理員,但隨著我們為平台加入功能,這些元件可能會隨著時間增加。這些元件是 Fuchsia 平台的一部分,並且存放在 fuchsia.git。這些元件可因產品而異。
  • UI 系統元件負責決定哪些檢視區塊或檢視區塊應接收事件,並將該資訊傳遞至 UI 架構執行元件以進行分派。UI 系統元件會使用 View 中的資訊 (通常是聚焦鏈) 來判斷應接收事件的檢視畫面。
  • UI 系統元件可能也會耗用事件。
  • UI 架構目前包含 Flutter、Chromium 和 Carnelian。我們預計日後會支援更多 UI 架構/執行階段。這些可用於各種產品類型,但不屬於 Fuchsia 平台。
  • UI 檢視畫面是圖形元件,其擁有對應的畫面區域,稱為檢視區塊。(請參閱下方的檢視畫面和事件轉送)。
  • 媒體按鈕事件不一定會遵循此模式。媒體按鈕的最終目的地可能是設定服務,而非 UI 檢視畫面。

在某些情況下,事件可能需要經過其他階段才會最終提交。舉例來說,觸控事件可能會透過 View 分派給虛擬鍵盤元件,這會產生合成按鍵按下,然後透過輸入管道分派。

輸入管道會將指標事件傳送至 View,而這負責將事件分派到正確的執行階段執行個體。如此一來,ViewModel 就能全面掌握全域一致的螢幕畫面,在動畫播放期間避免發生競爭狀況。(請參閱下方的轉送圖形事件)。

設計

輸入事件來源

輸入事件通常會透過輸入驅動程式或 Fuchsia 元件進入系統,這類元件可做為輸入裝置的控制器 (例如藍牙 HID 裝置的 bt-host 元件)。在許多情況下,這類事件是從人機介面裝置 (HID) 事件開始,但也有部分例外情況。驅動程式和控制器會發出每個事件做為 fuchsia.ui.input/InputReport。一般的輸入報表會由輸入管道使用和轉換。但在復原模式下,系統會將其直接傳送至使用 Carnelian 實作的終端機元件,而不會進行任何中介處理。

測試的輸入事件產生方式不同。(請參閱下方的測試)。

輸入管道

輸入管道元件是 Fuchsia 系統元件。實作輸入管道演算法。輸入管道元件的運作方式如同輸入堆疊中的政策層。負責判斷特定裝置所支援的事件類型、如何分派輸入事件,以及管理輸入裝置。

輸入管道演算法的組成要素如下:

繫結階段通常會利用裝置狀態相關資訊來擴增 InputReports。例如:

  • 含有相對滑鼠移動的 InputReport 會變為具有螢幕相關座標的 InputEvent。
  • 按下 InputReports 串流會成為「key down」和「key up」InputEvents 的串流。(驅動程式通常只會回報特定時間下有哪些按鍵,而不會分開和上下事件)。系統可能會在稍後的 InputReport 中缺少鍵,藉此推斷「鍵上」。

不過,輸入管道不會在工作階段領域中執行,輸入管道比工作階段更特殊,並使用我們目前不希望向工作階段元件公開的多項功能。

輸入管道實作項目會透過 Fussia 平台提供給產品擁有者。根據這個 RFC 的發布作業,這些實作項目是以 Rust 編寫,輸入處理常式則是實作共用 InputHandler Rust 特徵的類別,但日後為了進行最佳化和擴充能力可能會隨時變更。

目前平台提供兩種輸入管道實作方式,一種針對主要需要觸控螢幕互動的裝置進行最佳化,另一種則針對有滑鼠和鍵盤的產品周圍進行最佳化。這種有限的自訂程度未來可能會擴大。(請參閱下方的「輸入管道自訂」一節)。

輸入處理常式

輸入處理常式 輸入處理常式是主要機制,可讓產品擁有者自訂與產品狀態相關的輸入處理方式。我們有時會將這稱為輸入事件的產品政策。輸入處理常式可以

  • 新增情境資訊 (例如使用中的鍵盤配置,或按下滑鼠同時按住的按鍵),藉此強化事件。
  • 根據周圍的事件串流 (例如輸入平滑、觸控板手勢) 修改事件。
  • 您可以在處理常式內處理事件,或將事件傳送至 UI 系統元件公開的服務,再由此負責將該事件分派至適當的 UI 檢視區塊組合。目標檢視畫面或檢視畫面是由 View 中的目前檢視畫面焦點決定。(請參閱下方的「聚焦」一節)。
  • 傳送 OutputReports,以便控制輸入裝置狀態 (例如設定 Capd Lock LED)。

就短期而言,我們定義了由每個輸入處理常式實作的 Rust 特徵 InputHandler,長期來看,這可以透過 FIDL 介面取代。每個處理常式都必須具有使用輸入事件的能力,且應輸出輸入事件 (可能為空白) 向量。

#[async_trait]
pub trait InputHandler: Send {
    /// Returns a vector of InputEvents after handling `input_event`.
    ///
    /// # Parameters
    /// `input_event`: The InputEvent to be handled.
    async fn handle_input_event(
        &mut self,
        input_event: input_device::InputEvent,
    ) -> Vec<input_device::InputEvent>;
}

日後在 Fuchsia 上建構的產品可能需要使用的輸入處理常式範例 (部分相當受歡迎):

  • 無障礙功能輸入處理常式:當啟用相關的無障礙功能 (例如切換導覽或使用鍵盤快速鍵的螢幕閱讀器) 時,將事件傳送至 11y Manager。
  • 捷徑處理常式:判斷鍵盤事件是否與使用中的鍵盤快速鍵 (可呼叫其他元件)。
  • 「Locale Handler」:套用目前檢視畫面的有效語言代碼相關資訊。
  • 指標事件調度處理常式:將觸控/滑鼠/觸控筆事件傳送至 View,以便分派到檢視畫面。
  • 媒體按鈕處理常式:將媒體按鈕轉送至設定服務 (或其他地方)。
  • 鍵盤版面配置處理常式:使用目前使用中的鍵盤配置為鍵盤事件加上註解。
  • TouchPad 手勢處理常式:觸控板手勢,以及轉寄對等的滑鼠事件。
  • 輸入流暢處理常式:以平均計算事件減少時基誤差。
  • Focus Handler:使用 ViewRef 為目前聚焦的檢視畫面加上註解鍵盤事件。
  • 睡眠模式處理常式:在裝置處於睡眠狀態時隱藏輸入內容。
  • 多點觸控鬆開關按鈕處理常式:將觸控手勢事件解讀為媒體按鈕。

在許多情況下,輸入處理常式會將事件分派至 Fuchsia 系統服務,例如 View、無障礙管理工具、IME Manager 等。在這種情況下,該事件會標示為「處理中」,並透過管道的其餘部分傳播。(請參閱下方的「事件串流一致性」)。

自訂輸入管道

透過指定要納入的處理常式及其顯示順序,輸入管道執行個體化。這可讓您新增處理常式、重新排序處理常式,或將已修改的管道執行個體化。Rust 中的範例:

async fn input_handlers(
 ...
 ...
) -> Vec<Box<dyn InputHandler>> {
    let mut handlers: Vec<Box<dyn InputHandler>> = vec![];
    // Shortcut needs to go before IME.
    add_shortcut_handler(&mut handlers).await;
    add_ime(&mut handlers).await;
    add_touch_handler(..., &mut handlers).await;
    add_mouse_handler(..., &mut handlers).await;
    handlers
}

2021 年,這個平台提供兩個輸入管道實作項目,每個實作項目都會做為 fuchsia.git 中的一個元件進行實作,能夠運用未在 fuchsia SDK 中發布的特殊權限 API。這些實作會共用許多輸入處理常式 (它們執行相同的程式碼),主要在支援的輸入模式方面主要不同。其中一種實作方式,是針對主要使用觸控螢幕互動的裝置,以及另以滑鼠和鍵盤在產品周圍的方向最佳化。產品專屬程式碼受限於設定程式碼,用於判定要執行個體化的處理常式。

在短期內,可透過向工作階段公開能力 (可能是以 FIDL API 形式透過工作階段架構反映的設定) 來授予工作階段有限的設定,讓工作階段決定要啟用的輸入模式。此 API 可針對個別產品進行設定,並在工作階段啟動時生效 (即設定產品使用者體驗時)。在正常產品作業期間,並沒有打算「即時」重新設定管道的意圖。

隨著 Fuchsia 擴展來支援其他產品類別,這組輸入處理常式和不同產品設定可能會進一步擴充,因此需要提供能力,讓工作階段可從各種管道設定中挑選,或者直接設定應存在的輸入管道階段以及其順序。某些輸入處理常式可能是特定產品,且需要位於 fuchsia.git 之外。

每項產品都應能使用符合特定需求需求的輸入管道,當中包含該產品支援輸入行為所需的輸入處理常式。確切做法不在本 RFC 的涵蓋範圍內。在理想情況下,任何這類設定解決方案都會利用平台提供的結構化設定機制,而不是發想特定的輸入項目,而且也應會費力,以公開滿足產品需求所需的最低可能設定途徑。

檢視畫面與事件轉送

Fuchsia UI 可能會同時包含螢幕上多個執行階段的圖形。UI 會整理成 Scenic 擁有的「全域場景圖」,其中包含構成 UI 的圖形內容,以及算繪該 UI 所需的資訊。執行階段可將使用者看到的內容新增至場景圖中名為「檢視畫面」的景觀資源,藉此為場景提供使用者可見的內容。一般而言,檢視畫面會對應螢幕上的某個區域,但這些區域不一定是矩形,而且在特定時間並不會顯示所有檢視畫面。由於每個檢視畫面都是風景區資源,不適合在其他元件中參照,因此我們將名為 ViewRef 的核心物件與每個檢視畫面建立關聯。

系統會以階層方式整理檢視畫面,其中子項檢視畫面只會影響其上層檢視畫面邊界內的螢幕空間,即嚴格的包含模型。」如果檢視區塊是圖表中另一個檢視畫面的父項,父項檢視畫面會保留對其子項的特定控制項,尤其是與內容位置和事件轉送有關。

查看樹狀結構

下圖說明場景圖根層級的結構。

Root -> 無障礙功能檢視畫面 -> sysUI -> {some view, some other view, but other view}

  • 與無障礙管理員相關聯的檢視畫面可讓無障礙管理員攔截無障礙服務和變更焦點所需的輸入事件,並視需要在使用者介面的其餘部分繪製「上方」。
  • 「sysUI」(系統 UI) 檢視畫面是所有其他檢視畫面的父項。這種檢視畫面通常用於實作「系統手勢」(例如在螢幕邊緣滑動以變更應用程式) 和系統鍵盤快速鍵。也適用於 UI 的許多非輸入層面。

轉送圖形事件

如果是對應螢幕上特定位置的使用者事件 (例如觸控、滑鼠、觸控筆),則輸入事件會先透過 View 轉送,再分派到與每個檢視畫面相關聯的執行階段執行個體。這種做法的優點包括

  • 場景圖隔離:風景是唯一能全面瞭解畫面位置的元件。我們不允許其他元件查詢特定時間點的畫面內容 (也稱為「命中測試」)。
  • 全球一致性:由於風景是特定檢視畫面在特定時間在畫面上顯示的可靠資料來源,因此使用景觀分派事件可避免檢視畫面大小、位置,或輸入事件發生時間與傳送時間之間消失。當使用者與裝置互動時,可能需要頻繁變更的產品。請注意,View 也擁有焦點鏈,可用於保持非指標事件的調度一致。
  • 平行分派 (手勢消歧):檢視畫面重疊時,表示特定事件串流可能有多個檢視區塊感興趣。舉例來說,產品可能會想要實作「系統手勢」(例如滑動關閉應用程式),但應用程式本身可能會以不同的方式解讀該手勢。View 負責判斷應接收特定事件的檢視畫面,並透過稱為手勢消歧的程序協調這些檢視畫面。在此模式下,觸控事件的串流會平行分派至多個檢視畫面,接著在「手勢」中解析,以決定最終會耗用事件串流的檢視畫面。

應景

為判斷目前執行中的哪個軟體應接收特定輸入事件,我們需要檢視焦點的概念。這大致上是目前「有效」且已準備好接收事件的檢視畫面。不過,實際上多個檢視畫面可能會對每個事件感興趣。

透過聚焦鏈 (也就是檢視畫面樹狀結構中與聚焦檢視畫面及其祖系對應的 ViewRefs 向量) 來判斷檢視畫面焦點。焦點鏈結屬於 View 所有 (因為 View 會管理檢視畫面),但其他元件可能會要求變更目前的焦點,例如回應無障礙動作或鍵盤快速鍵。輸入管道負責監控焦點鏈結中的變更,並將資訊提供給輸入處理常式,而該處理常式可能會將事件轉送至正確的用戶端元件/檢視畫面。焦點鏈結的終端機元素對應於目前的聚焦檢視畫面。

部分處理常式會對單一聚焦檢視畫面感興趣,而其他處理常式會有興趣存取整個聚焦鏈。例如:

  • 不會觸發鍵盤快速鍵的鍵盤事件通常會轉送至目前聚焦的檢視畫面。
  • 無障礙管理員會使用聚焦檢視畫面,判斷螢幕閱讀器目前在哪些項目處於「使用中」狀態。
  • 鍵盤快速鍵管理員對整個焦點鏈結感興趣,其中任何可能已註冊鍵盤快速鍵和相關優先順序。

焦點事件會以特殊類型 InputEvent 的形式在輸入管道中移動,並會嚴格排列其他輸入事件的順序。

事件串流一致性

事件串流是一組相關的 InputEvents,通常會在時間接近時發生。例如:

  • 鍵盤:'a' KEY DOWN -> 'a' KEY UP
  • 滑鼠:HOVER -> HOVER -> Button_DOWN -> Button_UP
  • 輕觸:向下移動 -> 移動 -> 移動 -> 移動 -> 向上移動

系統必須確保管道各階段的事件串流和每個檢視畫面的事件串流一致性。這表示如果輸入處理常式透過轉送到系統服務的方式使用事件,應將適當的「處理」事件傳送至後續的輸入處理常式,以通知任何用戶端。

處理事件串流時焦點有所改變時,情況也會改變。從用戶端的觀點來看,每個「按下按鍵」都必須與對應的「按鍵」相符,或是如果焦點發生變更或輸入裝置中斷連線,則要符合「取消」事件。滑鼠點擊和觸控事件串流也是如此。輸入管道負責將事件標示為「處理」,並透過輸入管道傳播這些事件,以確保串流的一致性。當串流取消時,系統服務負責通知檢視畫面。

效能

可接受的延遲時間

使用者輸入內容具時效性。延遲時間 (也就是從事件發生到 UI 回應的時間) 應盡可能降低,不過使用者對延遲時間的容忍度會因輸入類型而異。使用者可能會遇到效能降低 (可以完成工作) 的情形,以及在某些情況下延遲時間的滿意度低至 10 毫秒。使用者體驗開始明顯降低超過 100 毫秒,且可能超過 300 毫秒都無法接受。直接操控 (例如螢幕上的觸控筆繪圖) 特別敏感,可能需要預測事件才能提供可接受的使用者體驗。(詳情請參閱這份延遲文件)。

由於此 RFC 所描述的輸入系統在執行階段,以及以其為基礎的 UI 所執行的層級較低,因此使用者會遇到系統輸入延遲,以及因處理並轉譯輸入事件回應而造成的任何延遲。因此,輸入系統應盡力盡快為應用程式和執行階段保留大部分的「延遲預算」。

此外,時間一致也很重要。即使平均事件傳送時間很短,但事件時間的變動性極高,仍可能會破壞使用者體驗,因此請務必考量延遲時間分佈情形和平均值。

提升效能

如要縮短輸入架構中的延遲時間,最佳做法是盡量減少不必要的程序環境切換。每次進入核心及結束核心時 (通常需要執行排程器),都會在事件的時間發生變化。

未來我們可能會嘗試在圖形和輸入堆疊中執行多個元件 (例如風景和輸入管道),做為單一程序內的獨立元件,進一步減少程序躍點。如果我們發現這會產生額外的延遲時間,也可能會重新將選擇的 Rust 做為輸入管道的實作語言。

為觸控事件推出手勢消歧 (也稱為平行調度) 功能,可能會產生額外的延遲,同時等待感興趣的元件回應特定事件串流。為了讓這個演算法具有高效能,用戶端必須盡快合作並回應輸入事件。系統會需要一些機制來指定並強制執行用戶端延遲期望 (SLA)。我們會在未來設計中詳細說明這一點。

國際化與輸入內容情境

每個檢視畫面都有專屬的輸入背景資訊,包括使用中的輸入方法 (「使用中的鍵盤」)。輸入背景資訊與 fuchsia.intl.Profile 中的資訊不同,後者包含使用者的偏好語言代碼,會影響 UI 呈現。不過,使用者的語言代碼設定可能會影響可用的輸入法/鍵盤版面配置。如要進一步瞭解 Fuchsia 國際化,請參閱 Fuchsia 國際化說明文件

系統應允許不同的檢視畫面使用不同的輸入方法。例如,使用者可能會以一種語言撰寫電子郵件,同時使用其他語言撰寫電子郵件。產品可選擇強制執行單一系統通用的語言代碼或啟用的輸入法,但架構必須支援每個檢視畫面專屬的輸入情境。未來我們可能會決定如何儲存這些設定。

除了將事件轉送至正確的檢視畫面之外,輸入管道 (以及 IME Manager 等相關系統元件) 在解讀輸入事件時也會使用該檢視畫面的輸入背景資訊。例如,輸入管道會為實體鍵盤事件加上註解,並提供事件發生時的輸入情境中正在使用的鍵盤配置資訊。與焦點變更一樣,對使用中的鍵盤配置所做的變更應視為輸入事件,並會與其他事件依序處理,以免出現狀態改變的競爭狀況。

無障礙功能

為了讓使用者無論操作能力如何,都能輕鬆使用 Fuchsia 裝置,Fuchsia 無障礙架構提供了多項無障礙功能,能夠變更使用者與裝置互動的方式。具體而言,這麼做可帶來以下好處:

  • 用於「放大」部分或全部 UI 的放大鏡。
  • 一種螢幕閱讀器,可讓失明或低視能使用者透過與目前 UI 對應的「語意樹狀結構」進行探索和互動,而不必輸入影像內容。

啟用上述一或兩項功能時,無障礙管理員必須透過輸入管道攔截輸入事件,並將這些事件解讀為對目前使用中無障礙功能的指令。這些指令可能會根據裝置類型使用多個輸入模式。舉例來說,工作站螢幕閱讀器主要使用鍵盤快速鍵運作,而觸控螢幕裝置的螢幕閱讀器可能會使用一系列的輕觸和滑動操作。視啟用的無障礙功能而定,無障礙管理員可能會決定只消耗部分事件 (例如放大鏡使用部分手勢,但允許其他手勢傳遞至 UI) 或所有事件 (就像螢幕閱讀器會將事件轉譯為語意動作一樣)。

無障礙管理工具會維持每個檢視畫面的連線,以便透過語意 API (fuchsia.accessibility.semantics) 查看、說明該檢視畫面中的 UI 元素,並與其互動。舉例來說,已啟用螢幕閱讀器的「輕觸兩下」功能通常會傳送至檢視區塊,做為目前所選語意節點上的「預設動作」語意。

安全性考量

輸入管道及相關聯的系統元件會使用幾個未發布到 SDK 中的特殊權限 API。藉由要求工作階段使用輸入管道來處理輸入作業,平台就能限制外部軟體可用的功能。

此外,也必須考慮 UI 阻礙攻擊,例如點閱綁架。不實的輸入事件可用於在未經使用者同意的情況下授予權限 (例如將點擊轉送至惡意網站上的按鈕)。雖然在平台層級很難完全預防,但輸入架構必須確保圖像事件只會傳送至正確的 UI 元件,而且產品擁有者要能輕鬆透過系統瞭解輸入事件的流程。

隱私權注意事項

對輸入管道所做的變更應接受隱私權審查,因為使用者輸入內容的存取權可能會允許攻擊者建立鍵盤記錄器或其他惡意軟體。除了復原模式以外,輸入管道應為直接從驅動程式庫允許的使用者輸入事件的唯一元件,以防止這種情況。

測試

測試輸入管道

平台輸入行為應使用與您使用這些功能的產品代碼相對應支援的輸入功能 (例如觸控輸入、鍵盤快速鍵) 對應的密封整合測試。測試應針對每個支援的執行階段,使用最少的圖形元件來驗證相關功能。確保功能穩定度與特定產品無關,可讓開發人員建構出獨立於特定產品的產品。

密封測試存在許多超出這個 RFC 範圍的挑戰。

測試所有其他項目

端對端測試極度仰賴合成輸入事件,以可重現的測試方式偽造使用者互動。雖然大部分的 UI 架構都含有插入事件的方式 (例如 Flutter 驅動程式),但這並不足以測試涉及多個執行階段的任何情況。這意味著,Fuchsia 提供適當的 API 來建立假輸入內容。這是透過 SL4F 和 Fuchsia 輸入合成程式庫來完成,該程式庫會透過專屬的插入 API,將事件插入輸入管道。這個 API 應只在開發人員版本中提供,且不得在正式版中使用,因為該 API 允許插入任意輸入。

輸入產業

比起本文所述的高層架構,支援各種不同的輸入裝置會帶來大量的複雜度。這些詳細資料將在後續的 RFC 中獲得解決。主要輸入產業包括:

  • 實體鍵盤 (藍牙和 USB)
  • 虛擬或螢幕小鍵盤
  • 滑鼠
  • 觸控
  • 觸控板

說明文件

請將這個 RFC 的內容和實作詳情新增至 Fuchsia 公開說明文件。

考慮改用的替代方案

本節包含我們所討論的 (廣) 替代方法的子集。

將根簡報者進化為管道

過去,View 負責分派所有使用者輸入事件,包括沒有圖形/位置元件的鍵盤事件。雖然鍵盤事件已移除,但目前某些產品設定會使用這項資訊。根簡報者中現有的輸入處理程式碼可以擴充以處理其他用途。不過,這段程式碼缺乏測試涵蓋範圍,且必須進行大量的重新寫入,才能提供一致性和設定功能的所需屬性,同時移除輸入處理與圖形 API 之間不必要的耦合。

產品相關風景

由於輸入內容 (尤其是指標式的輸入) 與圖形息息相關,因此其中一個選項探索會透過 Scenic,也就是 Fuchsia 圖形引擎來轉送輸入處理。這種架構是從目前狀態出發的極限值。在此版本中,合成器會從 View 中分解出來,並在「立即模式」下運作,意味著視窗管理員每次進行變更時都必須繪製。View 就會成為視窗管理員,假設這是產品專屬的元件,且各產品類別必須採用不同的實作方式。輸入內容會透過這個元件轉送。

雖然在任何單一產品中都能這樣做,但需要為個別產品輸入任何自訂項目,才能烘焙到圖形引擎。這可能表示每個新的產品類型都需要特殊的 View。這個方法可能是日後的最佳化作業,但對於目前用途而言,系統認為耗用的資源過多。