ファンシー・コンポジター
Fancy Compositorは純粋なQMLでWaylandコンポジタを書く方法を示すサンプルです。
はじめに
Fancy Compositorは小さなデスクトップスタイルのWaylandコンポジターのサンプルで、Qt Wayland CompositorQML APIのパワーと使いやすさを示すものです。
Fancy Compositorの例はMinimal QMLの例と似ていますが、QMLコードのみで実装された本格的なWaylandコンポジターです。
コンポジターの初期化
最小限のQMLの例と同様に、Fancy CompositorはQtがサポートしている主なシェル拡張をサポートしています。
// Shell surface extension. Needed to provide a window concept for Wayland clients. // I.e. requests and events for maximization, minimization, resizing, closing etc. XdgShell { onToplevelCreated: (toplevel, xdgSurface) => screen.handleShellSurface(xdgSurface) } // Minimalistic shell extension. Mainly used for embedded applications. IviApplication { onIviSurfaceCreated: (iviSurface) => screen.handleShellSurface(iviSurface) } // Deprecated shell extension, still used by some clients WlShell { onWlShellSurfaceCreated: (shellSurface) => screen.handleShellSurface(shellSurface) }
これらはWaylandCompositor の子としてインスタンス化され、サーバからクライアントにブロードキャストされるサポートインターフェースのリストに自動的に追加されます。
接続されたクライアントがサーフェスを作成し、シェルエクステンションの1つにバインドすると、対応するシグナルが発せられます。そして、カスタムWaylandOutput クラスのメソッドが呼び出され、ShellSurface がListModel に追加される。
function handleShellSurface(shellSurface) { shellSurfaces.append({shellSurface: shellSurface}); }
このモデルはRepeater のソースとして使用され、コンポジターのWaylandOutput の中にShellSurfaceItems を作成します。これにより、Qt Quick シーンにサーフェスのビューが追加されます。これはShellSurfaceItem であるため、どのシェル拡張が使用されているかによって、コンポジターのユーザーに対する特定のインタラクションオプションも持っています。
Repeater { model: output.shellSurfaces // Chrome displays a shell surface on the screen (See Chrome.qml) Chrome { shellSurface: modelData onDestroyAnimationFinished: output.shellSurfaces.remove(index) } }
キーボード
基本的なウィンドウシステム機能に加えて、Fancy Compositor はオプションでインプロセスで動作するオンスクリーンキーボードもサポートしています。これはQt Virtual Keyboardモジュールを使用しており、モジュールが利用可能であれば有効になります。
import QtQuick import QtQuick.VirtualKeyboard InputPanel { visible: active y: active ? parent.height - height : parent.height anchors.left: parent.left anchors.right: parent.right }
コードは簡単です。出力の一番下にInputPanel をインスタンス化し、現在アクティブな場合のみ表示されるようにします。
Loader { anchors.fill: parent source: "Keyboard.qml" }
そして、Loader 要素を使って、WaylandOutput にキーボードを追加します。Loader は、Qt Virtual Keyboardモジュールへの依存を避けるために使用しています。読み込みに失敗した場合、コンポジターは正常に動作し続けますが、オンスクリーンキーボードのサポートはありません。
最後に、コンポジターがテキスト入力をクライアントに伝える方法が必要です。これはtext-input
拡張機能を使って行います。Fancy Compositor の例では、text_input_unstable_v2
プロトコルと Qt のqt_text_input_method_unstable_v1
プロトコルの両方をサポートしています。
WaylandCompositor の子としてQtTextInputMethodManager をインスタンス化することでqt_text_input_method_unstable_v1
拡張をコンポジターに追加し、TextInputManager でtext_input_unstable_v2
を追加します。
新しいQtアプリケーションは、qt_text_input_method_unstable_v1
が利用可能であればそれを選びますが、他のクライアントはtext_input_unstable_v2
を使うことができます。
トランジション
基本的な機能に加え、Fancy Compositorの例では、状態間の遷移をアニメーションで表現しています。
その1つ目がアクティベーションのトランジションです。これはactivated ステートを持つ唯一のシェルエクステンションであるため、XdgShell でのみサポートされています。
Connections { target: shellSurface.toplevel !== undefined ? shellSurface.toplevel : null // some signals are not available on wl_shell, so let's ignore them ignoreUnknownSignals: true function onActivatedChanged() { // xdg_shell only if (shellSurface.toplevel.activated) { receivedFocusAnimation.start(); } } } SequentialAnimation { id: receivedFocusAnimation ParallelAnimation { NumberAnimation { target: scaleTransform; property: "yScale"; to: 1.02; duration: 100; easing.type: Easing.OutQuad } NumberAnimation { target: scaleTransform; property: "xScale"; to: 1.02; duration: 100; easing.type: Easing.OutQuad } } ParallelAnimation { NumberAnimation { target: scaleTransform; property: "yScale"; to: 1; duration: 100; easing.type: Easing.InOutQuad } NumberAnimation { target: scaleTransform; property: "xScale"; to: 1; duration: 100; easing.type: Easing.InOutQuad } } }
XdgShell プロトコルでクライアントウィンドウがアクティブになると、ウィンドウが200ミリ秒の間「飛び出す」アニメーションがトリガーされます。
Fancy Compositorは破壊アニメーションもサポートしています。これは、クライアントがウィンドウを優雅に閉じた場合でも、クラッシュした場合でも、ウィンドウが閉じて表面が破壊されるたびにトリガーされます。
onSurfaceDestroyed: { bufferLocked = true; destroyAnimation.start(); } SequentialAnimation { id: destroyAnimation ParallelAnimation { NumberAnimation { target: scaleTransform; property: "yScale"; to: 2/height; duration: 150 } NumberAnimation { target: scaleTransform; property: "xScale"; to: 0.4; duration: 150 } NumberAnimation { target: chrome; property: "opacity"; to: chrome.isChild ? 0 : 1; duration: 150 } } NumberAnimation { target: scaleTransform; property: "xScale"; to: 0; duration: 150 } ScriptAction { script: destroyAnimationFinished() } }
アニメーションの間、コンテンツが存在することを保証するために、バッファをロックすることから始めます。つまり、クライアントによってレンダリングされた最終フレームは、私たちがそれを終了するまでメモリに残ります。
再び、アイテムのスケールでアニメーションをトリガーします。このアニメーションは、CRTスクリーンの電源を切ることを模したもので、ウィンドウが閉じられ、空中に消えてしまったのではないことをユーザーに視覚的に知らせるものです。
このような状態変化には、Qt Quickをフルに使って、どのようなアニメーション効果でも自由に使うことができます。
©2024 The Qt Company Ltd. ここに含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 ここで提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。