diff --git a/bin/breezy_gnome_setup b/bin/breezy_gnome_setup index f93c496..274bad5 100755 --- a/bin/breezy_gnome_setup +++ b/bin/breezy_gnome_setup @@ -59,7 +59,7 @@ if [ -z "$binary_path_arg" ] then # download and unzip the binary echo "Downloading to: ${tmp_dir}/$FILE_NAME" - curl -L -O $binary_download_url + curl -L "$binary_download_url" > "$FILE_NAME" else FILE_NAME=$(basename $binary_path_arg) if [[ "$binary_path_arg" = /* ]]; then diff --git a/bin/breezy_vulkan_setup b/bin/breezy_vulkan_setup index 464e785..bac0377 100755 --- a/bin/breezy_vulkan_setup +++ b/bin/breezy_vulkan_setup @@ -39,10 +39,11 @@ fi if [ -z "$binary_path_arg" ] then - # download and unzip the latest driver - echo "Downloading to: ${tmp_dir}/breezyVulkan-$ARCH.tar.gz" - curl -L -O $binary_download_url + # download and unzip the binary binary_path_arg="breezyVulkan-$ARCH.tar.gz" + echo "Downloading to: ${tmp_dir}/$binary_path_arg" + + curl -L "$binary_download_url" > "$binary_path_arg" else if [[ "$binary_path_arg" = /* ]]; then abs_path="$binary_path_arg" diff --git a/kwin/src/CMakeLists.txt b/kwin/src/CMakeLists.txt index 0fed214..896a2dc 100644 --- a/kwin/src/CMakeLists.txt +++ b/kwin/src/CMakeLists.txt @@ -4,14 +4,15 @@ add_subdirectory(kcm) -kcoreaddons_add_plugin(kwin4_effect_cube INSTALL_NAMESPACE "kwin/effects/plugins/") -target_sources(kwin4_effect_cube PRIVATE +kcoreaddons_add_plugin(breezy_desktop_effect INSTALL_NAMESPACE "kwin/effects/plugins/") +target_sources(breezy_desktop_effect PRIVATE cubeeffect.cpp main.cpp ) -kconfig_add_kcfg_files(kwin4_effect_cube cubeconfig.kcfgc) +kconfig_add_kcfg_files(breezy_desktop_effect cubeconfig.kcfgc) -target_link_libraries(kwin4_effect_cube +target_include_directories(breezy_desktop_effect PRIVATE /usr/include/kwin) +target_link_libraries(breezy_desktop_effect Qt6::Core Qt6::Gui Qt6::Quick @@ -23,7 +24,7 @@ target_link_libraries(kwin4_effect_cube KF6::I18n KF6::WindowSystem - kwineffects + KWin::kwin ) install(DIRECTORY qml DESTINATION ${KDE_INSTALL_DATADIR}/kwin/effects/cube) diff --git a/kwin/src/cubeeffect.cpp b/kwin/src/cubeeffect.cpp index dbce20b..e7a94e1 100644 --- a/kwin/src/cubeeffect.cpp +++ b/kwin/src/cubeeffect.cpp @@ -6,21 +6,27 @@ #include "cubeeffect.h" #include "cubeconfig.h" +#include "effect/effect.h" +#include "effect/effecthandler.h" #include #include +#include #include #include #include #include +Q_LOGGING_CATEGORY(KWIN_XR, "kwin.xr") + namespace KWin { CubeEffect::CubeEffect() : m_shutdownTimer(new QTimer(this)) { + qCCritical(KWIN_XR) << "\t\t\tBreezy - constructor"; qmlRegisterUncreatableType("org.kde.kwin.effect.cube", 1, 0, "CubeEffect", QStringLiteral("Cube cannot be created in QML")); m_shutdownTimer->setSingleShot(true); @@ -57,7 +63,7 @@ CubeEffect::CubeEffect() void CubeEffect::reconfigure(ReconfigureFlags) { CubeConfig::self()->read(); - setAnimationDuration(animationTime(200)); + setAnimationDuration(animationTime(std::chrono::milliseconds(200))); setCubeFaceDisplacement(CubeConfig::cubeFaceDisplacement()); setDistanceFactor(CubeConfig::distanceFactor() / 100.0); setMouseInvertedX(CubeConfig::mouseInvertedX()); @@ -75,11 +81,11 @@ void CubeEffect::reconfigure(ReconfigureFlags) break; } - for (const ElectricBorder &border : qAsConst(m_borderActivate)) { + for (const ElectricBorder &border : std::as_const(m_borderActivate)) { effects->unreserveElectricBorder(border, this); } - for (const ElectricBorder &border : qAsConst(m_touchBorderActivate)) { + for (const ElectricBorder &border : std::as_const(m_touchBorderActivate)) { effects->unregisterTouchBorder(border, m_toggleAction); } @@ -99,7 +105,7 @@ void CubeEffect::reconfigure(ReconfigureFlags) } } -QVariantMap CubeEffect::initialProperties(EffectScreen *screen) +QVariantMap CubeEffect::initialProperties(Output *screen) { return QVariantMap{ {QStringLiteral("effect"), QVariant::fromValue(this)}, @@ -137,6 +143,7 @@ void CubeEffect::toggle() if (isRunning()) { deactivate(); } else { + qCCritical(KWIN_XR) << "\t\t\tBreezy - activate"; activate(); } } @@ -146,7 +153,7 @@ void CubeEffect::activate() if (effects->isScreenLocked()) { return; } - if (effects->numberOfDesktops() < 3) { + if (effects->desktops().size() < 3) { return; } @@ -159,8 +166,8 @@ void CubeEffect::deactivate() return; } - const QList screens = effects->screens(); - for (EffectScreen *screen : screens) { + const QList screens = effects->screens(); + for (Output *screen : screens) { if (QuickSceneView *view = viewForScreen(screen)) { QMetaObject::invokeMethod(view->rootItem(), "stop"); } @@ -283,18 +290,74 @@ QQuaternion CubeEffect::xrRotation() const { } void CubeEffect::updateXrRotation() { - // Example: Read quaternion from /dev/shm/breezy_xr_quat (float32[4], binary) - QFile shmFile("/dev/shm/breezy_xr_quat"); - if (shmFile.open(QIODevice::ReadOnly)) { - float data[4]; - if (shmFile.read(reinterpret_cast(data), sizeof(data)) == sizeof(data)) { - QQuaternion quat(data[3], data[0], data[1], data[2]); // w, x, y, z - if (quat != m_xrRotation) { - m_xrRotation = quat; - Q_EMIT xrRotationChanged(); - } - } - shmFile.close(); + const QString shmPath = QStringLiteral("/dev/shm/breezy_desktop_imu"); + QFile shmFile(shmPath); + + if (!shmFile.open(QIODevice::ReadOnly)) { + return; + } + + QByteArray buffer = shmFile.readAll(); + shmFile.close(); + + if (buffer.size() < 64) { // Minimum expected size based on the data structure + return; + } + + // Create a data view for reading binary data + const char* data = buffer.constData(); + // Use proper data positions based on the original GJS layout + // VERSION at offset 0, ENABLED at offset 1, etc. + + // Read version and enabled flags at their correct positions + quint8 version = static_cast(data[0]); // VERSION at offset 0 + quint8 enabledFlag = static_cast(data[1]); // ENABLED at offset 1 + + // DISPLAY_FOV is at offset: 1 + 1 + (4*4) + (4*2) = 26 + float displayFov; + memcpy(&displayFov, data + 26, sizeof(float)); + + // EPOCH_MS is at offset: 26 + 4 + 4 + 1 + 1 + 1 + (4*16) = 101 + quint64 imuDateMs; + memcpy(&imuDateMs, data + 101, sizeof(quint64)); + imuDateMs = qFromLittleEndian(imuDateMs); + + // IMU_QUAT_DATA is at offset: 101 + 8 = 109 + float imuData[4]; + memcpy(imuData, data + 109, sizeof(imuData)); + + // Validate data + const quint64 currentTimeMs = QDateTime::currentMSecsSinceEpoch(); + const bool validKeepAlive = (currentTimeMs - imuDateMs) < 5000; // 5 second timeout + const bool validData = validKeepAlive && displayFov != 0.0f; + const quint8 expectedVersion = 4; // Define expected data layout version + const bool enabled = (enabledFlag != 0) && (version == expectedVersion) && validData; + + if (!enabled) { + return; + } + qCCritical(KWIN_XR) << "\t\t\tBreezy" << "version:" << version + << " enabledFlag:" << enabledFlag + << " currentTimeMs:" << currentTimeMs + << " imuDateMs:" << imuDateMs; + + + // Check for reset state (identity quaternion) + const bool imuResetState = (imuData[0] == 0.0f && imuData[1] == 0.0f && + imuData[2] == 0.0f && imuData[3] == 1.0f); + + if (imuResetState) { + return; + } + qCCritical(KWIN_XR) << "\t\t\tBreezy - here 5"; + + // Create quaternion (w, x, y, z) + QQuaternion quat(imuData[3], imuData[0], imuData[1], imuData[2]); + + if (quat != m_xrRotation) { + qCCritical(KWIN_XR) << "\t\t\tBreezy - here 6"; + m_xrRotation = quat; + Q_EMIT xrRotationChanged(); } } diff --git a/kwin/src/cubeeffect.h b/kwin/src/cubeeffect.h index 13b5802..f37c8aa 100644 --- a/kwin/src/cubeeffect.h +++ b/kwin/src/cubeeffect.h @@ -6,8 +6,9 @@ #pragma once -#include +#include +#include #include #include @@ -85,7 +86,7 @@ Q_SIGNALS: void xrRotationChanged(); protected: - QVariantMap initialProperties(EffectScreen *screen) override; + QVariantMap initialProperties(Output *screen) override; private: void realDeactivate(); diff --git a/kwin/src/kcm/CMakeLists.txt b/kwin/src/kcm/CMakeLists.txt index 2979e72..9a6df2a 100644 --- a/kwin/src/kcm/CMakeLists.txt +++ b/kwin/src/kcm/CMakeLists.txt @@ -2,13 +2,13 @@ # # SPDX-License-Identifier: BSD-3-Clause -set(kwin_cube_config_SOURCES cubeeffectkcm.cpp) -ki18n_wrap_ui(kwin_cube_config_SOURCES cubeeffectkcm.ui) -qt_add_dbus_interface(kwin_cube_config_SOURCES ${KWIN_EFFECTS_INTERFACE} kwineffects_interface) +set(breezy_desktop_config_SOURCES cubeeffectkcm.cpp) +ki18n_wrap_ui(breezy_desktop_config_SOURCES cubeeffectkcm.ui) +qt_add_dbus_interface(breezy_desktop_config_SOURCES ${KWIN_EFFECTS_INTERFACE} kwineffects_interface) -kcoreaddons_add_plugin(kwin_cube_config INSTALL_NAMESPACE "kwin/effects/configs" SOURCES ${kwin_cube_config_SOURCES}) -kconfig_add_kcfg_files(kwin_cube_config ../cubeconfig.kcfgc) -target_link_libraries(kwin_cube_config +kcoreaddons_add_plugin(breezy_desktop_config INSTALL_NAMESPACE "kwin/effects/configs" SOURCES ${breezy_desktop_config_SOURCES}) +kconfig_add_kcfg_files(breezy_desktop_config ../cubeconfig.kcfgc) +target_link_libraries(breezy_desktop_config KF6::ConfigCore KF6::ConfigGui KF6::ConfigWidgets diff --git a/kwin/src/kcm/cubeeffectkcm.cpp b/kwin/src/kcm/cubeeffectkcm.cpp index 931c9e4..3bbef93 100644 --- a/kwin/src/kcm/cubeeffectkcm.cpp +++ b/kwin/src/kcm/cubeeffectkcm.cpp @@ -20,7 +20,7 @@ K_PLUGIN_CLASS(CubeEffectConfig) CubeEffectConfig::CubeEffectConfig(QObject *parent, const KPluginMetaData &data, const QVariantList &args) - : KCModule(parent, data, args) + : KCModule(parent, data) { ui.setupUi(widget()); addConfig(CubeConfig::self(), widget()); diff --git a/kwin/src/metadata.json b/kwin/src/metadata.json index 19e39fa..7e0f29d 100644 --- a/kwin/src/metadata.json +++ b/kwin/src/metadata.json @@ -2,17 +2,16 @@ "KPlugin": { "Authors": [ { - "Email": "vlad.zahorodnii@kde.org", - "Name": "Vlad Zahorodnii" + "Email": "wayne@xronlinux.com", + "Name": "Wayne Heaney" } ], - "Category": "Window Management", - "Description": "Arrange desktops in a virtual cube", - "EnabledByDefault": false, - "Id": "cube", + "Category": "XR", + "Description": "Breezy Desktop XR Effect", + "EnabledByDefault": true, "License": "GPL", - "Name": "Cube" + "Name": "Breezy Desktop XR" }, - "X-KDE-ConfigModule": "kwin_cube_config", + "X-KDE-ConfigModule": "breezy_desktop_config", "X-KWin-Border-Activate": true } diff --git a/kwin/src/qml/CubeCameraController.qml b/kwin/src/qml/CubeCameraController.qml index 5bef1d7..20ca795 100644 --- a/kwin/src/qml/CubeCameraController.qml +++ b/kwin/src/qml/CubeCameraController.qml @@ -83,14 +83,17 @@ Item { } function updateCamera() { - const eulerRotation = root.rotation.toEulerAngles(); - const theta = (eulerRotation.x + 90) * Math.PI / 180; - const phi = eulerRotation.y * Math.PI / 180; + // convert NWU to EUS by passing root.rotation values: w, -y, z, -x + let effectiveRotation = Qt.quaternion(root.rotation.scalar, -root.rotation.y, root.rotation.z, -root.rotation.x); + + const eulerRotation = effectiveRotation.toEulerAngles(); + const theta = 90 * Math.PI / 180; + const phi = 0.0; camera.position = Qt.vector3d(radius * Math.sin(phi) * Math.sin(theta), radius * Math.cos(theta), radius * Math.cos(phi) * Math.sin(theta)); - camera.rotation = root.rotation; + camera.rotation = effectiveRotation; } // Add property to receive XR rotation from effect diff --git a/kwin/vertexshadereffect/CMakeLists.txt b/kwin/vertexshadereffect/CMakeLists.txt deleted file mode 100644 index e69de29..0000000 diff --git a/kwin/vertexshadereffect/vertexshadereffect.cpp b/kwin/vertexshadereffect/vertexshadereffect.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/kwin/vertexshadereffect/vertexshadereffect.json b/kwin/vertexshadereffect/vertexshadereffect.json deleted file mode 100644 index e69de29..0000000