ファンシー・コンポジター
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つ目がアクティベーションのトランジションです。これはXdgShell でのみサポートされています。これはactivated ステートを持つ唯一のシェル拡張だからです。
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 の全範囲を自由に使って、あらゆる種類のアニメーション効果を使うことができる。
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.