diff --git a/.nix/packages/breezy-gnome/default.nix b/.nix/packages/breezy-gnome/default.nix new file mode 100644 index 0000000..6676e86 --- /dev/null +++ b/.nix/packages/breezy-gnome/default.nix @@ -0,0 +1,65 @@ +{ + self, + version, + lib, + stdenv, + glib, +}: +let + extensionUuid = "breezydesktop@xronlinux.com"; +in +stdenv.mkDerivation (finalAttrs: { + pname = "gnome-shell-extension-breezy-desktop"; + inherit version; + + src = self; + + nativeBuildInputs = [ + glib # for glib-compile-schemas + ]; + + dontConfigure = true; + dontBuild = true; + + passthru = { + inherit extensionUuid; + }; + + installPhase = '' + runHook preInstall + + extDir=$out/share/gnome-shell/extensions/${extensionUuid} + mkdir -p $extDir + + # JavaScript source files + cd gnome/src + for f in *.js metadata.json; do + install -Dm644 "$f" "$extDir/$f" + done + + # Fragment shader (resolve symlink) + cp -L Sombrero.frag "$extDir/Sombrero.frag" + + # D-Bus interfaces + mkdir -p "$extDir/dbus-interfaces" + cp dbus-interfaces/*.xml "$extDir/dbus-interfaces/" + + # Textures (resolve symlinks) + mkdir -p "$extDir/textures" + cp -L textures/* "$extDir/textures/" + + # GSettings schema (resolve symlink and compile) + mkdir -p "$extDir/schemas" + cp -L schemas/*.xml "$extDir/schemas/" + glib-compile-schemas "$extDir/schemas" + + runHook postInstall + ''; + + meta = { + description = "GNOME Shell extension for Breezy Desktop XR virtual display"; + homepage = "https://github.com/wheaney/breezy-desktop"; + license = lib.licenses.gpl3Only; + platforms = lib.platforms.linux; + }; +}) diff --git a/.nix/packages/breezy-kde/default.nix b/.nix/packages/breezy-kde/default.nix new file mode 100644 index 0000000..fa19fc1 --- /dev/null +++ b/.nix/packages/breezy-kde/default.nix @@ -0,0 +1,89 @@ +{ + self, + version, + lib, + stdenv, + fetchFromGitHub, + cmake, + pkg-config, + kdePackages, + libepoxy, +}: +stdenv.mkDerivation (finalAttrs: { + pname = "breezy-kwin"; + inherit version; + + src = self; + + sourceRoot = "."; + + unpackPhase = '' + cp -r $src $TMPDIR/breezy-desktop + chmod -R u+w $TMPDIR/breezy-desktop + cd $TMPDIR/breezy-desktop/kwin + ''; + + nativeBuildInputs = [ + cmake + kdePackages.extra-cmake-modules + kdePackages.wrapQtAppsHook + pkg-config + ]; + + buildInputs = with kdePackages; [ + kconfig + kconfigwidgets + kcoreaddons + kglobalaccel + ki18n + kcmutils + kwindowsystem + kxmlgui + kwin + qtbase + qtdeclarative + qt3d + qtquick3d + libepoxy + ]; + + postPatch = '' + # VERSION is read relative to kwin/src/../VERSION = kwin/VERSION + # and also from kwin/../VERSION for the top-level CMakeLists.txt + echo "${finalAttrs.version}" > ../VERSION + echo "${finalAttrs.version}" > VERSION + + # Copy files expected by CMake install but located elsewhere in the mono-repo + cp ../ui/modules/PyXRLinuxDriverIPC/xrdriveripc.py src/xrdriveripc/xrdriveripc.py + cp ../ui/data/icons/hicolor/scalable/apps/com.xronlinux.BreezyDesktop.svg src/kcm/com.xronlinux.BreezyDesktop.svg + + # Fix hardcoded /usr/include/kwin path + substituteInPlace cmake/info.cmake \ + --replace-fail '/usr/include/kwin/effect/effect.h' \ + '${kdePackages.kwin.dev}/include/kwin/effect/effect.h' + + # Fix QtQuick3D QML module detection - bypass qmake query + substituteInPlace CMakeLists.txt \ + --replace-fail 'execute_process( + COMMAND ''${QT6_QMAKE_EXECUTABLE} -query QT_INSTALL_QML + OUTPUT_VARIABLE QT6_QML_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE + )' 'set(QT6_QML_DIR "${kdePackages.qtquick3d}/lib/qt-6/qml")' + + # Remove the hardcoded /usr/include reference + substituteInPlace src/CMakeLists.txt \ + --replace-fail 'target_include_directories(breezy_desktop PRIVATE /usr/include/kwin)' \ + 'target_include_directories(breezy_desktop PRIVATE ${kdePackages.kwin.dev}/include/kwin)' + ''; + + cmakeFlags = [ + "-DCMAKE_BUILD_TYPE=Release" + ]; + + meta = { + description = "KWin effect plugin for Breezy Desktop XR virtual display"; + homepage = "https://github.com/wheaney/breezy-desktop"; + license = lib.licenses.gpl3Only; + platforms = lib.platforms.linux; + }; +}) diff --git a/.nix/packages/breezy-ui/default.nix b/.nix/packages/breezy-ui/default.nix new file mode 100644 index 0000000..a66fe89 --- /dev/null +++ b/.nix/packages/breezy-ui/default.nix @@ -0,0 +1,91 @@ +{ + self, + version, + lib, + stdenv, + fetchFromGitHub, + meson, + ninja, + pkg-config, + gettext, + glib, + gtk4, + libadwaita, + desktop-file-utils, + gobject-introspection, + wrapGAppsHook4, + python3Packages, + python3, + gst_all_1, + appstream, +}: +stdenv.mkDerivation (finalAttrs: { + pname = "breezy-desktop-ui"; + inherit version; + + # Use the ui/ subtree but need root for VERSION file + src = self; + sourceRoot = "ui"; + + # The source is a nix store path, not a directory name + unpackPhase = '' + cp -r $src $TMPDIR/breezy-desktop + chmod -R u+w $TMPDIR/breezy-desktop + cd $TMPDIR/breezy-desktop/ui + sourceRoot=$(pwd) + ''; + + nativeBuildInputs = [ + meson + ninja + pkg-config + gettext + glib # glib-compile-schemas + gtk4 # gtk-update-icon-cache + desktop-file-utils + gobject-introspection + wrapGAppsHook4 + appstream # appstreamcli for validation + ]; + + buildInputs = [ + gtk4 + libadwaita + glib + gst_all_1.gstreamer + gst_all_1.gst-plugins-base + (python3.withPackages ( + ps: with ps; [ + pygobject3 + pydbus + ] + )) + ]; + + # Patch the entry scripts to use Nix store paths instead of XDG_DATA_HOME + postPatch = '' + substituteInPlace src/breezydesktop.in \ + --replace-fail "appdir = os.getenv('APPDIR', xdg_data_home)" \ + "appdir = os.getenv('APPDIR', '$out/share')" + substituteInPlace src/virtualdisplay.in \ + --replace-fail "appdir = os.getenv('APPDIR', xdg_data_home)" \ + "appdir = os.getenv('APPDIR', '$out/share')" || true + + # Upstream bug: virtualdisplayrow.py is missing from meson.build install list + substituteInPlace src/meson.build \ + --replace-fail "'virtualdisplay.py'," "'virtualdisplay.py', 'virtualdisplayrow.py'," + ''; + + # Skip tests that need network or display + mesonFlags = [ + ]; + + # wrapGAppsHook4 handles GI_TYPELIB_PATH, GDK_PIXBUF, etc. + + meta = { + description = "GTK4 settings UI for Breezy Desktop XR"; + homepage = "https://github.com/wheaney/breezy-desktop"; + license = lib.licenses.gpl3Only; + platforms = lib.platforms.linux; + }; +}) diff --git a/.nix/packages/breezy-vulkan/default.nix b/.nix/packages/breezy-vulkan/default.nix new file mode 100644 index 0000000..fab75c6 --- /dev/null +++ b/.nix/packages/breezy-vulkan/default.nix @@ -0,0 +1,60 @@ +{ + self, + version, + lib, + stdenv, + fetchFromGitHub, + meson, + ninja, + pkg-config, + glslang, + spirv-headers, + vulkan-headers, + vulkan-loader, + libx11, +}: +stdenv.mkDerivation (finalAttrs: { + pname = "breezy-vulkan"; + inherit version; + + src = "${self}/vulkan/modules/vkBasalt"; + + nativeBuildInputs = [ + meson + ninja + pkg-config + glslang + ]; + + buildInputs = [ + spirv-headers + vulkan-headers + vulkan-loader + libx11 + ]; + + postInstall = + let + sombreroSrc = "${self}/modules/sombrero"; + vulkanSrc = "${self}/vulkan"; + in + '' + # Install sombrero shaders + mkdir -p $out/share/breezy-vulkan/shaders + cp ${sombreroSrc}/Sombrero.frag $out/share/breezy-vulkan/shaders/ + cp ${sombreroSrc}/calibrating.png $out/share/breezy-vulkan/shaders/ || true + + # Install breezy vulkan config + install -Dm644 ${vulkanSrc}/config/vkBasalt.conf $out/share/breezy-vulkan/vkBasalt.conf + + # Install custom banner + cp ${vulkanSrc}/custom_banner.png $out/share/breezy-vulkan/ || true + ''; + + meta = { + description = "Vulkan post-processing layer for Breezy Desktop XR gaming"; + homepage = "https://github.com/wheaney/breezy-desktop"; + license = lib.licenses.gpl3Only; + platforms = [ "x86_64-linux" ]; + }; +}) diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..732d829 --- /dev/null +++ b/flake.lock @@ -0,0 +1,98 @@ +{ + "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1767039857, + "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1767039857, + "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1776169885, + "narHash": "sha256-l/iNYDZ4bGOAFQY2q8y5OAfBBtrDAaPuRQqWaFHVRXM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4bd9165a9165d7b5e33ae57f3eecbcb28fb231c9", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1774106199, + "narHash": "sha256-US5Tda2sKmjrg2lNHQL3jRQ6p96cgfWh3J1QBliQ8Ws=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "6c9a78c09ff4d6c21d0319114873508a6ec01655", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": "nixpkgs", + "xrlinuxdriver": "xrlinuxdriver" + } + }, + "xrlinuxdriver": { + "inputs": { + "flake-compat": "flake-compat_2", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1776468124, + "narHash": "sha256-Hd/D09C/8eYdQD3bhoZo02Ta1ZxsATavZdIL7Dsv8FI=", + "ref": "shymega/nix-flake-support", + "rev": "888dceff06f7d0a5b88e2b29c5d98905aa447560", + "revCount": 418, + "submodules": true, + "type": "git", + "url": "https://github.com/shymega/XRLinuxDriver" + }, + "original": { + "ref": "shymega/nix-flake-support", + "type": "git", + "url": "https://github.com/shymega/XRLinuxDriver" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..dd65539 --- /dev/null +++ b/flake.nix @@ -0,0 +1,62 @@ +{ + description = "Nix Flake for Breezy Desktop"; + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs?ref=nixos-unstable"; + flake-compat = { + url = "github:edolstra/flake-compat"; + flake = false; + }; + xrlinuxdriver.url = "git+https://github.com/shymega/XRLinuxDriver?ref=shymega/nix-flake-support"; + self.submodules = true; + }; + outputs = + inputs: + let + inherit (inputs) self nixpkgs flake-utils; + + forEachSystem = + let + systems = [ + "x86_64-linux" + "aarch64-linux" + ]; + genPkgs = system: nixpkgs.legacyPackages.${system}; + inherit (nixpkgs.lib) genAttrs; + in + f: genAttrs systems (system: f (genPkgs system)); + in + { + packages = forEachSystem ( + pkgs: + let + version = builtins.readFile "${self}/VERSION"; + in + { + breezy-gnome = pkgs.callPackage ./.nix/packages/breezy-gnome { inherit self version; }; + breezy-kde = pkgs.callPackage ./.nix/packages/breezy-kde { inherit self version; }; + breezy-ui = pkgs.callPackage ./.nix/packages/breezy-ui { inherit self version; }; + breezy-vulkan = pkgs.callPackage ./.nix/packages/breezy-vulkan { inherit self version; }; + breezy-desktop = pkgs.symlinkJoin { + name = "breezy-desktop"; + paths = with self.packages.${pkgs.stdenv.hostPlatform.system}; [ + breezy-gnome + breezy-kde + breezy-ui + breezy-vulkan + ] ++ (with inputs.xrlinuxdriver.packages.${pkgs.stdenv.hostPlatform.system}; [ + xrlinuxdriver + ]); + meta.mainProgram = "breezydesktop"; + }; + default = self.packages.${pkgs.stdenv.hostPlatform.system}.breezy-desktop; + } + ); + + devShells = forEachSystem (pkgs: { + default = pkgs.mkShell { + inputsFrom = with self.packages.${pkgs.stdenv.hostPlatform.system}; [ default ]; + }; + }); + overlays.default = _: prev: self.packages.${prev.stdenv.hostPlatform.system}; + }; +}