QtShell コンポジター

QtShell Compositor は シェル拡張の使い方を示します。QtShell

QtShell CompositorはデスクトップスタイルのWaylandコンポジターのサンプルで、 と呼ばれる特殊なQtShellシェル拡張プロトコルを使用する完全なQt Waylandコンポジターを実装しています。

コンポジターはQt QuickとQMLで実装されています。

接続の作成

この例では、WaylandCompositor オブジェクトへの唯一の拡張としてQtShell を挙げています。つまり、サーバーに接続するクライアントは、この拡張機能をサポートしている必要があり、コンポジターと同じバージョンのQtアプリケーションである必要があります。

QtShell {
    onQtShellSurfaceCreated: (qtShellSurface) => screen.handleShellSurface(qtShellSurface)
}

クライアントがQtShell インターフェースに接続すると、QtShellSurface を作成します。コンポジターは、qtShellSurfaceCreated シグナルの発信によって、このことを通知されます。この例では、後で簡単にアクセスできるように、シェルサーフェスをListModel に追加します。

property ListModel shellSurfaces: ListModel {}
function handleShellSurface(shellSurface) {
    shellSurfaces.append({shellSurface: shellSurface});
}

ListModel は、Repeater のモデルとして使用されます。 は、クライアントのコンテンツを画面に表示するために必要な Qt Quick アイテムを作成します。

Repeater {
    id: chromeRepeater
    model: output.shellSurfaces
    // Chrome displays a shell surface on the screen (See Chrome.qml)
    Chrome {
        shellSurface: modelData
        onClientDestroyed:
        {
            output.shellSurfaces.remove(index)
        }
    }
}

これは、ウィンドウの状態と装飾を処理するローカルのChrome

クローム

Chrome は、クライアントコンテンツを確実に表示し、ウィンドウの状態、位置、サイズなどを処理する型です。組み込みのQtShellChrome をベースとして使用し、ウィンドウの状態(最大化、最小化、フルスクリーン)とウィンドウのアクティブ化(その時点でアクティブなウィンドウが1つだけであることを保証)を自動的に処理します。

Chrome Item QtShellChrome は典型的なコンポジターの動作を提供する便利なクラスで、このロジックをサンプルに実装する手間を省くことができます。

Chrome がどのように書かれていても、クライアント・コンテンツを保持するためにShellSurfaceItem を持つ必要があります。

ShellSurfaceItem {
    id: shellSurfaceItemId
    anchors.top: titleBar.bottom
    anchors.bottom: bottomResizeHandle.top
    anchors.left: leftResizeHandle.right
    anchors.right: rightResizeHandle.left

    moveItem: chrome

    staysOnBottom: shellSurface.windowFlags & Qt.WindowStaysOnBottomHint
    staysOnTop: !staysOnBottom && shellSurface.windowFlags & Qt.WindowStaysOnTopHint
}
shellSurfaceItem: shellSurfaceItemId

ShellSurfaceItem は、Qt Quick シーンにおけるクライアントのコンテンツの視覚的な表現です。QtShellChrome は自動的にQtShellSurfacewindowGeometry のサイズになります。これは、クライアントのバッファのサイズにフレームマージンのサイズを足したサイズです。フレームマージンとは、Chrome の側面にある予約領域で、ウィンドウの装飾を含めるために使用できます。

したがって、ShellSurfaceItem は、クライアント・バッファのために予約された領域を埋めるために、ウィンドウ装飾に固定される。

ウィンドウ装飾

ウィンドウ装飾は通常、クライアントのコンテンツを囲むフレームで、情報(ウィンドウのタイトルなど)やユーザーとのインタラクション(ウィンドウのサイズ変更、閉じる、移動など)の可能性を追加します。

QtShell では、ウィンドウの装飾は常にコンポジターによって描画され、クライアントによって描画されることはありません。サイズと位置が正しく伝達されるために、QtShell は、ウィンドウのどれだけがこれらの装飾のために予約されているかを知る必要もあります。これはQtShellChrome によって自動的に処理されるか、frameMarginLeftframeMarginRightframeMarginTopframeMarginBottom を設定することによって手動で処理される。

ウィンドウの周囲にリサイズ・ハンドルがあり、上部にタイトル・バーがあるような典型的なケースでは、デフォルトのフレーム・マージンに頼る方が便利です。QtShell Compositor の例では、このようにしています。

まず、Qt Quick アイテムを作成して、ウィンドウのさまざまな部分の装飾を表現します。例えば左側には、ウィンドウのサイズを変更するためにユーザーがつかんでドラッグできるリサイズ・ハンドルが必要です。

Rectangle {
    id: leftResizeHandle
    color: "gray"
    width: visible ? 5 : 0
    anchors.topMargin: 5
    anchors.bottomMargin: 5
    anchors.left: parent.left
    anchors.top: parent.top
    anchors.bottom: parent.bottom
}

この例では、単純に幅5ピクセルの矩形を作成し、Chrome の上、下、左側に固定します。

同様に、右、上、下、左上、右上、左下、右下のリサイズ・ハンドルを表す Qt Quick アイテムを追加します。タイトルバーも追加します。装飾が作成され、Chrome の側面に正しく固定されたら、QtShellChrome に対応するプロパティを設定します。

leftResizeHandle: leftResizeHandle
rightResizeHandle: rightResizeHandle
topResizeHandle: topResizeHandle
bottomResizeHandle: bottomResizeHandle
bottomLeftResizeHandle: bottomLeftResizeHandle
bottomRightResizeHandle: bottomRightResizeHandle
topLeftResizeHandle: topLeftResizeHandle
topRightResizeHandle: topRightResizeHandle
titleBar: titleBar

装飾のプロパティが設定されると、デフォルトのリサイズと再配置の動作が自動的に追加されます。ユーザーは、リサイズ・ハンドルを操作してウィンドウのサイズを変更し、タイトル・バーをドラッグして位置を変更することができます。QtShellSurface のフレーム・マージンも、装飾のサイズを考慮して自動的に設定されます (フレーム・マージンのプロパティが明示的に設定されていない限り)。

装飾の可視性は、QtShellSurface のウィンドウ・フラグに基づいて、QtShellChrome によって自動的に処理されます。

ウィンドウの管理

装飾の一部として、ウィンドウの状態と寿命を管理するツールボタンが一般的です。この例では、これらをタイトルバーに追加しています。

RowLayout {
    id: rowLayout
    anchors.right: parent.right
    anchors.rightMargin: 5

    ToolButton {
        text: "-"
        Layout.margins: 5
        visible: (chrome.windowFlags & Qt.WindowMinimizeButtonHint) != 0
        onClicked: {
            chrome.toggleMinimized()
        }
    }

    ToolButton {
        text: "+"
        Layout.margins: 5
        visible: (chrome.windowFlags & Qt.WindowMaximizeButtonHint) != 0
        onClicked: {
            chrome.toggleMaximized()
        }
    }

    ToolButton {
        id: xButton
        text: "X"
        Layout.margins: 5
        visible: (chrome.windowFlags & Qt.WindowCloseButtonHint) != 0
        onClicked: shellSurface.sendClose()
    }
}

各ボタンの可視性は、そのボタンのウィンドウ・フラグを条件とし、各ボタンがクリックされると、QtShellChrome の対応するメソッドを呼び出すだけです。例外は「閉じる」ボタンで、これはQtShellSurfacesendClose() メソッドを呼び出します。これにより、クライアントは自分自身を閉じるように指示され、アプリケーションの優雅なシャットダウンが保証されます。

Row {
    id: taskbar
    height: 40
    anchors.left: parent.left
    anchors.right: parent.right
    anchors.bottom: parent.bottom

    Repeater {
        anchors.fill: parent
        model: output.shellSurfaces

        ToolButton {
            anchors.verticalCenter: parent.verticalCenter
            text: modelData.windowTitle
            onClicked: {
                var item = chromeRepeater.itemAt(index)
                if ((item.windowState & Qt.WindowMinimized) != 0)
                    item.toggleMinimized()
                chromeRepeater.itemAt(index).activate()
            }
        }
    }
}

追加のウィンドウ管理ツールとして、この例では「タスク・バー」を用意しています。これは、ウィンドウのタイトルが表示されたツールボタンの列です。このボタンをクリックすることで、アプリケーションの最小化を解除したり、他のウィンドウに隠れているアプリケーションを前面に出したりすることができます。Chrome と同様に、ツールボタンの作成にはRepeater を使用し、そのモデルとしてシェルサーフェスリストを使用します。簡単のため、この例ではオーバーフロー(タスクバーに対してアプリケーションが多すぎる場合)の処理を行いませんが、適切なコンポジターでは、これも考慮すべきことです。

最後に、最大化されたアプリケーションがタスクバーで覆われた領域を埋めるように拡大するのを避けるために、クライアントウィンドウが利用できるWaylandOutput 領域の一部を管理する特別なアイテムを作成します。

Item {
    id: usableArea
    anchors.top: parent.top
    anchors.left: parent.left
    anchors.right: parent.right
    anchors.bottom: taskbar.top
}

このアイテムは、WaylandOutput の両端に固定されていますが、一番下のアンカーはタスク・バーの一番上にあります。

Chrome では、この領域を使用してウィンドウのmaximizedRect を定義します。

maximizedRect: Qt.rect(usableArea.x,
                       usableArea.y,
                       usableArea.width,
                       usableArea.height)

デフォルトでは、このプロパティは完全なWaylandOutput と一致します。しかし、私たちのケースでは、タスク・バーを使用可能な領域に含めたくないので、デフォルトをオーバーライドします。

プロジェクト例 @ code.qt.io

©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 ここで提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。