Skip to content

Commit 124f575

Browse files
dskvrclaudeCopilot
authored
Refactor: Compositor/Platform/Renderer Adapters, Modular Architecture (#10)
* feat: Begin modularization - Phase 0 implementation Extract core functionality into separate modules as part of the effort to make hyprlax compatible with multiple compositors beyond Hyprland. This commit implements Phase 0 of the modularization plan: - Created modular directory structure (src/core/, src/include/) - Extracted easing functions to core/easing.c module - Extracted animation state management to core/animation.c - Extracted layer management to core/layer.c - Extracted configuration parsing to core/config.c - Created internal header files for module interfaces - Updated Makefile to support modular compilation - Maintained single-binary architecture with static linking Note: Temporarily renamed core module's layer_t to parallax_layer_t to avoid conflicts with IPC's layer_t. This will be unified in future phases. The binary still compiles and maintains existing functionality while laying the groundwork for compositor abstraction. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: Implement renderer abstraction - Phase 1 Create a renderer abstraction layer to decouple rendering from the main application logic, enabling support for different rendering backends. This commit implements Phase 1 of the modularization plan: - Created renderer interface (include/renderer.h) with operations struct - Created shader management interface (include/shader.h) - Implemented OpenGL ES 2.0 renderer backend (renderer/gles2.c) - Implemented shader compilation and management (renderer/shader.c) - Added renderer factory for backend selection (renderer/renderer.c) - Updated Makefile to include renderer modules The renderer abstraction provides: - Texture management (create, destroy, bind) - Frame management (begin, end, present) - Shader program compilation and uniform management - Capability querying for feature detection - Support for blur effects and vsync control Note: The renderer is not yet integrated with the main application. This maintains compilation but doesn't change runtime behavior yet. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: Implement platform abstraction - Phase 2 Create a platform abstraction layer to decouple windowing system operations from the main application, enabling support for different platforms beyond Wayland. This commit implements Phase 2 of the modularization plan: - Created platform interface (include/platform.h) with operations struct - Implemented Wayland platform backend (platform/wayland.c) - Added X11 platform stub for future implementation (platform/x11.c) - Added platform factory with auto-detection (platform/platform.c) - Updated Makefile to include platform modules The platform abstraction provides: - Connection management (connect, disconnect, status) - Window management (create, destroy, show, hide) - Event handling (poll, wait, flush) - Native handle access for renderer integration - Platform capability detection (transparency, blur support) - Auto-detection of best available platform Platform detection uses environment variables: - Checks WAYLAND_DISPLAY and XDG_SESSION_TYPE for Wayland - Checks DISPLAY and XDG_SESSION_TYPE for X11 - Defaults to Wayland if nothing detected Note: The platform layer is not yet integrated with the main application. Shell-specific code will be moved to compositor adapters in Phase 3. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: Implement compositor adapters - Phase 3 Create compositor-specific adapters to abstract IPC and features across different Wayland compositors and X11 window managers. This commit implements Phase 3 of the modularization plan: - Created compositor interface (include/compositor.h) with operations struct - Implemented Hyprland adapter with IPC support (compositor/hyprland.c) - Added Sway adapter stub with i3-compatible IPC (compositor/sway.c) - Added generic Wayland adapter for wlr-layer-shell (compositor/generic_wayland.c) - Added X11/EWMH adapter stub for future support (compositor/x11_ewmh.c) - Added compositor factory with auto-detection (compositor/compositor.c) - Updated Makefile to include compositor modules The compositor abstraction provides: - Layer surface management (create, configure, destroy) - Workspace management (current, count, list) - Monitor management (current, list with properties) - IPC communication (connect, disconnect, send commands) - Event polling for workspace/monitor changes - Feature detection (blur, transparency, animations) - Compositor-specific optimizations Compositor detection order: 1. Hyprland (via HYPRLAND_INSTANCE_SIGNATURE) 2. Sway (via SWAYSOCK or XDG_CURRENT_DESKTOP) 3. X11/EWMH (via DISPLAY) 4. Generic Wayland (fallback for any wlr-layer-shell compositor) Note: Adapters are not yet integrated with the main application. The modular architecture now spans core, renderer, platform, and compositor layers. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: Implement runtime switching - Phase 4 Wire together all modular components into a working application with runtime backend selection and dynamic compositor detection. This commit implements Phase 4 of the modularization plan: - Created main application context (include/hyprlax.h) - Implemented integration module (hyprlax_main.c) tying all modules together - Added simple entry point (main.c) using the modular system - Updated Makefile to support both legacy and modular builds - Added command-line backend selection options: * --renderer <backend>: Choose renderer (gles2, auto) * --platform <backend>: Choose platform (wayland, x11, auto) * --compositor <backend>: Choose compositor (hyprland, sway, generic, auto) The integration provides: - Proper initialization chain (platform → compositor → window → renderer) - Unified command-line argument parsing - Backend auto-detection with manual override - Event handling from both platform and compositor layers - Animation updates using core modules - Clean shutdown sequence Key improvements: - Binary size reduced from 217KB to 55KB (75% smaller!) - Modular architecture allows easy addition of new backends - Runtime selection enables single binary for all environments - Maintains backward compatibility through USE_LEGACY=1 make flag The application now supports: - Multiple compositors: Hyprland, Sway, generic Wayland, X11/EWMH (stub) - Multiple platforms: Wayland, X11 (stub) - Multiple renderers: OpenGL ES 2.0 (more can be added) Usage: ./hyprlax [OPTIONS] [--layer <image:shift:opacity:blur>...] ./hyprlax --compositor sway --debug ./hyprlax --platform x11 --renderer gl3 # Future support 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * Wire everything together, fix broken tests * address review comments * add more compositors, update docs, update tests * missing tests * add more granular tets * Update tests/test_config_validation.c Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * add runtime controls to ctr command (hyprlax ctl) and respective docs/tests * fix memcheck errors * address review comments * add sections to website, switch to component model, finish x11 platform (no longer just a stub) * add gif to readme * add pre-release workflow * fix wf * fix prelease assets * add readiness check * add single instance protection, add IPC connection retries to all compositors * fix stdout/stder crash when closed condition * add new docs * add first phase of multi-monitor support * feat: Add multi and space example configurations Add example parallax configurations for testing multi-monitor support: - examples/multi/: Mountain scene with multiple layers - examples/space/: Space scene with 8 parallax layers 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com> * add window context abstraction to support different workspace methodologies, multi-monitors onm wayland should work * add feature branch builds and bot to link to binaries. * add workflow dispatch trigger to feature build * simply rendering logic, single path for all monitor configs, add feature flags for custom builds * code formatting and added better messages to integration tests * chore: bump version to v2.0.0-beta.2 Prepare for beta.2 pre-release with PR review fixes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * remove X11 platform support * [bugfix] parallax inconsistency and unexpected mouse behaviors (#21) * remove focus event handling, improve tests * fix linter errors --------- Co-authored-by: sandwich <dskvr@users.noreply.github.com> * implement niri parallax correctly * finish and correfct delta calculations * fix lagging state bug caused by multi-state tracking * remove all state tracking from Niri compositor adapter, fix bugs in core monitor.c * fix tests * appease linter * fix: remove hyprlax-ctl references from workflows The hyprlax-ctl standalone binary is no longer built in the refactor. Control functionality is now integrated into the main hyprlax binary. * single source of truth for version * update release procedure and feature branch workflow * River, working on single monitor setup (#44) Co-authored-by: sandwich <dskvr@users.noreply.github.com> * Niri Support (#41) * implement niri parallax correctly * finish and correfct delta calculations * fix lagging state bug caused by multi-state tracking * remove all state tracking from Niri compositor adapter, fix bugs in core monitor.c * fix tests * appease linter --------- Co-authored-by: sandwich <dskvr@users.noreply.github.com> * Performance Optimizations (#46) * Performance optimization: Implement smart rendering to fix 100% GPU usage - Add animation state tracking to only render when needed - Implement proper frame limiting with separate render and update timers - Skip rendering when no animations are active (idle state) - Increase sleep time to 100ms when idle (10 FPS polling) - Only update animations when they're actually active - Add needs_render flag for events that require re-rendering - Properly separate frame timing from render timing This should dramatically reduce GPU usage when the wallpaper is static. * Further GPU optimization: Disable VSync by default and increase idle polling interval - VSync now defaults to off to prevent GPU blocking when idle - Made VSync configurable via command line (--vsync) and config file - Increased idle polling interval from 100ms to 500ms (2 FPS when idle) - GPU should no longer block on eglSwapBuffers when idle - This should significantly reduce GPU power consumption when static The VSync blocking was causing the GPU to stay active even when no frames were being rendered. With VSync off by default and longer idle sleep times, the GPU can properly enter low power states. * Critical fix: GPU now properly returns to idle after animations complete The issue was that after animations completed, the render loop would get stuck in an infinite rendering state due to incorrect flag management. Problems fixed: 1. needs_render flag was not being properly cleared after rendering 2. Animation completion was checked at the wrong time in the loop 3. The final frame of animation wasn't guaranteed to be rendered Changes: - Clear needs_render flag after each render (it gets re-set if needed) - Re-check animation state AFTER updating animations, not just before - Ensure one final frame is rendered when animations complete - Properly update animation state flags for next iteration This fixes the bug where GPU would stay at 140W+ and P2 state after workspace changes, instead of returning to 32W and P8 idle state. * Fix sleep timing bug that prevented proper idle after animations The issue was in the sleep time calculation. After animations completed, we were still calculating sleep_time based on last_render_time + frame_time, but time_since_render kept growing, making sleep_time negative or very small. This prevented proper sleeping and kept the GPU active. Fix: - Only calculate frame-based sleep timing when actively rendering - When idle, use a fixed 500ms sleep time directly - This ensures we actually sleep when idle, allowing GPU to power down * Fix FPS being capped at 30 during animations The issue was that needs_render was only set once per loop iteration, causing unnecessary delays between frames during animations. Fix: - Set needs_render = true immediately when animations are active - This ensures we render as soon as frame_time has elapsed - Simplified the render flag logic to avoid double-checking Now animations should run at the configured FPS (60/144) instead of 30. * CRITICAL FIX: Animations were running forever due to unit mismatch The monitor animation duration was being multiplied by 1000 (converting to milliseconds) but compared against elapsed time in seconds. This meant a 4 second animation would take 4000 seconds (over an hour) to complete! This caused: - Animations to run forever at 60 FPS - GPU stuck at 350W+ power consumption - GPU utilization at 65-67% continuously Fixed by keeping both elapsed time and duration in seconds. * Fix additional animation timing bugs - Use get_time() directly instead of ctx->last_frame_time for animation start - Remove another instance of * 1000.0 ms conversion bug - Animations now properly use current time for calculations However, there's still an issue with animations not fully stopping or restarting after completion. * SUCCESS: All performance issues fixed! Animations now properly complete and GPU returns to idle power. Test results: - Baseline (no hyprlax): 42W - Hyprlax idle: 42W - During animation: 350W (expected for 4K rendering) - Post-animation: Returns to 30-33W within 4 seconds Key fixes applied: 1. Smart rendering - only render when needed 2. Fixed animation duration bugs (ms vs seconds) 3. Proper idle detection and sleep timing 4. VSync off by default to prevent GPU blocking 5. Correct time calculations using get_time() The GPU now properly idles at low power when no animations are active! * Additional performance optimizations - Increased idle sleep time from 500ms to 1s (reduces polling overhead) - Added glFinish() before buffer swap to ensure GPU work completes - This may help with frame timing consistency These changes further reduce CPU/GPU usage when idle while maintaining smooth animations when active. * Add configurable idle polling frequency - Added --idle-poll-rate command line option with validation - Added idle_poll_rate config file option - Default value is 2.0 Hz (500ms) for balanced responsiveness - Valid range is 0.1 to 10.0 Hz with automatic fallback to default - Shows the rate in debug output as both Hz and milliseconds - Replaces hardcoded 1-second idle sleep with configurable rate 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * low hanging fruit * glex optimizations * further trims * add benchmark scripts + further optimizations * add frame callbacks * add per-monitor frame profiling * add separable blur and blur downscaling * add diagnostics * update becnhmark scripts to be configurable --------- Co-authored-by: sandwich <dskvr@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com> * add event driven rendering from idle instead of poll * add smoke tests for get_event_fd in compositors * Parallax Modes: Cursor Tracking, TOML Config (#48) * feat: mouse-parallax modes + renderer/Wayland hardening (clean rebase onto feature/refactor) * Add River/Niri support. Add smoke tests and reduce verbosity of debug log, add trace level. * last commit broke everything, commit stash * track down regression and fix (cause was mixture of enums and ints on log level) --------- Co-authored-by: sandwich <dskvr@users.noreply.github.com> * Hierarchical documentation restructure (#51) * docs: restructure documentation to hierarchical layout - Create hierarchical directory structure for better organization - Split large documents into focused, manageable files - Add comprehensive reference documentation for CLI, IPC, and environment vars - Create dedicated sections for different audiences (users, developers) - Add new guides for cursor tracking and performance optimization - Improve configuration documentation with TOML reference and migration guide - Separate build, architecture, contributing, and testing documentation - Add quick-start guide and compatibility matrix for new users The new structure provides: - Easier navigation with clear categorization - Faster reference lookups with dedicated reference section - Better separation between user and developer documentation - More maintainable, focused documents - Progressive disclosure (simple -> detailed) * fix accuracy of docs --------- Co-authored-by: sandwich <dskvr@users.noreply.github.com> * Fix IPC (#53) * docs: restructure documentation to hierarchical layout - Create hierarchical directory structure for better organization - Split large documents into focused, manageable files - Add comprehensive reference documentation for CLI, IPC, and environment vars - Create dedicated sections for different audiences (users, developers) - Add new guides for cursor tracking and performance optimization - Improve configuration documentation with TOML reference and migration guide - Separate build, architecture, contributing, and testing documentation - Add quick-start guide and compatibility matrix for new users The new structure provides: - Easier navigation with clear categorization - Faster reference lookups with dedicated reference section - Better separation between user and developer documentation - More maintainable, focused documents - Progressive disclosure (simple -> detailed) * fix accuracy of docs * complete phase 1 ipc refactor * IPC refactor continued * fix logging inconsistencies and auto assign z-index * refresh image data in layer * pre gpu fixes * found it --------- Co-authored-by: sandwich <dskvr@users.noreply.github.com> * move time to middle layer * Cherry blossom with time example (#55) * add --only-image flag to py script * functional clock * add global json flag for json output of hyprlax ctl returns and fix time script --------- Co-authored-by: sandwich <dskvr@users.noreply.github.com> * AUR (#54) * feat(aur): add hyprlax-git PKGBUILD and AUR docs * docs(aur): add AUR install instructions; add Arch PKGBUILD for hyprlax-git * appease linter * ci(aur): add release-only AUR publish workflow; add stable PKGBUILD template --------- Co-authored-by: sandwich <dskvr@users.noreply.github.com> * Feature/align config keys (#56) * add --only-image flag to py script * functional clock * add global json flag for json output of hyprlax ctl returns and fix time script * First pass on canonical config keys * map ENV keys and update documentation * improve usability with better outputs, help menus and documentation. * improve usability with better outputs, help menus and documentation. * update cherry-blossom example with new keys --------- Co-authored-by: sandwich <dskvr@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com> * fix regressions from claude's conflict resolution (#57) Co-authored-by: sandwich <dskvr@users.noreply.github.com> * Layer Tint (#58) * fix IPC tint + help menu * tint with blur * fix linker errors --------- Co-authored-by: sandwich <dskvr@users.noreply.github.com> * Final Cleanup Pass (#61) * remove legacy path and add capability bits to adapters * complete modularization. fully decoupled. DRY af * fix frame accumulation * add freeze frame config * update tests --------- Co-authored-by: sandwich <dskvr@users.noreply.github.com> * Input mode refactor, more flexiblity, new input mode, implicit hybrid (#62) * add design documents * add scaffolding for core input manager and wire up new input controls to core render pipeline * input selection and parsing * update input plumbing so all inputs drive same selector * port niri/river to new input system, update tests and docs * add window input mode * update confs and tests --------- Co-authored-by: sandwich <dskvr@users.noreply.github.com> * fix animation loop delays * update example docs and SPA --------- Co-authored-by: sandwich <dskvr@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent c8e28f9 commit 124f575

262 files changed

Lines changed: 39004 additions & 2372 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/aur-release.yml

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
name: Publish AUR (hyprlax)
2+
3+
on:
4+
release:
5+
types: [published]
6+
7+
jobs:
8+
aur:
9+
if: ${{ github.event.release.prerelease == false }}
10+
runs-on: ubuntu-latest
11+
container: archlinux:base-devel
12+
steps:
13+
- name: Install tools
14+
run: |
15+
pacman -Syu --noconfirm git openssh wget sed which base-devel wayland wayland-protocols
16+
17+
- name: Checkout repository
18+
uses: actions/checkout@v4
19+
20+
- name: Prepare PKGBUILD for release tag
21+
id: prep
22+
env:
23+
TAG: ${{ github.event.release.tag_name }}
24+
run: |
25+
set -euo pipefail
26+
if [[ -z "${TAG:-}" ]]; then echo "Missing tag"; exit 1; fi
27+
PKGVER="${TAG#v}"
28+
echo "pkgver=${PKGVER}" >> "$GITHUB_OUTPUT"
29+
WORKDIR=/tmp/aur-hyprlax
30+
mkdir -p "$WORKDIR"
31+
cp packaging/arch/hyprlax/PKGBUILD "$WORKDIR/PKGBUILD"
32+
# Update pkgver in PKGBUILD
33+
sed -i "s/^pkgver=.*/pkgver=${PKGVER}/" "$WORKDIR/PKGBUILD"
34+
# Fetch source tarball and compute sha256
35+
TARBALL_URL="https://github.com/sandwichfarm/hyprlax/archive/refs/tags/${TAG}.tar.gz"
36+
wget -O /tmp/src.tar.gz "$TARBALL_URL"
37+
SHA256=$(sha256sum /tmp/src.tar.gz | awk '{print $1}')
38+
# Ensure source filename has v${pkgver}
39+
sed -i "s|^source=.*|source=(\"hyprlax-v${PKGVER}.tar.gz::${TARBALL_URL}\")|" "$WORKDIR/PKGBUILD"
40+
sed -i "s/^sha256sums=.*/sha256sums=('${SHA256}')/" "$WORKDIR/PKGBUILD"
41+
# Generate .SRCINFO
42+
cd "$WORKDIR"
43+
makepkg --printsrcinfo > .SRCINFO
44+
ls -la
45+
46+
- name: Configure SSH for AUR
47+
env:
48+
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
49+
run: |
50+
set -euo pipefail
51+
if [[ -z "${AUR_SSH_PRIVATE_KEY:-}" ]]; then
52+
echo "AUR_SSH_PRIVATE_KEY secret is not set" >&2
53+
exit 1
54+
fi
55+
install -m 700 -d ~/.ssh
56+
echo "$AUR_SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519
57+
chmod 600 ~/.ssh/id_ed25519
58+
ssh-keyscan -t ed25519 aur.archlinux.org >> ~/.ssh/known_hosts
59+
60+
- name: Push to AUR (hyprlax)
61+
env:
62+
PKGDIR: /tmp/aur-hyprlax
63+
run: |
64+
set -euo pipefail
65+
cd /tmp
66+
git clone ssh://aur@aur.archlinux.org/hyprlax.git aur-hyprlax-repo
67+
cd aur-hyprlax-repo
68+
# Copy updated files
69+
cp -f "$PKGDIR/PKGBUILD" "$PKGDIR/.SRCINFO" .
70+
if git diff --quiet --no-index . "$PKGDIR"; then
71+
echo "No changes to push to AUR"
72+
exit 0
73+
fi
74+
git config user.name "github-actions"
75+
git config user.email "actions@github.com"
76+
git add PKGBUILD .SRCINFO
77+
git commit -m "release: ${GITHUB_REF#refs/tags/}"
78+
git push
79+
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: Feature Build Cleanup
2+
3+
on:
4+
pull_request:
5+
types: [converted_to_draft, closed]
6+
7+
jobs:
8+
cleanup-comment:
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
- name: Remove build artifact comment
13+
uses: actions/github-script@v7
14+
with:
15+
github-token: ${{ secrets.GITHUB_TOKEN }}
16+
script: |
17+
const comments = await github.rest.issues.listComments({
18+
owner: context.repo.owner,
19+
repo: context.repo.repo,
20+
issue_number: context.issue.number
21+
});
22+
23+
const botComment = comments.data.find(comment =>
24+
comment.user.type === 'Bot' &&
25+
comment.body.includes('🤖 **Build Artifact Available**')
26+
);
27+
28+
if (botComment) {
29+
const eventType = context.payload.action;
30+
let updateBody = '';
31+
32+
if (eventType === 'converted_to_draft') {
33+
updateBody = `🤖 **Build Artifact Paused**
34+
35+
This PR has been converted to draft. Build artifacts are only generated for PRs ready for review.
36+
37+
Mark this PR as "Ready for review" to generate a new build artifact.`;
38+
} else if (eventType === 'closed') {
39+
updateBody = `🤖 **Build Artifact Expired**
40+
41+
This PR has been closed. The build artifact links above may no longer work.`;
42+
}
43+
44+
if (updateBody) {
45+
await github.rest.issues.updateComment({
46+
owner: context.repo.owner,
47+
repo: context.repo.repo,
48+
comment_id: botComment.id,
49+
body: updateBody
50+
});
51+
}
52+
}

.github/workflows/feature-build.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,20 @@ jobs:
8989
libwayland-dev \
9090
libegl1-mesa-dev \
9191
libgles2-mesa-dev \
92-
libx11-dev \
93-
libxext-dev \
9492
wayland-scanner++ \
9593
pkg-config
9694
95+
- name: Generate VERSION file
96+
if: steps.pr_info.outputs.skip != 'true'
97+
run: |
98+
# Sanitize branch name (replace / with -)
99+
BRANCH_NAME=$(echo "${{ steps.pr_info.outputs.head_ref }}" | sed 's/\//-/g')
100+
# Get short commit hash
101+
SHORT_SHA=$(echo "${{ steps.pr_info.outputs.head_sha }}" | cut -c1-7)
102+
# Create VERSION file with branch-commit format
103+
echo "${BRANCH_NAME}-${SHORT_SHA}" > VERSION
104+
echo "Generated version: $(cat VERSION)"
105+
97106
- name: Build hyprlax
98107
if: steps.pr_info.outputs.skip != 'true'
99108
run: |

.github/workflows/pre-release.yml

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -62,19 +62,17 @@ jobs:
6262
wayland-protocols \
6363
libegl1-mesa-dev \
6464
libgles2-mesa-dev \
65-
libx11-dev \
66-
libxext-dev \
6765
check
6866
6967
- name: Build binary
7068
env:
7169
CC: ${{ matrix.cc }}
7270
ARCH: ${{ matrix.arch }}
7371
run: |
74-
# Add pre-release version info to build
75-
VERSION=${{ github.ref_name }}
72+
# Extract version from tag (remove 'v' prefix)
73+
VERSION="${GITHUB_REF_NAME#v}"
74+
echo "$VERSION" > VERSION
7675
echo "Building pre-release version: $VERSION"
77-
echo "#define HYPRLAX_VERSION \"$VERSION-PRE\"" > src/version.h
7876
7977
make clean
8078
make
@@ -88,21 +86,14 @@ jobs:
8886
run: |
8987
# Rename binaries to match release workflow naming
9088
mv hyprlax hyprlax-${{ matrix.arch }}
91-
mv hyprlax-ctl hyprlax-ctl-${{ matrix.arch }}
9289
chmod +x hyprlax-${{ matrix.arch }}
93-
chmod +x hyprlax-ctl-${{ matrix.arch }}
9490
9591
- name: Upload hyprlax artifact
9692
uses: actions/upload-artifact@v4
9793
with:
9894
name: hyprlax-${{ matrix.arch }}
9995
path: hyprlax-${{ matrix.arch }}
10096

101-
- name: Upload hyprlax-ctl artifact
102-
uses: actions/upload-artifact@v4
103-
with:
104-
name: hyprlax-ctl-${{ matrix.arch }}
105-
path: hyprlax-ctl-${{ matrix.arch }}
10697

10798
create-pre-release:
10899
needs: [validate-branch, build-pre-release]
@@ -187,20 +178,17 @@ jobs:
187178
### 🔧 Installation (Testing Only)
188179
189180
\`\`\`bash
190-
# Download binaries
181+
# Download binary
191182
wget https://github.com/sandwichfarm/hyprlax/releases/download/${VERSION}/hyprlax-x86_64
192-
wget https://github.com/sandwichfarm/hyprlax/releases/download/${VERSION}/hyprlax-ctl-x86_64
193183
194184
# Make executable and install (at your own risk)
195-
chmod +x hyprlax-x86_64 hyprlax-ctl-x86_64
185+
chmod +x hyprlax-x86_64
196186
sudo mv hyprlax-x86_64 /usr/local/bin/hyprlax
197-
sudo mv hyprlax-ctl-x86_64 /usr/local/bin/hyprlax-ctl
198187
\`\`\`
199188
200189
### 📦 Available Builds
201190
202191
- \`hyprlax-x86_64\` - Main hyprlax binary for Intel/AMD 64-bit
203-
- \`hyprlax-ctl-x86_64\` - Control client for Intel/AMD 64-bit
204192
205193
*Note: ARM64 builds not available for pre-releases. Please build from source.*
206194
@@ -245,7 +233,6 @@ jobs:
245233
prerelease: true # ALWAYS true for pre-releases
246234
files: |
247235
hyprlax-x86_64
248-
hyprlax-ctl-x86_64
249236
SHA256SUMS
250237
fail_on_unmatched_files: true
251238
generate_release_notes: false # We generate our own

.github/workflows/release.yml

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,40 @@ name: Release
33
on:
44
push:
55
tags:
6-
- 'v*'
6+
# Only match stable version tags (no dash)
7+
# v1.0.0, v2.1.3 etc. (NOT v1.0.0-beta.1)
8+
- 'v[0-9]+.[0-9]+.[0-9]+'
79

810
permissions:
911
contents: write
1012

1113
jobs:
14+
validate-branch:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v4
19+
with:
20+
fetch-depth: 0
21+
22+
- name: Validate tag is from master
23+
run: |
24+
# Get the branch containing this tag
25+
BRANCH=$(git branch -r --contains ${{ github.ref_name }} | grep -v HEAD | head -1 | sed 's/.*origin\///')
26+
echo "Stable release tag ${{ github.ref_name }} is on branch: $BRANCH"
27+
28+
# Stable releases must be from master branch
29+
if [[ "$BRANCH" != "master" ]] && [[ "$BRANCH" != "main" ]]; then
30+
echo "::error::Stable release tags must be created from master/main branch!"
31+
echo "Current branch is: $BRANCH"
32+
echo "For pre-releases from feature branches, use version tags like v1.0.0-beta.1"
33+
exit 1
34+
fi
35+
36+
echo "✅ Stable release tag is correctly on master/main branch"
37+
1238
build:
39+
needs: validate-branch
1340
strategy:
1441
matrix:
1542
include:
@@ -34,6 +61,13 @@ jobs:
3461
pkg-config \
3562
make
3663
64+
- name: Write VERSION file from tag
65+
run: |
66+
# Extract version from tag (remove 'v' prefix)
67+
VERSION="${GITHUB_REF_NAME#v}"
68+
echo "$VERSION" > VERSION
69+
echo "Building version: $VERSION"
70+
3771
- name: Build
3872
env:
3973
CC: ${{ matrix.cc }}
@@ -45,26 +79,17 @@ jobs:
4579
id: binary
4680
run: |
4781
echo "hyprlax_name=hyprlax-${{ matrix.arch }}" >> $GITHUB_OUTPUT
48-
echo "ctl_name=hyprlax-ctl-${{ matrix.arch }}" >> $GITHUB_OUTPUT
4982
50-
- name: Rename binaries
83+
- name: Rename binary
5184
run: |
5285
mv hyprlax ${{ steps.binary.outputs.hyprlax_name }}
53-
mv hyprlax-ctl ${{ steps.binary.outputs.ctl_name }}
5486
chmod +x ${{ steps.binary.outputs.hyprlax_name }}
55-
chmod +x ${{ steps.binary.outputs.ctl_name }}
5687
5788
- name: Upload hyprlax artifact
5889
uses: actions/upload-artifact@v4
5990
with:
6091
name: ${{ steps.binary.outputs.hyprlax_name }}
6192
path: ${{ steps.binary.outputs.hyprlax_name }}
62-
63-
- name: Upload hyprlax-ctl artifact
64-
uses: actions/upload-artifact@v4
65-
with:
66-
name: ${{ steps.binary.outputs.ctl_name }}
67-
path: ${{ steps.binary.outputs.ctl_name }}
6893

6994
release:
7095
needs: build
@@ -84,17 +109,12 @@ jobs:
84109
# Move all binaries to root
85110
find ./binaries -type f -name 'hyprlax-*' -exec mv {} . \;
86111
87-
# Check if we have the x86_64 binaries
112+
# Check if we have the x86_64 binary
88113
if [ ! -f hyprlax-x86_64 ]; then
89114
echo "Error: hyprlax-x86_64 binary not found!"
90115
exit 1
91116
fi
92117
93-
if [ ! -f hyprlax-ctl-x86_64 ]; then
94-
echo "Error: hyprlax-ctl-x86_64 binary not found!"
95-
exit 1
96-
fi
97-
98118
# Create checksums
99119
sha256sum hyprlax-* > SHA256SUMS
100120
@@ -127,25 +147,24 @@ jobs:
127147
body: |
128148
## Release ${{ steps.version.outputs.version }}
129149
130-
Smooth parallax wallpaper animations for Hyprland.
150+
Multi-compositor parallax wallpaper engine for Linux.
131151
132152
### Installation
133153
134-
Download the binaries:
135-
- `hyprlax-x86_64` - Main hyprlax binary for x86_64 systems
136-
- `hyprlax-ctl-x86_64` - Control client for x86_64 systems
154+
Download the binary:
155+
- `hyprlax-x86_64` - hyprlax binary for x86_64 systems (control interface integrated)
137156
138157
```bash
139-
# Download both binaries
158+
# Download binary
140159
wget https://github.com/${{ github.repository }}/releases/download/${{ steps.version.outputs.version }}/hyprlax-x86_64
141-
wget https://github.com/${{ github.repository }}/releases/download/${{ steps.version.outputs.version }}/hyprlax-ctl-x86_64
142160
143161
# Make executable and install
144-
chmod +x hyprlax-x86_64 hyprlax-ctl-x86_64
162+
chmod +x hyprlax-x86_64
145163
sudo mv hyprlax-x86_64 /usr/local/bin/hyprlax
146-
sudo mv hyprlax-ctl-x86_64 /usr/local/bin/hyprlax-ctl
147164
```
148165
166+
**Note:** The control interface is now integrated. Use `hyprlax ctl <command>` for runtime control.
167+
149168
For ARM64 and other architectures, please build from source.
150169
151170
### Changes
@@ -158,7 +177,6 @@ jobs:
158177
159178
files: |
160179
hyprlax-x86_64
161-
hyprlax-ctl-x86_64
162180
SHA256SUMS
163181
draft: false
164182
prerelease: ${{ contains(steps.version.outputs.version, '-') }}

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ jobs:
110110
--suppress=unusedFunction \
111111
--suppress=constVariablePointer \
112112
--inline-suppr \
113-
src/ipc.c src/hyprlax-ctl.c
113+
src/ipc.c src/hyprlax_ctl.c
114114
115115
- name: Check code formatting
116116
run: |

0 commit comments

Comments
 (0)