Cursor Tracking Guide¶
Create interactive parallax effects that respond to mouse movement.
Overview¶
Cursor-driven parallax makes layers shift based on mouse position, creating an immersive depth effect that follows user focus.
Quick Start¶
Basic Setup¶
[global.parallax]
input = "cursor"
[global.input.cursor]
sensitivity_x = 1.0
sensitivity_y = 1.0
[[global.layers]]
path = "background.jpg"
shift_multiplier = 0.5
[[global.layers]]
path = "foreground.png"
shift_multiplier = 1.0
Parallax Inputs¶
Cursor-Only Mode¶
Layers move only with mouse movement:
[global.parallax]
input = "cursor"
Blended Inputs¶
Combine workspace and cursor movement:
[global.parallax]
input = ["workspace", "cursor:0.3"] # 30% cursor influence
Workspace-Only Mode (Traditional)¶
Disable cursor tracking:
[global.parallax]
input = "workspace"
Cursor Input Settings¶
Sensitivity¶
Control how much layers move relative to cursor:
[global.input.cursor]
sensitivity_x = 1.0 # 1.0 = normal, 2.0 = double movement
sensitivity_y = 0.5 # Reduce vertical sensitivity
Dead Zone¶
Ignore small cursor movements:
[global.input.cursor]
deadzone_px = 5 # Ignore movements under 5 pixels
Smoothing¶
Smooth cursor movement with exponential moving average:
[global.input.cursor]
ema_alpha = 0.25 # 0.0 = max smoothing, 1.0 = no smoothing
Lower values create smoother, more delayed movement.
Animation¶
Animate cursor-driven changes:
[global.input.cursor]
animation_duration = 3.0 # Seconds to animate position changes
easing = "expo" # Easing function for cursor animation
Normalization¶
Note: Cursor normalization targets are currently fixed; normalize_to is reserved and not configurable in this build.
Movement Control¶
Invert Movement¶
Make layers move opposite to cursor:
[global.parallax.invert.cursor]
x = true # Layers move left when cursor moves right
y = false # Normal vertical movement
Limit Movement Range¶
Prevent excessive parallax:
[global.parallax.max_offset_px]
x = 300 # Maximum 300px horizontal shift
y = 150 # Maximum 150px vertical shift
Per-Layer Control¶
Different Speeds per Axis¶
[[global.layers]]
path = "clouds.png"
shift_multiplier = { x = 2.0, y = 0.5 } # Fast horizontal, slow vertical
Layer-Specific Settings¶
[[global.layers]]
path = "background.jpg"
shift_multiplier = 0.3 # Slow movement
scale = 1.3 # Overscale to hide edges during movement
[[global.layers]]
path = "midground.png"
shift_multiplier = 0.7
scale = 1.15
[[global.layers]]
path = "foreground.png"
shift_multiplier = 1.2 # Moves faster than cursor
scale = 1.0
Effect Examples¶
Depth Focus Effect¶
Objects appear to shift based on depth:
[global.parallax]
input = "cursor"
[global.input.cursor]
sensitivity_x = 0.8
sensitivity_y = 0.6
ema_alpha = 0.2
[[global.layers]]
path = "far_mountains.jpg"
shift_multiplier = 0.2
blur = 3.0
[[global.layers]]
path = "trees.png"
shift_multiplier = 0.6
blur = 1.0
[[global.layers]]
path = "character.png"
shift_multiplier = 1.0
blur = 0.0
Floating Elements¶
UI elements that subtly follow cursor:
[global.input.cursor]
sensitivity_x = 0.3
sensitivity_y = 0.3
ema_alpha = 0.1 # Very smooth
animation_duration = 5.0
easing = "sine"
[[global.layers]]
path = "ui_element.png"
shift_multiplier = { x = 1.0, y = 0.5 }
Tilt Effect¶
Simulate 3D card tilt:
[global.parallax.invert.cursor]
x = true
y = true
[global.input.cursor]
sensitivity_x = 0.5
sensitivity_y = 0.5
[[global.layers]]
path = "card_shadow.png"
shift_multiplier = { x = -0.3, y = -0.3 }
opacity = 0.5
[[global.layers]]
path = "card.png"
shift_multiplier = 0.0 # Card itself doesn't move
[[global.layers]]
path = "card_shine.png"
shift_multiplier = { x = 0.5, y = 0.5 }
opacity = 0.7
Performance Optimization¶
Reduce Smoothing¶
Less smoothing = less calculation:
ema_alpha = 0.5 # Less smooth but more responsive
Limit Refresh Rate¶
[global]
fps = 60 # Lower FPS for battery savings
Disable Animation¶
animation_duration = 0.0 # Instant movement
Multi-Monitor Considerations¶
Consistent Behavior¶
Use canvas normalization for uniform behavior:
[global.input.cursor]
follow_global = true
Per-Monitor Settings¶
Different sensitivities based on monitor size:
# For 4K monitor (needs less sensitivity)
sensitivity_x = 0.5
sensitivity_y = 0.5
# For 1080p monitor (needs more sensitivity)
sensitivity_x = 1.2
sensitivity_y = 1.2
Troubleshooting¶
Cursor Not Tracked¶
- Check compositor supports cursor position reporting
- Verify
parallax.inputincludes cursor, e.g.,"cursor"or"workspace,cursor:0.3"
- Verify
- Run with
--debugto see cursor position
Jittery Movement¶
- Increase smoothing:
ema_alpha = 0.1 - Add dead zone:
deadzone_px = 3 - Increase animation duration
Too Much/Little Movement¶
- Adjust sensitivity values
- Modify shift_multiplier per layer
- Set max_offset_px limits
CPU Usage High¶
- Lower FPS:
fps = 30 - Reduce smoothing:
ema_alpha = 0.5 - Use fewer layers
Testing Configuration¶
# Test with debug output
HYPRLAX_DEBUG=1 hyprlax --config cursor-config.toml --debug
Complete Example¶
# Interactive desktop with cursor parallax
[global]
fps = 144
vsync = true
debug = false
[global.parallax]
input = "cursor"
[global.parallax.invert.cursor]
x = false
y = false
[global.parallax.max_offset_px]
x = 400
y = 200
[global.input.cursor]
follow_global = true
sensitivity_x = 1.0
sensitivity_y = 0.7
deadzone_px = 2
ema_alpha = 0.25
animation_duration = 2.5
easing = "expo"
# Sky - barely moves
[[global.layers]]
path = "~/wallpapers/sky.jpg"
shift_multiplier = 0.1
scale = 1.3
blur = 2.0
fit = "cover"
# Mountains - slow movement
[[global.layers]]
path = "~/wallpapers/mountains.png"
shift_multiplier = 0.3
scale = 1.2
blur = 1.0
fit = "cover"
# Forest - medium movement
[[global.layers]]
path = "~/wallpapers/forest.png"
shift_multiplier = 0.6
scale = 1.15
blur = 0.5
fit = "cover"
# Foreground - full movement
[[global.layers]]
path = "~/wallpapers/foreground.png"
shift_multiplier = 1.0
scale = 1.1
blur = 0.0
fit = "cover"
# UI overlay - moves opposite for depth
[[global.layers]]
path = "~/wallpapers/ui_overlay.png"
shift_multiplier = { x = -0.2, y = -0.1 }
opacity = 0.8
fit = "contain"
align = { x = 0.5, y = 0.5 }