팬시 컴포지터
팬시 컴포저는 순수 QML로 팬시 웨이랜드 컴포저를 작성하는 방법을 보여주는 예제입니다.
소개
팬시 컴포저는 작은 데스크톱 스타일의 Wayland 컴포저 예제로서 Qt Wayland Compositor 예제입니다.
팬시 컴포저 예제는 QML 코드만을 사용하여 구현된 완전한 웨이랜드 컴포저라는 점에서 미니멀 QML 예제와 유사합니다.
컴포저 초기화하기
Minimal 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 의 자식으로 인스턴스화되어 서버에서 클라이언트로 브로드캐스트되는 지원 인터페이스 목록에 자동으로 추가됩니다.
연결된 클라이언트가 서페이스를 생성하고 이를 셸 확장 중 하나에 바인딩하면 해당 신호가 방출됩니다. 그러면 사용자 지정 WaylandOutput 클래스 내부의 메서드가 호출되어 ShellSurface 을 ListModel 에 추가합니다.
function handleShellSurface(shellSurface) { shellSurfaces.append({shellSurface: shellSurface}); }
이 모델은 컴포저의 WaylandOutput 안에 ShellSurfaceItems 을 생성하는 Repeater 의 소스로 사용됩니다. 그러면 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) } }
키보드
팬시 컴포지터는 기본 윈도우 시스템 기능 외에도 프로세스 중에 실행되는 온스크린 키보드(옵션)도 지원합니다. 이는 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
확장자를 통해 이루어집니다. 팬시 컴포저 예제는 text_input_unstable_v2
프로토콜과 Qt의 qt_text_input_method_unstable_v1
프로토콜을 모두 지원합니다.
qt_text_input_method_unstable_v1
확장은 QtTextInputMethodManager 을 WaylandCompositor 의 자식으로 인스턴스화하여 컴포저에 추가하고, TextInputManager 은 text_input_unstable_v2
을 추가합니다.
최신 Qt 응용 프로그램은 사용 가능한 경우 qt_text_input_method_unstable_v1
를 선택하지만, 다른 클라이언트는 text_input_unstable_v2
을 사용할 수 있습니다.
트랜지션
기본 기능 외에도 Fancy Compositor 예제에서는 상태 사이의 애니메이션 전환도 보여줍니다.
첫 번째는 활성화 전환입니다. 이는 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밀리초 동안 "튀어나오는" 애니메이션을 트리거합니다.
팬시 컴포저는 소멸 애니메이션도 지원합니다. 이 애니메이션은 클라이언트가 창을 우아하게 닫았든, 충돌이 발생했든 상관없이 창이 닫히고 표면이 파괴될 때마다 트리거됩니다.
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.