OS animations and smooth scrolling for nextOS 2.5.0#8
Conversation
Add animation engine to compositor with ease-out cubic easing: - Window open: slide-up + fade-in (200ms) - Window close: fade-out + slide-down with deferred destruction (150ms) - Window minimize: slide to taskbar + fade-out (250ms) - Window unminimize: slide from taskbar + fade-in (250ms) - Window maximize/restore: fade transition (200ms) - Start menu: slide-up/down + fade (150ms) Animation state tracked per-window with timer-based progress. Hit-testing skips windows in close/minimize animations. Fade overlay blends window pixels towards wallpaper cache. Co-authored-by: dynodevv <85120286+dynodevv@users.noreply.github.com>
Co-authored-by: dynodevv <85120286+dynodevv@users.noreply.github.com>
…nt smooth scrolling 1. Z-order bug fix: Save background pixels before drawing animated window, then blend between saved background and drawn window. This correctly shows windows behind during close/minimize animations instead of the wallpaper bleeding through. 2. GNOME-like stretch animations: Maximize/restore/minimize/unminimize now animate position AND size (stretch effect). Canvas is scaled during animation using nearest-neighbor sampling. Added anim_from_w/h and anim_to_w/h fields to window_t struct. 3. Smooth scrolling: Added compositor_get_smooth_scroll() API that provides interpolated scroll values. Scroll input accumulates into a target, which is smoothly interpolated at ~30% per frame. All 4 apps (notepad, browser, explorer, settings) updated to use it. Co-authored-by: dynodevv <85120286+dynodevv@users.noreply.github.com>
Apply the same bg_save technique to the start menu animation that was applied to window animations. Previously the start menu fade blended toward wallpaper, but it sits above the taskbar, so fading should show the taskbar behind it. Co-authored-by: dynodevv <85120286+dynodevv@users.noreply.github.com>
- Add cw > 0 && ch > 0 check to canvas blit to prevent out-of-bounds access when source canvas dimensions are very small - Fix smooth scroll: snap small remainders (< 256 fixed-point) to prevent scroll values from getting stuck and never draining Co-authored-by: dynodevv <85120286+dynodevv@users.noreply.github.com>
The previous smooth scroll implementation used a fixed-point x256 accumulator that delivered fractional scroll notches. This never worked because integer division always rounded fractional values to 0, causing the snap-to-±1 fallback to make scrolling identical to raw/choppy. New approach: - Raw scroll notches converted to pixel targets (120px per notch) - Each frame releases 30% of remaining pixels (min 2px), creating natural ease-out deceleration over ~12 frames (~96ms) - Pixel-based apps (notepad, browser) receive smooth pixel deltas directly, removing their per-notch multipliers - Row-based apps (explorer, settings) use raw compositor_get_scroll() since they can't do sub-row scrolling Co-authored-by: dynodevv <85120286+dynodevv@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR claims to fix smooth scrolling but actually includes two major feature additions: (1) a pixel-level smooth scrolling system and (2) a comprehensive window/menu animation system with ease-out cubic easing. The PR description only mentions the smooth scrolling changes.
Changes:
- Pixel-level smooth scrolling with 30% per-frame ease-out interpolation (accumulator + gradual release)
- Complete animation system: window open/close/minimize/unminimize/maximize/restore animations with canvas scaling, alpha blending, and background saving
- Start menu slide+fade animations
- Updated notepad and browser to use pixel-based smooth scrolling API
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| kernel/ui/compositor.h | Added animation type defines, window animation state fields, and compositor_get_smooth_scroll() declaration |
| kernel/ui/compositor.c | Implemented smooth scroll accumulator/interpolation, complete animation system with ease-out cubic easing, deferred window destruction, canvas scaling during animations, alpha blending with background saving, start menu animations |
| apps/notepad/notepad.c | Switched to compositor_get_smooth_scroll() and removed LINE_HEIGHT multiplier |
| apps/browser/browser.c | Switched to compositor_get_smooth_scroll() and removed pixel multiplier |
| @@ -959,6 +1264,16 @@ void compositor_handle_mouse(int mx, int my, int buttons, int scroll) | |||
| if (mx >= bx && mx < bx + 120) { | |||
| if (windows[i].minimized) { | |||
| windows[i].minimized = 0; | |||
There was a problem hiding this comment.
Inconsistency in animation lifecycle: unminimize sets minimized = 0 immediately (line 1266), but minimize waits until animation completion to set minimized = 1 (line 1121). While the current code works due to the draw_window conditional checking both minimized and anim_type, this asymmetry is confusing and could lead to bugs. Consider moving this line to the ANIM_UNMINIMIZE finalization case (after line 1124) to match the minimize pattern and make the code more maintainable.
There was a problem hiding this comment.
Fixed in 455d40a. Moved minimized = 0 from the click handler to the ANIM_UNMINIMIZE finalization case, matching the minimize pattern. Both now update minimized at animation completion.
| /* ── Animation types ──────────────────────────────────────────────────── */ | ||
| #define ANIM_NONE 0 | ||
| #define ANIM_OPEN 1 | ||
| #define ANIM_CLOSE 2 | ||
| #define ANIM_MINIMIZE 3 | ||
| #define ANIM_UNMINIMIZE 4 | ||
| #define ANIM_MAXIMIZE 5 | ||
| #define ANIM_RESTORE 6 | ||
|
|
There was a problem hiding this comment.
The PR title and description focus solely on fixing smooth scrolling, but the changes include a complete window animation system (open, close, minimize, unminimize, maximize, restore animations with ease-out cubic easing, canvas scaling during animations, alpha blending with background saving, start menu animations, etc.). This extensive animation system is not mentioned in the PR description. While these features may be valuable, bundling them with the smooth scrolling fix makes the PR harder to review and increases risk. Consider splitting these into separate PRs: one for smooth scrolling fixes and another for the animation system.
|
@copilot apply changes based on the comments in this thread |
Move minimized=0 from the click handler to the ANIM_UNMINIMIZE finalization case, matching the minimize pattern which sets minimized=1 at animation completion. This makes the minimize/ unminimize lifecycle symmetric and less error-prone. Co-authored-by: dynodevv <85120286+dynodevv@users.noreply.github.com>
Applied the lifecycle fix from the review in |
Implements a comprehensive animation system and pixel-level smooth scrolling for nextOS, providing a modern, fluid experience that matches the skeuomorphic design aesthetic.
Animation System
Animation state is tracked per-window with
anim_from_x/y/w/handanim_to_x/y/w/hfields. The minimize/unminimize lifecycle is symmetric — both update theminimizedflag only at animation completion.Z-order Animation Bug Fix
Window and start menu animations previously blended toward the wallpaper cache during fading, causing windows behind the animated window to briefly disappear. Fixed by saving background pixels before drawing the animated element, then blending against the saved snapshot instead of the wallpaper. Applied to both window and start menu animations.
Smooth Scrolling
The initial fixed-point ×256 accumulator approach never worked — integer division always rounded fractional values to 0. Redesigned with a pixel-level accumulator:
smooth_scroll_accumcompositor_get_smooth_scroll()directly as pixel deltacompositor_get_scroll()since discrete row indexing can't benefit from sub-row interpolationFiles Changed
kernel/ui/compositor.hcompositor_get_smooth_scroll()declarationkernel/ui/compositor.capps/notepad/notepad.ccompositor_get_smooth_scroll(), removed per-notch multiplierapps/browser/browser.ccompositor_get_smooth_scroll(), removed per-notch multiplierapps/explorer/explorer.ccompositor_get_scroll()for row-based scrollingapps/settings/settings.ccompositor_get_scroll()for row-based scrolling💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.