Tech HUD Eyecandy & Ripples
===========================

Simple Description (for everyone)
----------------------------------
Tech HUD Eyecandy is a small set of transparent desktop overlay windows for Linux that make your desktop look like a sci-fi movie interface.

You can place one or more windows anywhere on your screen. Each window can show:

- Animated starfields (slowly drifting stars)
- Falling data streams (Matrix-like)
- Crawling border lights that run around the window frame
- Inner crawlers and Tetris-style waypoint animations
- A customizable background – either a picture you drag & drop, or a solid color with a theme gradient

The windows are click-through, always-on-top (or below), sticky across workspaces, and you can save their position, size, border style and theme. Everything is managed from a central Manager dialog where you can create new windows, edit existing ones, or quit.

There is a second program called Tech HUD Ripples. It looks similar but adds a realistic water-ripple simulation:

- Raindrops fall from the top and create expanding ripples
- Moving your mouse creates a trail of waves
- A soft subsurface drift (mu-waves) slowly sways the whole surface
- Shoreline waves appear at the bottom of the window
- All ripples can be tinted with your theme color

Why two programs?

The ripple simulation is very CPU heavy. It constantly calculates a height field and distorts the background image pixel by pixel. Even with Low-Res Mode (2x faster, half resolution) and a GPU fast-path, it uses much more CPU than the simple eyecandy animations.

To keep your desktop smooth, the project is split:

1) tech-hud-eyecandy – lightweight, many windows possible, very low CPU
2) tech-hud-ripples – heavy water simulation, best used with only 1-2 windows, with Low-Res Mode enabled by default

You can run both at the same time, or only one of them.

License: GPL v2 or later

You are free to use, modify and redistribute this program under the terms of the GNU General Public License version 2 or any later version. See COPYING or https://www.gnu.org/licenses/gpl-2.0.html

---
Technical Details
-----------------

Files:
- tech_hud_eyecandy.vala / tech-hud-eyecandy – the lightweight version
- tech_hud_ripples.vala / tech-hud-ripples – the ripple version with full configuration
- Makefile builds both with valac

Dependencies (build):
valac, gtk+-3.0, cairo, pangocairo, gio-2.0, gee-0.8
  sudo apt install valac libgtk-3-dev libcairo2-dev libpango1.0-dev libgee-0.8-dev

Build & Run:
  make
  ./tech-hud-eyecandy
  ./tech-hud-ripples
Config is saved in:
  ~/.config/tech-hud-eyecandy/config.ini
  ~/.config/tech-hud-ripples/config.ini
For background images, dropped files are copied to:
  ~/.cache/tech-hud-eyecandy/ and ~/.cache/tech-hud-ripples/

Architecture:

EyecandyManagerApp / TechHudRipplesApp:
- Holds Gee.ArrayList<HudWindow> and HudWindowInstance configs
- spawn_all() creates HudWindow for each instance
- Config load/save via GLib.KeyFile (INI style)

HudWindow (Gtk.Window):
- Type: TOPLEVEL, app_paintable, RGBA visual for transparency
- Window hints: set_type_hint (UTILITY/NORMAL), skip_taskbar/pager, keep_above/below, stick/unstick
- Position/size from config, applied via set_default_size/move/resize
- draw() uses Cairo:
  - Background: either solid color, image surface (scaled), or linear gradient from ThemeManager
  - Border: generated via get_border_vertices(w,h) depending on border_style (0=rectangle, 1=cut corners, etc.)
  - Starfield: list of particles with x,y,z and speed
  - DataStream: characters falling
  - Crawlers: outer border lights and inner crawlers with waypoints (generate_tetris_waypoints)
  - All animations driven by GLib.Timeout (16ms ~60fps) and Gtk.main()

Ripples:
- Additional state class RippleState:
  enabled, rain_enabled, drop_strength, rain_interval, rain_height_percent, drop_sharpness,
  waves_enabled, mouse_strength, mouse_radius, sharpness, alpha, damping, speed,
  tint_enabled (+r,g,b,strength), sway_enabled (+speed,strength), wave_height_percent,
  mu_tint_enabled, shoreline_enabled (+speed,strength,height_percent, tint), low_res_mode, gpu_accelerated

- Simulation:
  Two int16/short buffers curr_buf / prev_buf of size last_w*last_h (window size)
  Classic ripple algorithm:
    curr = ((neighbors sum)/2 - prev) * damping / 256
  Drops injected via ripple_drop(x,y,strength,radius)
  Rain and mouse add drops

- Rendering – two paths:

  1) draw_ripples_surface (full quality, slower):
     div = low_res_mode ? 2 : 1
     Cached surfaces: cached_ripple_bg_surface (background) and cached_ripple_surface (distorted)
     For each low-res pixel (x,y):
       - blend = (y/rh)^2 – stronger at bottom
       - mu_blend based on wave_height_percent
       - shore_blend based on shoreline_height_percent
       - sway offset = sin(wave_time + y*0.06*div) * sway_strength * mu_blend
       - ox,oy from buffer differences, shade from vertical diff
       - nx,ny = (x+ox/div+sway/div, y+oy/div) clamped
       - Sample bg_data[src_idx] + shade, apply tint if mag>5, apply shoreline wave and mu tint

  2) draw_ripples_gpu_fast (fast path, used when low_res_mode or gpu_accelerated):
     Same logic but only single pass over bg surface, no second full-res draw.
     rw = w/div, rh = h/div, bilinear filter on final scale.
     Much faster, ~4x less pixels when div=2.
     Shoreline and mu tint are included in this path since v2.

- Performance options in dialog:
  Low-Res Mode (2x faster, half resolution) – RECOMMENDED, sets div=2
  Use GPU Acceleration – forces fast path even at full res
  Resolution div, frame_skip, fast_mode, bottom_fade are kept for future optimization

Dialogs:

EyecandyManagerDialog:
  - Shows list of windows
  - set_default_size(820, target_h) where target_h = monitor.get_workarea().height (screen height - taskbar)
  - set_size_request(820,400) as minimum so it can be shrunk

WindowConfigDialog (eyecandy) / EyecandyConfigDialog (ripples):
  - Notebook with tabs: General, Background, 1.Raindrops, 2.Mouse Trail Wave, 3.Subsurface Drift, 4.Shoreline Waves
  - All values bound to inst.* and app.update_active_window() + save
  - For ripples, workarea.height used as initial height to fill screen minus taskbar

Known issues:
- Wayland: transparency and keep_above/below may behave differently; X11 is recommended
- Large windows at full resolution without Low-Res Mode are CPU heavy
- Background images are cached as Cairo ImageSurface – very large images increase memory

Future ideas:
- LUT for sin() in shoreline/mu waves
- Frame skipping option (skip every Nth physics tick)
- OpenGL shader version for ripples
