Skip to content

Feat: Added border textures + gradient texture support - #1367

Open
SDG-Den wants to merge 6 commits into
mangowm:mainfrom
SDG-Den:border-textures
Open

SDG-Den wants to merge 6 commits into
mangowm:mainfrom
SDG-Den:border-textures

Conversation

@SDG-Den

@SDG-Den SDG-Den commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Feature:

added a border texturing system (initially meant to support gradients, but expanded to allow a wide selection of customization) as well as supporting dispatchers.

new options:

  • active_texture(_top/_mid/_bot)
    sets the focused texture. 4 keys in total, one for each available texture slot (users can composite 3 textures on top of eachother if they so choose) and a general one that always targets the top slot

  • inactive_texture(_top/_mid_bot)
    same but for the unfocused textures

new mmsg field

texture_render_ms - shows the time taken to render the borders (always shows the last call), used for testing and useful to users to see the impact their borders have on their performance.

new window rules:

  • (in)active_texture(_top/_mid/_bot)
    same as the new options, multiple rules can be used to define multiple textures for the same window.

  • focus_color
    sets an override for the global focus_color option for that window

  • border_color
    sets an override for the global border_color option for that window

  • borderpx
    sets an override for the global borderpx option for that window

  • border_radius
    sets an override for the global border_radius option for that window

new dispatchers:

  • set_active_texture
    allows setting any of the active texture slots.

  • set_inactive_texture
    allows setting any of the inactive texture slots.

  • rerender_texture
    triggers an immediate re-render of the focused window's texture (for scripting)

  • set_focus_override
    sets an override for the focus border color

  • set_border_override
    sets an override for the unfocused border color

  • clear_focus_override
    sets the focus border back to its windowrule or global config value

  • clear_border_override
    sets the unfocused border back to its windowrule or global config value

  • set_border_px
    sets the border thickness override, -1 resets to default

  • set_border_radius
    sets the border radius override, -1 resets to default

renderers

  1. linear gradient
  2. radial gradient
  3. conic gradient (false conic)
  4. static image
  5. tiled image
  6. fit image (stretch/squashed)
  7. fit image as overlay (does not cut out client, allows overlaying texture on top of window)
  8. tile image as overlay
  9. segment image (uses ninepatch textures)
  10. segment color (allows you to set each side of the border an individual color)
  11. solid color (in case you want to layer your texture with a solid color)
  12. solid color overlay (covers the whole client, can be used with low alpha values to create things like dimming)

renderers make use of caching where possible to avoid high software rendering costs, as well as caching all loaded images to avoid constantly loading them from disk. cache-warming is done on compositor start, config reload and first monitor detected to avoid heavy disk loads during use.

at the moment, only PNG is supported for images.

tests

all renderers were tested in a worst-case scenario:

  • nested compositor (pixman rendering)
  • various source scales (480p, 1080p, 8k images)
  • various border widths (5px, 20px, 50px)
  • heavy combinations

measurements were done every 10ms, and were done on a "worst-measurement" basis, meaning that all results were the worst single render call in the measured window for any of the displays on screen.

both spawn and animation tests were done, spawn tests were done on tile layout at 1080p, and up to 8 window spawns was tested.

for animation, focus and resize were both tested multiple times. focus by using a dispatcher to change focus, resize through smartresizewin dispatcher

all testing was done automatically using a testing harness, all in, about 12 hours of testing was done.

all individual renderers pass the following requirements, even when deliberately used in a way to produce the worst-possible performance:

  • cold spawn (texture not on any window yet) under 25ms (this is the threshold above which animation stutter becomes noticeable)
  • hot spawn under 20ms
  • focus change sub-1ms
  • resize worst-case under 10ms
  • resize median under 5ms

tests were done at 1080p on a ryzen 7 5700g with a target framerate of 60FPS. each renderer was tested in a fresh instance of mango.

examples 1-4

top left - solid_color_overlay (dark red dimming)
top right - solid_color (green, primarily for compositing)
bottom left - segment_color
bottom right - segment_image (ninepatch)
screenshot_2026-09-15_00-04-03

examples 5-8

top left - fit_overlay (with a dirt texture)
top right - tile_overlay (with a censor box)
bottom left - fit_image
bottom right - tile_image (with transparent components to show border color through)
screenshot_2026-09-15_00-03-46

examples 9-12

top left - static_image
top right - conic_gradient (full spectrum)
bottom left - radial_gradient (black to white)
bottom right - linear-gradient (teal to dark blue)
screenshot_2026-09-15_00-03-38

Comment thread src/animation/client.c
@SDG-Den
SDG-Den force-pushed the border-textures branch 2 times, most recently from c64f85e to 79ed852 Compare September 7, 2026 11:54
re-worked texture engine for multiple slots

added helper dispatchers and window rules that make working with the texture system easier

added caching to image based renderers so image does not get read from disk every time

added animations

added a couple more renderers
@SDG-Den
SDG-Den marked this pull request as ready for review September 9, 2026 00:39
@SDG-Den
SDG-Den marked this pull request as draft September 9, 2026 12:28
@DreamMaoMao
DreamMaoMao force-pushed the main branch 4 times, most recently from 7ec6dc4 to 3dc2970 Compare September 12, 2026 06:32
fixed crash with groups, fixed fade blink wonkiness, fixed some inconsistent syntax

performance improvement - swapped cache searches from loop-based search to insertion sort based search.

reworked segment renderer to use caching for each tile, drastically lowering re-render cost

slight optimization to fit renderers: scale down cache first, also allowed monitoring of render times using mmsg

made various other performance optimizations, added pre-caching, benchmarked all renderers within spec:

- 25ms cold spawn
- 20ms warm spawn
- 10ms maximum resize animation
- 5ms median resize animation
- sub-1ms focus-change animation

these are all measured by the time taken by the longest render call. Also added texture_render_ms field to client IPC output so users can measure the impact of their textures.

some final fixes and brush-ups, as well as update to performance table
@SDG-Den
SDG-Den marked this pull request as ready for review September 14, 2026 21:24
This was referenced Sep 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants