fix: comprehensive boot warnings and exceptions — fixable silenced, unfixable diagnosed

Build system (5 gaps hardened):
- COOKBOOK_OFFLINE defaults to true (fork-mode)
- normalize_patch handles diff -ruN format
- New 'repo validate-patches' command (25/25 relibc patches)
- 14 patched Qt/Wayland/display recipes added to protected list
- relibc archive regenerated with current patch chain

Boot fixes (fixable):
- Full ISO EFI partition: 16 MiB → 1 MiB (matches mini, BIOS hardcoded 2 MiB offset)
- D-Bus system bus: absolute /usr/bin/dbus-daemon path (was skipped)
- redbear-sessiond: absolute /usr/bin/redbear-sessiond path (was skipped)
- daemon framework: silenced spurious INIT_NOTIFY warnings for oneshot_async services (P0-daemon-silence-init-notify.patch)
- udev-shim: demoted INIT_NOTIFY warning to INFO (expected for oneshot_async)
- relibc: comprehensive named semaphores (sem_open/close/unlink) replacing upstream todo!() stubs
- greeterd: Wayland socket timeout 15s → 30s (compositor DRM wait)
- greeter-ui: built and linked (header guard unification, sem_compat stubs removed)
- mc: un-ignored in both configs, fixed glib/libiconv/pcre2 transitive deps
- greeter config: removed stale keymapd dependency from display/greeter services
- prefix toolchain: relibc headers synced, _RELIBC_STDLIB_H guard unified

Unfixable (diagnosed, upstream):
- i2c-hidd: abort on no-I2C-hardware (QEMU) — process::exit → relibc abort
- kded6/greeter-ui: page fault 0x8 — Qt library null deref
- Thread panics fd != -1 — Rust std library on Redox
- DHCP timeout / eth0 MAC — QEMU user-mode networking
- hwrngd/thermald — no hardware RNG/thermal in VM
- live preload allocation — BIOS memory fragmentation, continues on demand
This commit is contained in:
2026-05-05 20:20:37 +01:00
parent a5f97b6632
commit f31522130f
81834 changed files with 11051982 additions and 108 deletions
@@ -0,0 +1,46 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.14)
project(qt-shell LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
find_package(Qt6 COMPONENTS Core)
find_package(Qt6 COMPONENTS Gui)
find_package(Qt6 COMPONENTS Qml)
qt_add_executable(qt-shell
main.cpp
)
set_target_properties(qt-shell PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
target_link_libraries(qt-shell PUBLIC
Qt::Core
Qt::Gui
Qt::Qml
)
# Resources:
set(qt-shell_resource_files
"images/background.jpg"
"qml/Chrome.qml"
"qml/HandleHandler.qml"
"qml/CompositorScreen.qml"
"qml/Keyboard.qml"
"qml/main.qml"
)
qt6_add_resources(qt-shell "qt-shell"
PREFIX
"/"
FILES
${qt-shell_resource_files}
)
Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

@@ -0,0 +1,21 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/QUrl>
#include <QtCore/QDebug>
#include <QtGui/QGuiApplication>
#include <QtQml/QQmlApplicationEngine>
int main(int argc, char *argv[])
{
// ShareOpenGLContexts is needed for using the threaded renderer
// on Nvidia EGLStreams
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts, true);
QGuiApplication app(argc, argv);
QQmlApplicationEngine appEngine(QUrl("qrc:///qml/main.qml"));
return app.exec();
}
@@ -0,0 +1,458 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtWayland.Compositor
Item {
id: chrome
property bool positionSet: false
x: shellSurface.windowGeometry.x - leftResizeHandle.width
y: shellSurface.windowGeometry.y - topResizeHandle.height - titleBar.height
width: shellSurface.windowGeometry.width + leftResizeHandle.width + rightResizeHandle.width
height: shellSurface.windowGeometry.height + topResizeHandle.height + titleBar.height + bottomResizeHandle.height
property rect oldGeometry: Qt.rect(0, 0, 100, 100)
property bool isChild: parent.shellSurface !== undefined
property alias shellSurface: shellSurfaceItem.shellSurface
property int windowState: Qt.WindowNoState
signal destroyAnimationFinished
signal activated
signal deactivated
property int windowFlags: shellSurface.windowFlags !== Qt.Window
? shellSurface.windowFlags
: defaultFlags
onDecorationsShowingChanged:{
shellSurfaceItem.updateFrameMargins()
}
Component.onCompleted: {
shellSurface.active = true
}
property int defaultFlags: (Qt.Window
| Qt.WindowMaximizeButtonHint
| Qt.WindowMinimizeButtonHint
| Qt.WindowCloseButtonHint)
property bool frameless: (chrome.windowFlags & Qt.FramelessWindowHint) != 0
|| (chrome.windowState & Qt.WindowFullScreen) != 0
|| ((chrome.windowFlags & Qt.Popup) == Qt.Popup
&& (chrome.windowFlags & Qt.Tool) != Qt.Tool)
property bool decorationsShowing: (chrome.windowFlags & Qt.Window) != 0 && !frameless
transform: [
Scale {
id: scaleTransform
origin.x: chrome.width / 2
origin.y: chrome.height / 2
}
]
Rectangle {
id: leftResizeHandle
color: "gray"
width: visible ? 5 : 0
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
visible: decorationsShowing
HandleHandler {
enabled: (chrome.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0
flags: westBound
}
}
Rectangle {
id: rightResizeHandle
color: "gray"
width: visible ? 5 : 0
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
visible: decorationsShowing
HandleHandler {
enabled: (chrome.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0
flags: eastBound
}
}
Rectangle {
id: topResizeHandle
color: "gray"
height: visible ? 5 : 0
anchors.left: parent.left
anchors.top: parent.top
anchors.right: parent.right
visible: decorationsShowing
HandleHandler {
enabled: (chrome.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0
flags: northBound
}
}
Rectangle {
id: bottomResizeHandle
color: "gray"
height: visible ? 5 : 0
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.right: parent.right
visible: decorationsShowing
HandleHandler {
enabled: (chrome.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0
flags: southBound
}
}
Rectangle {
id: topLeftResizeHandle
color: "gray"
height: 5
width: 5
anchors.left: parent.left
anchors.top: parent.top
visible: decorationsShowing
HandleHandler {
enabled: (chrome.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0
flags: westBound | northBound
}
}
Rectangle {
id: topRightResizeHandle
color: "gray"
height: 5
width: 5
anchors.right: parent.right
anchors.top: parent.top
visible: decorationsShowing
HandleHandler {
enabled: (chrome.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0
flags: eastBound | northBound
}
}
Rectangle {
id: bottomLeftResizeHandle
color: "gray"
height: 5
width: 5
anchors.left: parent.left
anchors.bottom: parent.bottom
visible: decorationsShowing
HandleHandler {
enabled: (chrome.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0
flags: westBound | southBound
}
}
Rectangle {
id: bottomRightResizeHandle
color: "gray"
height: 5
width: 5
anchors.right: parent.right
anchors.bottom: parent.bottom
visible: decorationsShowing
HandleHandler {
enabled: (chrome.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0
flags: eastBound | southBound
}
}
function constrainPoint(mousePos) {
var x0 = usableArea.x
var y0 = usableArea.y
var x1 = x0 + usableArea.width
var y1 = y0 + usableArea.height
return Qt.point(Math.min(Math.max(x0,mousePos.x), x1),
Math.min(Math.max(y0,mousePos.y), y1))
}
function maxContentRect() {
var x0 = usableArea.x + leftResizeHandle.width
var x1 = usableArea.x + usableArea.width - rightResizeHandle.width
var y0 = usableArea.y + topResizeHandle.height + titleBar.height
var y1 = usableArea.y + usableArea.height - bottomResizeHandle.height
return Qt.rect(x0, y0, x1 - x0, y1 - y0)
}
function randomPos(windowSize, screenSize) {
var res = (windowSize >= screenSize) ? 0 : Math.floor(Math.random() * (screenSize - windowSize))
return res
}
function activate()
{
shellSurface.active = true
shellSurfaceItem.raise()
activated()
}
function deactivate()
{
shellSurface.active = true
deactivated()
}
function setWindowState(nextState) {
var currentState = chrome.windowState
if (currentState === nextState)
return
console.log("setWindowState", nextState.toString(16))
if ((currentState & (Qt.WindowMinimized | Qt.WindowMaximized | Qt.WindowFullScreen)) == 0)
chrome.oldGeometry = chrome.shellSurface.windowGeometry
chrome.windowState = nextState
if ((nextState & Qt.WindowMinimized) != 0) {
console.log("MINIMIZE")
chrome.shellSurface.requestWindowGeometry(nextState, Qt.rect(0, 0, 1, 1))
shellSurfaceItem.visible = false
} else if ((nextState & Qt.WindowFullScreen) != 0) {
console.log("FULLSCREENIZE")
chrome.shellSurface.requestWindowGeometry(nextState, Qt.rect(0, 0, output.window.width, output.window.height))
shellSurfaceItem.visible = true
} else if ((nextState & Qt.WindowMaximized) != 0) {
console.log("MAXIMIZE")
chrome.shellSurface.requestWindowGeometry(nextState, maxContentRect())
shellSurfaceItem.visible = true
} else {
console.log("NORMALIZE", chrome.oldGeometry)
chrome.shellSurface.requestWindowGeometry(nextState, chrome.oldGeometry)
shellSurfaceItem.visible = true
}
}
Rectangle {
id: titleBar
anchors.top: topResizeHandle.bottom
anchors.left: leftResizeHandle.right
anchors.right: rightResizeHandle.left
height: visible ? xButton.height + 10 : 0
color: shellSurface.active ? "cornflowerblue" : "lightgray"
visible: !frameless
Text {
anchors.left: parent.left
anchors.right: rowLayout.left
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: xButton.height
text: shellSurface.windowTitle
fontSizeMode: Text.Fit
}
RowLayout {
id: rowLayout
anchors.right: parent.right
anchors.rightMargin: 5
ToolButton {
text: "-"
Layout.margins: 5
visible: (chrome.windowFlags & Qt.WindowMinimizeButtonHint) != 0
onClicked: {
var newState
if ((shellSurface.windowState & Qt.WindowMinimized) != 0)
newState = chrome.windowState & ~Qt.WindowMinimized
else
newState = chrome.windowState | Qt.WindowMinimized
if ((newState & Qt.WindowMaximized) != 0)
newState &= ~Qt.WindowMaximized
setWindowState(newState)
}
}
ToolButton {
text: "+"
Layout.margins: 5
visible: (chrome.windowFlags & Qt.WindowMaximizeButtonHint) != 0
onClicked: {
var newState
if ((shellSurface.windowState & Qt.WindowMaximized) != 0)
newState = shellSurface.windowState & ~Qt.WindowMaximized
else
newState = shellSurface.windowState | Qt.WindowMaximized
if ((newState & Qt.WindowMinimized) != 0)
newState &= ~Qt.WindowMinimized
setWindowState(newState)
}
}
ToolButton {
id: xButton
text: "X"
Layout.margins: 5
visible: (chrome.windowFlags & Qt.WindowCloseButtonHint) != 0
onClicked: shellSurface.sendClose()
}
}
DragHandler {
target: null
property real xOffset: -1.0
property real yOffset: -1.0
property bool started: false
enabled: (shellSurface.windowState & (Qt.WindowMinimized|Qt.WindowMaximized)) == 0
onGrabChanged: {
started = false
activate()
}
onCentroidChanged: {
if (!active)
return
if (!started) {
xOffset = shellSurface.windowPosition.x - centroid.scenePressPosition.x
yOffset = shellSurface.windowPosition.y - centroid.scenePressPosition.y
started = true
chrome.positionAutomatic = false
}
var pos = chrome.constrainPoint(centroid.scenePosition)
shellSurface.windowPosition = Qt.point(pos.x + xOffset, pos.y + yOffset)
}
}
}
ShellSurfaceItem {
id: shellSurfaceItem
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
function updateFrameMargins()
{
shellSurface.frameMarginLeft = (decorationsShowing ? leftResizeHandle.width : 0)
shellSurface.frameMarginRight = (decorationsShowing ? rightResizeHandle.width : 0)
shellSurface.frameMarginTop = (decorationsShowing ? topResizeHandle.height : 0)
+ (!frameless ? titleBar.height : 0)
shellSurface.frameMarginBottom = (decorationsShowing ? bottomResizeHandle.height : 0)
}
Component.onCompleted: {
updateFrameMargins()
}
onSurfaceDestroyed: {
bufferLocked = true;
destroyAnimation.start();
}
Connections {
target: shellSurface
function onWindowFlagsChanged() {
console.log("FLAGS", shellSurface.windowFlags.toString(16))
shellSurfaceItem.updateFrameMargins()
}
function onWindowStateChanged() {
setWindowState(shellSurface.windowState)
}
function onActiveChanged() {
if (shellSurface.active) {
shellSurfaceItem.raise()
activated()
} else {
deactivated()
}
}
function onStartResize() {
console.log("START SYSTEM RESIZE")
}
function onStartMove() {
console.log("START SYSTEM MOVE")
}
function onRaiseRequested() {
console.log("RAISE")
shellSurfaceItem.raise()
}
function onLowerRequested() {
console.log("LOWER")
shellSurfaceItem.lower()
}
function onWindowGeometryChanged() {
console.log("GEOM CHANGE", shellSurface.windowGeometry)
}
}
Connections {
target: shellSurface.surface
function onHasContentChanged() {
if (!chrome.positionSet) {
var rect = shellSurface.windowGeometry
var w = rect.width
var h = rect.height
var space = maxContentRect()
var randomize = shellSurface.positionAutomatic
var xpos = randomize ? randomPos(w, space.width) + space.x : Math.max(rect.x, space.x)
var ypos = randomize ? randomPos(h, space.height) + space.y : Math.max(rect.y, space.y)
shellSurface.windowPosition = Qt.point(xpos, ypos)
}
chrome.positionSet = true
}
}
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: chrome.destroyAnimationFinished() }
}
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 }
}
}
}
}
@@ -0,0 +1,144 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.Window
import QtQuick.Controls
import QtWayland.Compositor
WaylandOutput {
id: output
property ListModel shellSurfaces: ListModel {}
property bool isNestedCompositor: Qt.platform.pluginName.startsWith("wayland") || Qt.platform.pluginName === "xcb"
property int currentActiveWindow: -1
function handleShellSurface(shellSurface) {
shellSurfaces.append({shellSurface: shellSurface});
}
// During development, it can be useful to start the compositor inside X11 or
// another Wayland compositor. In such cases, set sizeFollowsWindow to true to
// enable resizing of the compositor window to be forwarded to the Wayland clients
// as the output (screen) changing resolution. Consider setting it to false if you
// are running the compositor using eglfs, linuxfb or similar QPA backends.
sizeFollowsWindow: output.isNestedCompositor
window: Window {
width: 1920
height: 1080
visible: true
WaylandMouseTracker {
id: mouseTracker
anchors.fill: parent
// Set this to false to disable the outer mouse cursor when running nested
// compositors. Otherwise you would see two mouse cursors, one for each compositor.
windowSystemCursorEnabled: output.isNestedCompositor
Image {
id: background
anchors.fill: parent
fillMode: Image.Tile
source: "qrc:/images/background.jpg"
smooth: true
Repeater {
id: chromeRepeater
model: output.shellSurfaces
// Chrome displays a shell surface on the screen (See Chrome.qml)
Chrome {
shellSurface: modelData
onDestroyAnimationFinished:
{
if (currentActiveWindow > index) {
--currentActiveWindow
} else if (currentActiveWindow === index) {
currentActiveWindow = index - 1
if (currentActiveWindow >= 0) {
var nextActiveSurface = output.shellSurfaces.get(currentActiveWindow).shellSurface
if (nextActiveSurface !== undefined) // More than one surface can get destroyed at the same time
nextActiveSurface.active = true
}
}
output.shellSurfaces.remove(index)
}
onDeactivated: {
if (index === currentActiveWindow)
currentActiveWindow = -1
}
onActivated: {
if (index !== currentActiveWindow && currentActiveWindow >= 0) {
// This may already have been destroyed
if (output.shellSurfaces.get(currentActiveWindow).shellSurface !== undefined)
output.shellSurfaces.get(currentActiveWindow).shellSurface.active = false
}
currentActiveWindow = index
}
}
}
}
Rectangle {
anchors.fill: taskbar
color: "lavenderblush"
}
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: {
modelData.requestWindowGeometry(modelData.windowState & ~Qt.WindowMinimized,
modelData.windowGeometry)
chromeRepeater.itemAt(index).activate()
}
}
}
}
Item {
id: usableArea
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: taskbar.top
}
// Virtual Keyboard
Loader {
anchors.fill: parent
source: "Keyboard.qml"
}
// Draws the mouse cursor for a given Wayland seat
WaylandCursorItem {
inputEventsEnabled: false
x: mouseTracker.mouseX
y: mouseTracker.mouseY
seat: output.compositor.defaultSeat
}
}
Shortcut {
sequence: "Ctrl+Alt+Backspace"
onActivated: Qt.quit()
}
}
}
@@ -0,0 +1,86 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
DragHandler {
target: null
function selectCursor(f)
{
switch (f) {
case (southBound | eastBound):
case (northBound | westBound):
return Qt.SizeFDiagCursor
case (southBound | westBound):
case (northBound | eastBound):
return Qt.SizeBDiagCursor
case westBound:
case eastBound:
return Qt.SizeHorCursor
default:
return Qt.SizeVerCursor
}
}
property int flags: WestBound
readonly property int westBound: 1
readonly property int eastBound: 2
readonly property int northBound: 4
readonly property int southBound: 8
cursorShape: selectCursor(flags)
property rect geom
property real startX: -1.0
property real startY: -1.0
property bool started: false
onGrabChanged: {
started = false
}
onCentroidChanged: {
if (!active)
return
if (!started) {
geom = shellSurface.windowGeometry
startX = centroid.scenePressPosition.x
startY = centroid.scenePressPosition.y
started = true
}
var pos = chrome.constrainPoint(centroid.scenePosition)
var dx = pos.x - startX
var dy = pos.y - startY
var minWidth = Math.max(0, shellSurface.minimumSize.width)
var minHeight = Math.max(0, shellSurface.minimumSize.height)
var maxWidth = shellSurface.maximumSize.width > 0 ? shellSurface.maximumSize.width : Number.MAX_VALUE
var maxHeight = shellSurface.maximumSize.height > 0 ? shellSurface.maximumSize.height : Number.MAX_VALUE
var newLeft = geom.left
if (flags & westBound)
newLeft = Math.max(geom.right - maxWidth, Math.min(geom.right - minWidth, newLeft + dx));
var newTop = geom.top
if (flags & northBound)
newTop = Math.max(geom.bottom - maxHeight, Math.min(geom.bottom - minHeight, newTop + dy));
var newRight = geom.right
if (flags & eastBound)
newRight = Math.max(geom.left, newRight + dx);
var newBottom = geom.bottom
if (flags & southBound)
newBottom = Math.max(geom.top, newBottom + dy);
console.log("RESIZE HANDLER", shellSurface.windowGeometry, geom, dy, newTop)
shellSurface.requestWindowGeometry(shellSurface.windowState,
Qt.rect(newLeft,
newTop,
newRight - newLeft,
newBottom - newTop))
}
}
@@ -0,0 +1,12 @@
// Copyright (C) 2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtQuick.VirtualKeyboard
InputPanel {
visible: active
y: active ? parent.height - height : parent.height
anchors.left: parent.left
anchors.right: parent.right
}
@@ -0,0 +1,22 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick
import QtWayland.Compositor
import QtWayland.Compositor.QtShell
WaylandCompositor {
id: waylandCompositor
CompositorScreen { id: screen; compositor: waylandCompositor }
// Shell surface extension. Needed to provide a window concept for Wayland clients.
// I.e. requests and events for maximization, minimization, resizing, closing etc.
QtShell {
onQtShellSurfaceCreated: screen.handleShellSurface(qtShellSurface)
}
// Extension for Input Method (QT_IM_MODULE) support at compositor-side
QtTextInputMethodManager {}
}
@@ -0,0 +1,13 @@
QT += gui qml
SOURCES += \
main.cpp
OTHER_FILES = \
qml/main.qml \
qml/CompositorScreen.qml \
qml/Chrome.qml \
qml/Keyboard.qml \
images/background.jpg \
RESOURCES += qt-shell.qrc
@@ -0,0 +1,10 @@
<RCC>
<qresource prefix="/">
<file>images/background.jpg</file>
<file>qml/main.qml</file>
<file>qml/CompositorScreen.qml</file>
<file>qml/Chrome.qml</file>
<file>qml/Keyboard.qml</file>
<file>qml/HandleHandler.qml</file>
</qresource>
</RCC>