觸控事件的生命週期

本文說明如何透過觸控螢幕裝置 (觸控螢幕或觸控板) 處理事件。

總覽

整體來說,事件路徑會分成多個以不同抽象層級和狀態運作的元件。

  • 驅動程式會瞭解來自觸控裝置的原始觸控事件,但並不知道檢視畫面樹狀結構。
  • 輸入管道知道檢視系統和裝置的相關資訊,但不知道檢視區塊樹狀結構中的特定檢視用戶端。
  • View 擁有 UI 用戶端 (亦即 Flatland 用戶端) 和檢視區塊樹狀結構資料結構,其中包含命中區域等重要詳細資料。因此,View 會執行命中測試來判斷觸控事件的實際目的地。
  • 用戶端知道接收到的事件,而不是傳送至其他用戶端的事件。

此除法允許針對觸控事件分派宣告的特定全域屬性。

  • 驅動程式的工作非常簡單,且不含任何 UI 用戶端互動。
  • 透過 fuchsia.ui.pointerinjector 通訊協定的輸入管道必須知道檢視區塊樹狀結構。如此一來,即可對一組特定用戶端強制執行觸控事件。甚至保證特定 UI 用戶端的機密性、完整性和可用性 (透過專屬模式插入功能)。
  • 因此風景優美,使用者無法得知實體裝置與他們的特殊狀況。而是透過輸入管道建立的插入器通訊協定,在抽象裝置上運作。

這些部門是堆積層,可讓平台或產品導入不同的行為,而無須修改整個堆疊。舉例來說,簡單的觸控板可以設定用來模擬實體滑鼠裝置。假觸控螢幕可在測試環境中設定。如果 UI 用戶端尚未提供新的形式抽象化 (例如觸控筆),新的輸入形態可暫時設為舊版裝置。

UI 用戶端通訊協定

UI 用戶端的核心通訊協定是 fuchsia.ui.pointer.TouchSource 通訊協定,這是一般 Fuchsia 應用程式看到的通訊協定。此 API 會透過縮放不變的 injector viewport 抽象層,將觸控事件傳送至 UI 用戶端,而 Flatland 可強化轉換矩陣,將這些 injector viewport 座標轉換成特定檢視畫面的座標。這樣一來,UI 用戶端便可在放大時辨識實際縮放手勢,但也允許手勢直接操控其中一個位於檢視畫面座標系統中的 UI 元素。

為求效率,事件可以批次處理為向量。我們無法保證事件是否會批次處理。

事件的時間戳記會在驅動程式庫中產生,並保存到這個時間點。因此,在傳送至 UI 用戶端之前,FIDL 事件延遲不會對手勢速度計算造成不良影響。

駕駛座

hid-input-report 會剖析 USB Touch HID 輸入報表,並將這些報表轉譯成 FIDL sdk/fidl/fuchsia.input.report/touch

剖析 HID 報表並非易事,因此 UI 團隊決定避免匯出驅動程式庫程式以外的 HID。相反地,UI 團隊針對常見的事件 (例如觸控、滑鼠和鍵盤) 定義了乾淨的 FIDL。這樣可讓輸入管道和其他元件輕鬆與驅動程式庫互動。

系統會如何處理罕見的 HID 裝置?

Fuchsia 可能會直接將 HID 連線提供給真正知道該 USB HID 裝置的用戶端,並交由該用戶端直接處理。不過,駕駛人可以選擇以易於使用的 FIDL 定義事件,而不是 HID。

輸入管道

Input Pipeline 可以處理 2 種觸控裝置,並將其轉譯為不同的事件至 scenic

觸控螢幕

輸入管道會從裝置座標 (從裝置描述元) 取得聯絡位置,輸入管道會在顯示座標中將其正規化為實體像素。輸入管道也會留意 scene_manager 提供的可視區域更新,以便將 UI 用戶端的 injector viewport 附加至事件。

在輸入管道中,injector viewport 通常是在實體像素和顯示座標中。以便更輕鬆地與後續事件處理作業進行通訊。

觸控板

當裝置回報 HID 集合 (包括廣泛使用的 Windows Precision 觸控板集合),輸入管道會將裝置視為觸控板。

觸控板事件會轉換為滑鼠事件,例如雙指垂直或水平移動會解讀為滑鼠捲動事件。本文件不會說明觸控板的其餘部分。請參閱滑鼠文件

插入器可視區域

injector viewport 抽象化是將縮放比例不變手勢資料轉發給 UI 用戶端的重要部分,以便在放大等效果下正確解讀指標移動。該結構定義可視區域座標系統中的最大和最大範圍。

可視區域的界線 (矩形) 是與可視區域座標系統對齊的軸,但也可能是任意位置 (「浮點」) 出現,因為會有平移和縮放,但不會旋轉。浮動功能可讓插入器選擇傳遞座標的方式,例如在 Vulkan NDC 或螢幕像素座標中。可視區域矩形定義了分派的閂鎖區域。

UI 用戶端會在可視區域座標系統中接收指標的座標,以及將可視區域座標系統中的座標轉換為 UI 用戶端座標系統的矩陣。

造訪區域

Flatland 通訊協定定義了隱藏的「命中地區」,說明使用者在 UI 用戶端的檢視空間中可以互動的位置。一般來說,整個檢視畫面都是互動式,因此 Flatland 會提供完全涵蓋檢視畫面的預設命中區域。

某些進階情境需要針對命中區域設定更多資料。舉例來說,如果父項檢視畫面嵌入了子檢視畫面,而父項檢視畫面也想要「彈出」部分遮蔽子檢視畫面,則父項 UI 用戶端必須將該疊加層的大小描述為命中區域,為 Flatland。

關閉檢視畫面中的所有命中區域,表示使用者能看到 UI 用戶端的圖形內容,但不會將使用者的觸控動作分派至這個 UI 用戶端。此外,無障礙功能也無法將 UI 用戶端的語意內容與使用者手勢建立關聯。

手勢消歧

UI 用戶端通常會參與手勢消歧通訊協定,進而決定每個手勢的手勢擁有者。Flatland 會通知 UI 用戶端是否已授予或拒絕該手勢。GD 通訊協定是合作式,因此必須將遭拒的手勢視為取消。如果 UI 用戶端無法保證手勢可以視為已取消,解決方法就是直接緩衝觸控事件直到獲得擁有權,然後捨棄事件。某些用戶端 (例如 Chrome) 會使用這個擬真模型,因此除非獲得 Flatland 明確手勢擁有權的保證,否則 Fuchsia 的觸控事件實際上不會轉換成 JavaScript 事件。

Accessibility 的 LocalHit 通訊協定升級

Accessibility 的 UI 用戶端需要一般 UI 用戶端不應接收的額外資料。這些額外資料會在平台私人通訊協定 (fuchsia.ui.pointer.augment.LocalHit) 中提供,該通訊協定會將用戶端的 TouchSource 端點「升級」為具有更多資料欄位的組合器版本。

這些資料欄位可說明每個指標事件的命中測試結果,進而針對各個觸控事件放置於哪個檢視畫面和查看內部位置提供非常精細的資料。

無障礙中心會使用這項命中資料執行「探索模式」。