이 페이지에서

QtShell Compositor

QtShell Compositor는 QtShell 셸 확장 기능을 사용하는 방법을 보여줍니다.

QtShell Compositor는 ‘ QtShell ’라는 특수한 셸 확장 프로토콜을 사용하는 완전한 Qt Wayland Compositor 를 구현한 데스크톱 스타일의 Wayland 컴포지터 예제입니다.

두 개의 클라이언트 창이 있는 QtShell 컴포지터

이 컴포지터는 Qt Quick 와 QML을 사용하여 구현되었습니다.

연결 설정

이 예제에서는 QtShell 를 WaylandCompositor 객체의 유일한 확장으로 나열합니다. 이는 서버에 연결하는 모든 클라이언트도 이 확장을 지원해야 함을 의미하며, 따라서 클라이언트는 컴포지터와 동일한 버전의 Qt에서 실행되는 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
        onShellSurfaceChanged: {
            if (!shellSurface)
                output.shellSurfaces.remove(index)
        }
    }
}

이 클래스는 창 상태와 장식을 처리하는 로컬 Chrome 유형을 사용합니다.

Chrome

Chrome 는 클라이언트 콘텐츠가 표시되도록 보장하고 창 상태, 위치, 크기 등을 처리하는 타입입니다. 이 타입은 내장된 QtShellChrome 를 기반으로 하며, 창 상태(최대화, 최소화, 전체 화면)와 창 활성화(한 번에 하나의 창만 활성화되도록 보장)를 자동으로 처리합니다.

이 클래스의 동작은 어느 정도 사용자 정의가 가능하지만, 기본 Item 타입을 기반으로 하여 Chrome 기능을 처음부터 직접 구현할 수도 있습니다. 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 는 QtShellSurface 의 windowGeometry 에 맞춰 자동으로 크기가 조정되는데, 이는 클라이언트 버퍼의 크기에 프레임 여백의 크기를 더한 값입니다. 프레임 여백은 Chrome 의 측면에 할당된 영역으로, 창 장식을 포함하는 데 사용될 수 있습니다.

따라서 ShellSurfaceItem 는 클라이언트 버퍼를 위해 예약된 영역을 채우기 위해 창 장식(window decorations)에 고정됩니다.

창 장식

창 장식(window decoration)은 일반적으로 클라이언트 콘텐츠 주위를 둘러싼 프레임으로, 정보(예: 창 제목)를 추가하고 사용자 상호작용(예: 크기 조정, 닫기, 창 이동 등)을 가능하게 합니다.

QtShell 을 사용하면 창 장식은 항상 클라이언트가 아닌 컴포지터에 의해 그려집니다. 크기와 위치를 올바르게 전달받기 위해서는 QtShell 가 이러한 장식을 위해 예약된 창의 영역이 얼마나 되는지 알아야 합니다. 이는 QtShellChrome 를 통해 자동으로 처리되거나, frameMarginLeft, frameMarginRight, frameMarginTop 및 frameMarginBottom 을 설정하여 수동으로 처리할 수 있습니다.

창 주변에 크기 조정 핸들이 있고 상단에 제목 표시줄이 있는 일반적인 경우에는 기본 프레임 여백을 사용하는 것이 더 편리합니다. 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 의 해당 메서드를 호출합니다. 단, “닫기” 버튼은 예외로, QtShellSurface 의 sendClose() 메서드를 호출합니다. 이는 클라이언트에게 자체 종료를 지시하여 애플리케이션이 정상적으로 종료되도록 보장합니다.

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

© 2026 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.