diff --git a/kwin/README.md b/kwin/README.md deleted file mode 100644 index 254293f..0000000 --- a/kwin/README.md +++ /dev/null @@ -1,111 +0,0 @@ -# Cube effect - -![Screenshot](data/screenshot.avif) - -This is a basic desktop cube effect for KWin. It's primarily intended to help you -impress your friends with what one can do on "Linux." - -

- -

- - -## How to use it - -Go to desktop effect settings, and enable the Cube effect. Once you've done that, -the Cube effect can be activated by pressing `Meta+C` shortcut. - -Note that you will need at least 3 virtual desktops in order to activate the effect. - -Key navigation: - -- `Escape` - quit the effect -- `Left` and `Right` arrow keys - rotate the cube left or right, respectively -- `Enter`/`Space`/`Return` - switch to the currently viewed desktop - -Mouse navigation: - -- LMB click - switch to the currently viewed desktop -- Press LMB and drag - rotate the cube -- Wheel up and down - move the cube farther or closer, respectively - - -## Installation - -Arch Linux: - -For users who are using KF6/Plasma 6 -```sh -yay -S kwin-effects-cube-git -``` -For users who are using Plasma 5 -```sh -yay -S kwin-effects-cube -``` - -## Building from Git - -You will need the following dependencies to build this effect: - -* CMake -* any C++14 enabled compiler -* Qt - - qtbase - - qtdeclarative - - qtquick3d -* libkwineffects -* KDE Frameworks 5: - - Config - - CoreAddons - - Extra CMake Modules - - GlobalAccel - - WindowSystem - -On Arch Linux - -```sh -sudo pacman -S cmake extra-cmake-modules kwin qt5-quick3d -``` - -On Fedora - -```sh -sudo dnf install cmake extra-cmake-modules kf5-kconfig-devel kf5-kcoreaddons-devel \ - kf5-kglobalaccel-devel kf5-ki18n-devel kf5-kwindowsystem-devel kf5-kxmlgui-devel \ - kwin-devel libepoxy-devel qt5-qtbase-devel -``` - -On Ubuntu - -```sh -sudo apt install cmake extra-cmake-modules gettext kwin-dev libkf5config-dev \ - libkf5configwidgets-dev libkf5coreaddons-dev libkf5globalaccel-dev - libkf5windowsystem-dev libkf5xmlgui-dev qtbase5-dev qtdeclarative5-dev -``` - -After you installed all the required dependencies, you can build -the effect: - -```sh -git clone https://github.com/zzag/kwin-effects-cube.git -cd kwin-effects-cube -cmake -B build -S . \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=/usr -cmake --build build --parallel -cmake --install build -``` - -## Building QtQuick 3D from source code - -Note that some distributions (e.g. Ubuntu or Fedora) don't package QtQuick 3D. -If you use such a distro, you will have to build QtQuick 3D from source code. - -Go to https://download.qt.io/official_releases/qt/ and download qtquick3d source -tarball (it's in `submodules/` folder) for 5.15, unpack it and run the following commands - -``` -qmake qtquick3d.pro -make -make install -``` diff --git a/kwin/src/CMakeLists.txt b/kwin/src/CMakeLists.txt index 71a6c70..1aba16e 100644 --- a/kwin/src/CMakeLists.txt +++ b/kwin/src/CMakeLists.txt @@ -1,10 +1,6 @@ -# SPDX-FileCopyrightText: 2022 Vlad Zahorodnii -# -# SPDX-License-Identifier: BSD-3-Clause - kcoreaddons_add_plugin(breezy_desktop_effect INSTALL_NAMESPACE "kwin/effects/plugins/") target_sources(breezy_desktop_effect PRIVATE - cubeeffect.cpp + breezydesktopeffect.cpp main.cpp ) @@ -22,4 +18,4 @@ target_link_libraries(breezy_desktop_effect KWin::kwin ) -install(DIRECTORY qml DESTINATION ${KDE_INSTALL_DATADIR}/kwin/effects/cube) +install(DIRECTORY qml DESTINATION ${KDE_INSTALL_DATADIR}/kwin/effects/breezy_desktop) diff --git a/kwin/src/Messages.sh b/kwin/src/Messages.sh index d80b7d6..9f88a20 100644 --- a/kwin/src/Messages.sh +++ b/kwin/src/Messages.sh @@ -1,2 +1,2 @@ #! /usr/bin/env bash -$XGETTEXT `find . -name \*.qml-o -name \*.cpp` -o $podir/kwin_effect_cube.pot +$XGETTEXT `find . -name \*.qml-o -name \*.cpp` -o $podir/kwin_effect_breezy_desktop.pot diff --git a/kwin/src/cubeeffect.cpp b/kwin/src/breezydesktopeffect.cpp similarity index 70% rename from kwin/src/cubeeffect.cpp rename to kwin/src/breezydesktopeffect.cpp index 1d0d33a..604ed44 100644 --- a/kwin/src/cubeeffect.cpp +++ b/kwin/src/breezydesktopeffect.cpp @@ -1,10 +1,4 @@ -/* - SPDX-FileCopyrightText: 2022 Vlad Zahorodnii - - SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL -*/ - -#include "cubeeffect.h" +#include "breezydesktopeffect.h" #include "effect/effect.h" #include "effect/effecthandler.h" @@ -22,41 +16,43 @@ Q_LOGGING_CATEGORY(KWIN_XR, "kwin.xr") namespace KWin { -CubeEffect::CubeEffect() +BreezyDesktopEffect::BreezyDesktopEffect() : 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")); + qmlRegisterUncreatableType("org.kde.kwin.effect.breezy_desktop", 1, 0, "BreezyDesktopEffect", QStringLiteral("BreezyDesktop cannot be created in QML")); m_shutdownTimer->setSingleShot(true); - connect(m_shutdownTimer, &QTimer::timeout, this, &CubeEffect::realDeactivate); - connect(effects, &EffectsHandler::screenAboutToLock, this, &CubeEffect::realDeactivate); + connect(m_shutdownTimer, &QTimer::timeout, this, &BreezyDesktopEffect::realDeactivate); + connect(effects, &EffectsHandler::screenAboutToLock, this, &BreezyDesktopEffect::realDeactivate); - const QKeySequence defaultToggleShortcut = Qt::META | Qt::Key_C; + const QKeySequence defaultToggleShortcut = Qt::META | Qt::Key_B; m_toggleAction = new QAction(this); - m_toggleAction->setObjectName(QStringLiteral("Cube")); - m_toggleAction->setText(i18n("Toggle Cube")); + m_toggleAction->setObjectName(QStringLiteral("BreezyDesktop")); + m_toggleAction->setText(i18n("Toggle BreezyDesktop")); KGlobalAccel::self()->setDefaultShortcut(m_toggleAction, {defaultToggleShortcut}); KGlobalAccel::self()->setShortcut(m_toggleAction, {defaultToggleShortcut}); m_toggleShortcut = KGlobalAccel::self()->shortcut(m_toggleAction); - connect(m_toggleAction, &QAction::triggered, this, &CubeEffect::toggle); + connect(m_toggleAction, &QAction::triggered, this, &BreezyDesktopEffect::toggle); connect(KGlobalAccel::self(), &KGlobalAccel::globalShortcutChanged, this, [this](QAction *action, const QKeySequence &seq) { - if (action->objectName() == QStringLiteral("Cube")) { + if (action->objectName() == QStringLiteral("BreezyDesktop")) { m_toggleShortcut.clear(); m_toggleShortcut.append(seq); } }); - setSource(QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kwin/effects/cube/qml/main.qml")))); + setSource(QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kwin/effects/breezy_desktop/qml/main.qml")))); m_xrRotationTimer = new QTimer(this); m_xrRotationTimer->setInterval(16); // ~60Hz - connect(m_xrRotationTimer, &QTimer::timeout, this, &CubeEffect::updateXrRotation); + connect(m_xrRotationTimer, &QTimer::timeout, this, &BreezyDesktopEffect::updateXrRotation); m_xrRotationTimer->start(); + + toggle(); } -QVariantMap CubeEffect::initialProperties(Output *screen) +QVariantMap BreezyDesktopEffect::initialProperties(Output *screen) { return QVariantMap{ {QStringLiteral("effect"), QVariant::fromValue(this)}, @@ -64,32 +60,12 @@ QVariantMap CubeEffect::initialProperties(Output *screen) }; } -int CubeEffect::requestedEffectChainPosition() const +int BreezyDesktopEffect::requestedEffectChainPosition() const { return 70; } -void CubeEffect::grabbedKeyboardEvent(QKeyEvent *e) -{ - if (e->type() == QEvent::KeyPress) { - if (m_toggleShortcut.contains(e->key() | e->modifiers())) { - toggle(); - return; - } - } - QuickSceneEffect::grabbedKeyboardEvent(e); -} - -bool CubeEffect::borderActivated(ElectricBorder border) -{ - if (m_borderActivate.contains(border)) { - toggle(); - return true; - } - return false; -} - -void CubeEffect::toggle() +void BreezyDesktopEffect::toggle() { if (isRunning()) { deactivate(); @@ -99,7 +75,7 @@ void CubeEffect::toggle() } } -void CubeEffect::activate() +void BreezyDesktopEffect::activate() { if (effects->isScreenLocked()) { return; @@ -114,7 +90,7 @@ void CubeEffect::activate() effects->stopMouseInterception(this); } -void CubeEffect::deactivate() +void BreezyDesktopEffect::deactivate() { if (m_shutdownTimer->isActive()) { return; @@ -130,51 +106,51 @@ void CubeEffect::deactivate() m_shutdownTimer->start(animationDuration()); } -void CubeEffect::realDeactivate() +void BreezyDesktopEffect::realDeactivate() { setRunning(false); } -int CubeEffect::animationDuration() const +int BreezyDesktopEffect::animationDuration() const { return 200; } -qreal CubeEffect::cubeFaceDisplacement() const +qreal BreezyDesktopEffect::faceDisplacement() const { return 100; } -qreal CubeEffect::distanceFactor() const +qreal BreezyDesktopEffect::distanceFactor() const { return 1.5; } -bool CubeEffect::mouseInvertedX() const +bool BreezyDesktopEffect::mouseInvertedX() const { return false; } -bool CubeEffect::mouseInvertedY() const +bool BreezyDesktopEffect::mouseInvertedY() const { return false; } -CubeEffect::BackgroundMode CubeEffect::backgroundMode() const +BreezyDesktopEffect::BackgroundMode BreezyDesktopEffect::backgroundMode() const { return BackgroundMode::Color; } -QColor CubeEffect::backgroundColor() const +QColor BreezyDesktopEffect::backgroundColor() const { return QColor(Qt::black); } -QQuaternion CubeEffect::xrRotation() const { +QQuaternion BreezyDesktopEffect::xrRotation() const { return m_xrRotation; } -void CubeEffect::updateXrRotation() { +void BreezyDesktopEffect::updateXrRotation() { const QString shmPath = QStringLiteral("/dev/shm/breezy_desktop_imu"); QFile shmFile(shmPath); @@ -219,6 +195,11 @@ void CubeEffect::updateXrRotation() { const bool enabled = (enabledFlag != 0) && (version == expectedVersion) && validData; if (!enabled) { + if (isRunning()) { + qCCritical(KWIN_XR) << "\t\t\tBreezy - deactivate due to disabled"; + deactivate(); + } + return; } @@ -227,6 +208,11 @@ void CubeEffect::updateXrRotation() { imuData[2] == 0.0f && imuData[3] == 1.0f); if (imuResetState) { + if (isRunning()) { + qCCritical(KWIN_XR) << "\t\t\tBreezy - deactivate due to reset state"; + deactivate(); + } + return; } @@ -235,6 +221,12 @@ void CubeEffect::updateXrRotation() { if (quat != m_xrRotation) { m_xrRotation = quat; + + if (!isRunning()) { + qCCritical(KWIN_XR) << "\t\t\tBreezy - activate"; + activate(); + } + Q_EMIT xrRotationChanged(); } } diff --git a/kwin/src/breezydesktopeffect.h b/kwin/src/breezydesktopeffect.h new file mode 100644 index 0000000..0ed2d50 --- /dev/null +++ b/kwin/src/breezydesktopeffect.h @@ -0,0 +1,78 @@ +#pragma once + +#include + +#include +#include +#include + +namespace KWin +{ + + class BreezyDesktopEffect : public QuickSceneEffect + { + Q_OBJECT + Q_PROPERTY(int animationDuration READ animationDuration NOTIFY animationDurationChanged) + Q_PROPERTY(qreal faceDisplacement READ faceDisplacement NOTIFY faceDisplacementChanged) + Q_PROPERTY(qreal distanceFactor READ distanceFactor NOTIFY distanceFactorChanged) + Q_PROPERTY(bool mouseInvertedX READ mouseInvertedX NOTIFY mouseInvertedXChanged) + Q_PROPERTY(bool mouseInvertedY READ mouseInvertedY NOTIFY mouseInvertedYChanged) + Q_PROPERTY(BackgroundMode backgroundMode READ backgroundMode NOTIFY backgroundModeChanged) + Q_PROPERTY(QColor backgroundColor READ backgroundColor NOTIFY backgroundColorChanged) + Q_PROPERTY(QQuaternion xrRotation READ xrRotation NOTIFY xrRotationChanged) + + public: + enum class BackgroundMode + { + Color, + Skybox, + }; + Q_ENUM(BackgroundMode) + + BreezyDesktopEffect(); + + int requestedEffectChainPosition() const override; + + int animationDuration() const; + qreal faceDisplacement() const; + qreal distanceFactor() const; + bool mouseInvertedX() const; + bool mouseInvertedY() const; + BackgroundMode backgroundMode() const; + QColor backgroundColor() const; + + QQuaternion xrRotation() const; + + public Q_SLOTS: + void activate(); + void deactivate(); + void toggle(); + void updateXrRotation(); + + Q_SIGNALS: + void faceDisplacementChanged(); + void distanceFactorChanged(); + void mouseInvertedXChanged(); + void mouseInvertedYChanged(); + void animationDurationChanged(); + void skyboxChanged(); + void backgroundModeChanged(); + void backgroundColorChanged(); + void xrRotationChanged(); + + protected: + QVariantMap initialProperties(Output *screen) override; + + private: + void realDeactivate(); + + QTimer *m_shutdownTimer; + QAction *m_toggleAction = nullptr; + QList m_toggleShortcut; + QList m_borderActivate; + QList m_touchBorderActivate; + QQuaternion m_xrRotation; + QTimer *m_xrRotationTimer = nullptr; + }; + +} // namespace KWin diff --git a/kwin/src/cubeconfig.kcfg b/kwin/src/cubeconfig.kcfg deleted file mode 100644 index e69de29..0000000 diff --git a/kwin/src/cubeconfig.kcfgc b/kwin/src/cubeconfig.kcfgc deleted file mode 100644 index e69de29..0000000 diff --git a/kwin/src/cubeeffect.h b/kwin/src/cubeeffect.h deleted file mode 100644 index 5829318..0000000 --- a/kwin/src/cubeeffect.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - SPDX-FileCopyrightText: 2022 Vlad Zahorodnii - - SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL -*/ - -#pragma once - -#include - -#include -#include -#include - -namespace KWin -{ - -class CubeEffect : public QuickSceneEffect -{ - Q_OBJECT - Q_PROPERTY(int animationDuration READ animationDuration NOTIFY animationDurationChanged) - Q_PROPERTY(qreal cubeFaceDisplacement READ cubeFaceDisplacement NOTIFY cubeFaceDisplacementChanged) - Q_PROPERTY(qreal distanceFactor READ distanceFactor NOTIFY distanceFactorChanged) - Q_PROPERTY(bool mouseInvertedX READ mouseInvertedX NOTIFY mouseInvertedXChanged) - Q_PROPERTY(bool mouseInvertedY READ mouseInvertedY NOTIFY mouseInvertedYChanged) - Q_PROPERTY(BackgroundMode backgroundMode READ backgroundMode NOTIFY backgroundModeChanged) - Q_PROPERTY(QColor backgroundColor READ backgroundColor NOTIFY backgroundColorChanged) - Q_PROPERTY(QQuaternion xrRotation READ xrRotation NOTIFY xrRotationChanged) - -public: - enum class BackgroundMode { - Color, - Skybox, - }; - Q_ENUM(BackgroundMode) - - CubeEffect(); - - int requestedEffectChainPosition() const override; - void grabbedKeyboardEvent(QKeyEvent *e) override; - bool borderActivated(ElectricBorder border) override; - - int animationDuration() const; - qreal cubeFaceDisplacement() const; - qreal distanceFactor() const; - bool mouseInvertedX() const; - bool mouseInvertedY() const; - BackgroundMode backgroundMode() const; - QColor backgroundColor() const; - - QQuaternion xrRotation() const; - -public Q_SLOTS: - void activate(); - void deactivate(); - void toggle(); - void updateXrRotation(); - -Q_SIGNALS: - void cubeFaceDisplacementChanged(); - void distanceFactorChanged(); - void mouseInvertedXChanged(); - void mouseInvertedYChanged(); - void animationDurationChanged(); - void skyboxChanged(); - void backgroundModeChanged(); - void backgroundColorChanged(); - void xrRotationChanged(); - -protected: - QVariantMap initialProperties(Output *screen) override; - -private: - void realDeactivate(); - - QTimer *m_shutdownTimer; - QAction *m_toggleAction = nullptr; - QList m_toggleShortcut; - QList m_borderActivate; - QList m_touchBorderActivate; - QQuaternion m_xrRotation; - QTimer *m_xrRotationTimer = nullptr; -}; - -} // namespace KWin diff --git a/kwin/src/main.cpp b/kwin/src/main.cpp index e947f72..cdab856 100644 --- a/kwin/src/main.cpp +++ b/kwin/src/main.cpp @@ -1,15 +1,9 @@ -/* - SPDX-FileCopyrightText: 2022 Vlad Zahorodnii - - SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL -*/ - -#include "cubeeffect.h" +#include "breezydesktopeffect.h" namespace KWin { -KWIN_EFFECT_FACTORY_SUPPORTED(CubeEffect, "metadata.json", return CubeEffect::supported();) +KWIN_EFFECT_FACTORY_SUPPORTED(BreezyDesktopEffect, "metadata.json", return BreezyDesktopEffect::supported();) } // namespace KWin diff --git a/kwin/src/qml/Cube.qml b/kwin/src/qml/BreezyDesktop.qml similarity index 91% rename from kwin/src/qml/Cube.qml rename to kwin/src/qml/BreezyDesktop.qml index 0d266eb..30b621d 100644 --- a/kwin/src/qml/Cube.qml +++ b/kwin/src/qml/BreezyDesktop.qml @@ -1,17 +1,9 @@ -/* - SPDX-FileCopyrightText: 2022 Vlad Zahorodnii - - SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL -*/ - import QtQuick import QtQuick3D import org.kde.kwin as KWinComponents Node { - id: cube - readonly property var supportedModels: [ "VITURE", "nreal air", @@ -61,9 +53,8 @@ Node { } Repeater3D { - id: faceRepeater model: screens.length - delegate: CubeFace { + delegate: BreezyDesktopDisplay { screen: screens[index] property real screenRotation: { diff --git a/kwin/src/qml/CubeFace.qml b/kwin/src/qml/BreezyDesktopDisplay.qml similarity index 54% rename from kwin/src/qml/CubeFace.qml rename to kwin/src/qml/BreezyDesktopDisplay.qml index 4808d3e..3d6182b 100644 --- a/kwin/src/qml/CubeFace.qml +++ b/kwin/src/qml/BreezyDesktopDisplay.qml @@ -1,14 +1,8 @@ -/* - SPDX-FileCopyrightText: 2022 Vlad Zahorodnii - - SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL -*/ - import QtQuick import QtQuick3D Model { - id: face + id: display required property QtObject screen required property int index @@ -20,9 +14,9 @@ Model { lighting: DefaultMaterial.NoLighting diffuseMap: Texture { sourceItem: DesktopView { - screen: face.screen - width: face.screen.geometry.width - height: face.screen.geometry.height + screen: display.screen + width: display.screen.geometry.width + height: display.screen.geometry.height } } } diff --git a/kwin/src/qml/CubeCameraController.qml b/kwin/src/qml/CameraController.qml similarity index 89% rename from kwin/src/qml/CubeCameraController.qml rename to kwin/src/qml/CameraController.qml index c0f7c54..77a502d 100644 --- a/kwin/src/qml/CubeCameraController.qml +++ b/kwin/src/qml/CameraController.qml @@ -1,9 +1,3 @@ -/* - SPDX-FileCopyrightText: 2022 Vlad Zahorodnii - - SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL -*/ - import QtQuick import QtQuick3D diff --git a/kwin/src/qml/DesktopView.qml b/kwin/src/qml/DesktopView.qml index b62bc63..f87f7cd 100644 --- a/kwin/src/qml/DesktopView.qml +++ b/kwin/src/qml/DesktopView.qml @@ -1,9 +1,3 @@ -/* - SPDX-FileCopyrightText: 2022 Vlad Zahorodnii - - SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL -*/ - import QtQuick import org.kde.kwin as KWinComponents diff --git a/kwin/src/qml/main.qml b/kwin/src/qml/main.qml index c9aa0b7..a48a8ee 100644 --- a/kwin/src/qml/main.qml +++ b/kwin/src/qml/main.qml @@ -1,13 +1,7 @@ -/* - SPDX-FileCopyrightText: 2022 Vlad Zahorodnii - - SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL -*/ - import QtQuick import QtQuick3D import org.kde.kwin as KWinComponents -import org.kde.kwin.effect.cube +import org.kde.kwin.effect.breezy_desktop Item { id: root @@ -26,13 +20,6 @@ Item { function stop() { } - function switchToSelected() { - // const eulerRotation = cameraController.rotation.toEulerAngles(); - // const desktop = cube.screenAt(eulerRotation.y); - // KWinComponents.Workspace.currentDesktop = desktop; - // effect.deactivate(); - } - View3D { id: view anchors.fill: parent @@ -42,18 +29,18 @@ Item { fieldOfView: 22.55 } - Cube { - id: cube + BreezyDesktop { + id: breezyDesktop viewportFOVHorizontal: 40.09 viewportWidth: 1920 viewportHeight: 1080 } - CubeCameraController { + CameraController { id: cameraController anchors.fill: parent camera: camera - radius: 0.5 * cube.viewportHeight / Math.tan(camera.fieldOfView * Math.PI / 360) + radius: 0.5 * breezyDesktop.viewportHeight / Math.tan(camera.fieldOfView * Math.PI / 360) Behavior on rotation { enabled: !cameraController.busy && root.animationEnabled