WIP - working XR effect demo
This commit is contained in:
parent
75e31f3f16
commit
458700798f
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -6,21 +6,27 @@
|
|||
|
||||
#include "cubeeffect.h"
|
||||
#include "cubeconfig.h"
|
||||
#include "effect/effect.h"
|
||||
#include "effect/effecthandler.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QFile>
|
||||
#include <QLoggingCategory>
|
||||
#include <QQuickItem>
|
||||
#include <QTimer>
|
||||
|
||||
#include <KGlobalAccel>
|
||||
#include <KLocalizedString>
|
||||
|
||||
Q_LOGGING_CATEGORY(KWIN_XR, "kwin.xr")
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
CubeEffect::CubeEffect()
|
||||
: m_shutdownTimer(new QTimer(this))
|
||||
{
|
||||
qCCritical(KWIN_XR) << "\t\t\tBreezy - constructor";
|
||||
qmlRegisterUncreatableType<CubeEffect>("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<EffectScreen *> screens = effects->screens();
|
||||
for (EffectScreen *screen : screens) {
|
||||
const QList<Output *> 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<char*>(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<quint8>(data[0]); // VERSION at offset 0
|
||||
quint8 enabledFlag = static_cast<quint8>(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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <libkwineffects/kwinquickeffect.h>
|
||||
#include <effect/quickeffect.h>
|
||||
|
||||
#include <QAction>
|
||||
#include <QKeySequence>
|
||||
#include <QQuaternion>
|
||||
|
||||
|
|
@ -85,7 +86,7 @@ Q_SIGNALS:
|
|||
void xrRotationChanged();
|
||||
|
||||
protected:
|
||||
QVariantMap initialProperties(EffectScreen *screen) override;
|
||||
QVariantMap initialProperties(Output *screen) override;
|
||||
|
||||
private:
|
||||
void realDeactivate();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue