Proposal: native crossfade transition when changing desktop backgrounds
Hi,
I’d like to propose adding a crossfade transition to xfdesktop when switching from one wallpaper to another, if maintainers feel this fits the project.
This is not meant as a finished implementation or as code that should be merged as-is. My intention is to share a missing piece I came across, some research around it, and a small working PoC showing that current xfdesktop architecture can handle this directly inside its rendering pipeline.
Why I ended up looking into this: WMM
I’m developing WMM (Wallpaper Multi-Monitor Manager), a multi-monitor wallpaper manager built around native desktop integrations rather than replacing each desktop environment’s own wallpaper handling.
On Xfce, WMM changes wallpapers through normal xfdesktop mechanisms.
While working on Xfce support, one visual limitation became apparent: wallpaper changes are immediate, with no transition between outgoing and incoming backgrounds.
My first approach was to see whether WMM could provide that effect externally.
I tested or investigated several possibilities: intermediate images, root pixmap manipulation, overlays, and similar external approaches. They all ended up duplicating work already performed by xfdesktop, repeatedly loading or generating image data, or interfering with desktop elements that should not be part of a wallpaper transition.
That led me to look at current xfdesktop rendering path instead.
Missing piece: both surfaces exist, but never coexist
In xfdesktop 4.20.1, a new background eventually becomes a cairo_surface_t already rendered through normal backdrop pipeline.
When backdrop_loaded() receives that surface, previous bg_surface is destroyed immediately and replaced by the new one.
In simplified form:
surface A ↓ destroy ↓ surface B ↓ xfce_desktop_draw()
xfce_desktop_draw() already provides a convenient boundary for this kind of transition: backdrop is painted first, then desktop children are propagated afterwards.
So desktop icons do not need to be part of crossfade at all.
PoC simply delays destruction of surface A for a short period:
surface A ────────────────┐ ├─ Cairo blend ──> xfce_desktop_draw() surface B ────────────────┘ ↑ GdkFrameClock
No intermediate images are generated, and wallpaper is not reloaded for every frame. Both surfaces have already gone through normal xfdesktop rendering pipeline.
Experimental implementation
I built a PoC against:
xfdesktop 4.20.1-5507be2 Xfce 4.20 GTK 3.24.52
Changes are limited to:
src/xfce-desktop.c
Flow is deliberately small:
- When a new backdrop arrives, previous
bg_surfaceis temporarily kept as outgoing surface. - New surface remains
bg_surface, so normal backdrop authority is unchanged. - A
gtk_widget_add_tick_callback()callback is registered. - Transition progress is calculated from
GdkFrameClockpresentation time rather than frame counting or a synthetic timer. xfce_desktop_draw()paints outgoing surface first, then composites incoming surface over it usingcairo_paint_with_alpha().- Once transition reaches completion, outgoing surface is released and frame-clock callback is removed.
- Outside a transition, original single-surface drawing path remains unchanged.
PoC currently uses a fixed 750 ms duration, chosen from an existing real-world reference rather than as a proposed Xfce standard.
Historically, GNOME used a 750 ms duration for its GnomeBGCrossfade implementation, while other desktops have used somewhat different timings for similar effects.
So 750 ms here is only a sensible reference value for validating behavior. I am not proposing it as a required duration, or even necessarily as a fixed one.
Testing
PoC was compiled and tested directly on Xfce 4.20.
I tested:
- wallpaper changes triggered by WMM;
- changes made through normal Xfce mechanisms;
- multi-monitor setups;
- independent transitions on different monitors;
- consecutive changes before a previous transition finishes;
- desktop icon behavior;
- repeated wallpaper changes.
Across these scenarios, transition remained smooth and stable.
WMM itself contains no special handling for this experiment. It keeps requesting wallpaper changes exactly as before.
Crossfade appears purely because xfdesktop handles transition internally once a new surface arrives.
This also means feature is not tied to WMM: any backdrop change going through normal Xfce mechanisms could benefit from it.
Historical context
While researching this, I found old Bugzilla #7098, “[enh] Have backdrop change using a fading effect”, which was eventually closed as WONTFIX in 2020.
I have not been able to recover original discussion, so I do not know technical reasons behind that decision and do not want to speculate about them.
What seems relevant is that backdrop handling changed substantially afterwards.
In 2024, among other changes, xfdesktop moved towards one XfceDesktop per monitor and backdrop handling was reorganized around current XfdesktopBackdropManager, asynchronous loading/rendering, and cached Cairo surfaces.
This PoC takes advantage of that current architecture.
For that reason, I thought it could be worth revisiting crossfade based on what current xfdesktop pipeline allows, rather than treating this as a continuation of implementation assumptions from 2020.
PoC diff
I’m attaching complete, documented diff used for this experiment:
xfdesktop-crossfade-final.diff
Diff is not meant to prescribe how this feature should ultimately be implemented. Its purpose is to make this proposal reproducible and show exactly what was required to validate the approach.
It is intentionally limited to xfce-desktop.c. It does not modify BackdropManager, renderer, configuration handling, or external applications requesting wallpaper changes.
If a transition like this makes sense for xfdesktop, I naturally leave final design decisions to maintainers: whether it should be enabled by default, configurable, how long it should last, whether easing is desirable, where logic should ultimately live, or whether a different implementation better fits project architecture.
My goal here is simply to share something that proved viable on current codebase, together with working results and PoC.
Environment
- OS distribution: Manjaro Linux
- Xfce: 4.20
- xfdesktop: 4.20.1-5507be26
- GTK: 3.24.52
- Windowing system: X11
Tests described above were performed on X11. I have not validated this PoC on Wayland.
Thanks for your time, and for maintaining Xfce.