From 163eff4216c85ffa12dbdf77d1e7bd4e2e314c3c Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Fri, 30 Oct 2026 21:06:03 -0700 Subject: [PATCH] refactor(kde): make qt_curve an extension trait AnimationStyle is going to live in komorebi-protocol, and an inherent impl cannot be written outside the crate that defines the type (orphan rule). qt_curve (the only inherent impl on a type that moves in step 2, in any tree) becomes the trait QtCurve in core::animation, implemented for AnimationStyle; callers import it. The method is no longer const (trait methods cannot be); no caller needed that. Doc links to AnimationStyle::qt_curve are updated. Verified: cargo test -p komorebi --lib every_style: passed; cargo test -p komorebi --doc: 45 + 2 passed, 0 failed (includes the qt_curve doctest). --- komorebi-for-kde/docs/dev/ARCHITECTURE.md | 6 +++--- komorebi-for-kde/docs/dev/DESIGN.md | 2 +- komorebi-for-kde/komorebi/src/border_manager/mod.rs | 1 + komorebi-for-kde/komorebi/src/core/animation.rs | 13 +++++++++++-- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/komorebi-for-kde/docs/dev/ARCHITECTURE.md b/komorebi-for-kde/docs/dev/ARCHITECTURE.md index 56dd4979..a7285048 100644 --- a/komorebi-for-kde/docs/dev/ARCHITECTURE.md +++ b/komorebi-for-kde/docs/dev/ARCHITECTURE.md @@ -1099,7 +1099,7 @@ look without a border unloads the effect, if komorebi loaded it, and puts the us back. `shutdown` does the same. An effect KWin did not find when it started is reported once and komorebi goes on without it, with `apply_look` answering false. The animation is Geometry Change: its `Duration` and `Curve` are the look's, and cross-fading is off. The curve is a Qt easing -curve, the name of the style without its "Ease" ([`AnimationStyle::qt_curve`]); the stock effect +curve, the name of the style without its "Ease" ([`QtCurve::qt_curve`]); the stock effect ignores `Curve` and eases out exponentially, and komorebi's build of it reads it. KWin animates what is painted, so the frame the table reads is the final one at once and nothing waits for an animation to end. The @@ -1522,7 +1522,7 @@ the fake. The window manager is its only caller, through [`backend`]. The contra | The settings of one kind of animation win over the global ones, and a global setting clears them | framework path: the arms of [`WindowManager::process_command`] for `Animation`, `AnimationDuration` and `AnimationStyle`, and [`animation::movement_animation`] and [`animation::movement_style`], which read the kind's setting before the global one | `the_animation_messages_set_the_animation_and_the_compositor_is_asked_for_it` | none | | A command that changes a stack is carried out with the animation off, and the animation is on again after it | framework path: the arms of [`WindowManager::process_command`] for the stack messages swap `ANIMATION_ENABLED_GLOBAL` for false and put the value back | `the_animation_is_on_again_after_a_command_that_changes_a_stack` | none | | The `animation` key of the file is the animation settings, and a file without it leaves them | framework path: `StaticConfig::apply_globals` sets them only when the key is there, and `duration` and `style` only when the key has one | `the_animation_key_of_the_file_is_the_animation_settings` | none | -| Every style is a curve Qt has | test: [`AnimationStyle::qt_curve`] is a `match` of every style, and the test checks each against its name without the "Ease" | `every_style_is_a_curve_qt_has`, the doctest of `qt_curve`, `vm-features` (section D: two curves are in different places at the same moment) | a cubic Bézier is an ease out | +| Every style is a curve Qt has | test: [`QtCurve::qt_curve`] is a `match` of every style, and the test checks each against its name without the "Ease" | `every_style_is_a_curve_qt_has`, the doctest of `qt_curve`, `vm-features` (section D: two curves are in different places at the same moment) | a cubic Bézier is an ease out | | Only the windows the rules make see-through are, and only while transparency is on | framework path: [`transparency_manager::apply`] asks [`transparency_manager::transparent_windows`] and sends the difference from [`WindowManager::opacity_applied`] | `unfocused_windows_are_transparent_and_the_focused_one_is_not`, `turning_transparency_off_makes_everything_opaque_again`, `a_monocled_window_is_not_transparent`, `windows_the_rules_ignore_keep_their_opacity`, `vm-features` (section B) | none | | The `transparency` keys of the file are the settings, and a key the file leaves out has the default | framework path: `StaticConfig::apply_globals` stores `transparency` and `transparency_alpha` whether the file has them or not, and adds the ignore rules to `TRANSPARENCY_BLACKLIST` | `the_transparency_keys_of_the_file_are_the_transparency_settings` | none | | A theme gives every kind of border a color, the one it names or the theme's default | framework path: [`theme_manager::send_notification`] stores a color for each of the six kinds, from the theme's own defaults for the ones the message does not name | `a_named_theme_colours_every_kind_of_border` | none | @@ -2061,7 +2061,7 @@ plan needs no engine. A failure to start is logged, and the window manager runs [`WindowManager::opacity_applied`]: ../../komorebi/src/window_manager.rs [`animation::movement_animation`]: ../../komorebi/src/animation/mod.rs [`animation::movement_style`]: ../../komorebi/src/animation/mod.rs -[`AnimationStyle::qt_curve`]: ../../komorebi/src/core/animation.rs +[`QtCurve::qt_curve`]: ../../komorebi/src/core/animation.rs [`AnimationPrefix`]: ../../komorebi/src/animation/prefix.rs [`Backend::set_border_colours`]: ../../komorebi/src/backend/mod.rs [`border_manager::window_kinds`]: ../../komorebi/src/border_manager/mod.rs diff --git a/komorebi-for-kde/docs/dev/DESIGN.md b/komorebi-for-kde/docs/dev/DESIGN.md index aca0daf0..8728a699 100644 --- a/komorebi-for-kde/docs/dev/DESIGN.md +++ b/komorebi-for-kde/docs/dev/DESIGN.md @@ -485,7 +485,7 @@ resize, and what the window shows does not change. Because KWin animates with `QEasingCurve`, and a style is a curve KWin has when it is Qt's name without the "Ease": `EaseInOutSine` is `InOutSine` -([`AnimationStyle::qt_curve`](../../komorebi/src/core/animation.rs)). A custom cubic Bézier is not +([`QtCurve::qt_curve`](../../komorebi/src/core/animation.rs)). A custom cubic Bézier is not one of Qt's curves, and is drawn as an ease out, the kind of curve a window moving to its place wants. The stock Geometry Change has one curve, an exponential ease out, so komorebi's build of it reads a `Curve` setting ([PLATFORM.md](PLATFORM.md#the-patches)). diff --git a/komorebi-for-kde/komorebi/src/border_manager/mod.rs b/komorebi-for-kde/komorebi/src/border_manager/mod.rs index c8f6de66..427e24c3 100644 --- a/komorebi-for-kde/komorebi/src/border_manager/mod.rs +++ b/komorebi-for-kde/komorebi/src/border_manager/mod.rs @@ -23,6 +23,7 @@ use crate::backend::Look; use crate::backend::backend; use crate::core::WindowKind; use crate::core::animation::AnimationStyle; +use crate::core::animation::QtCurve; use crate::window_manager::WindowManager; use color_eyre::eyre; use komorebi_themes::colour::Colour; diff --git a/komorebi-for-kde/komorebi/src/core/animation.rs b/komorebi-for-kde/komorebi/src/core/animation.rs index e03110ac..c0e9b18c 100644 --- a/komorebi-for-kde/komorebi/src/core/animation.rs +++ b/komorebi-for-kde/komorebi/src/core/animation.rs @@ -80,7 +80,11 @@ pub enum AnimationStyle { CubicBezier(f64, f64, f64, f64), } -impl AnimationStyle { +/// The Qt easing curve of an animation style, as KWin's animation API takes it. +/// +/// A trait because `AnimationStyle` is to live in a crate shared with the other platforms, and an +/// inherent impl cannot be written outside the crate that defines the type. +pub trait QtCurve { /// Returns the name of the Qt easing curve of this style, as KWin's animation API takes it /// (`QEasingCurve.`). /// @@ -89,6 +93,7 @@ impl AnimationStyle { /// /// ```rust /// use komorebi::core::animation::AnimationStyle; + /// use komorebi::core::animation::QtCurve; /// /// assert_eq!(AnimationStyle::Linear.qt_curve(), "Linear"); /// assert_eq!(AnimationStyle::EaseInOutSine.qt_curve(), "InOutSine"); @@ -97,7 +102,11 @@ impl AnimationStyle { /// "OutCubic" /// ); /// ``` - pub const fn qt_curve(&self) -> &'static str { + fn qt_curve(&self) -> &'static str; +} + +impl QtCurve for AnimationStyle { + fn qt_curve(&self) -> &'static str { match self { Self::Linear => "Linear", Self::EaseInSine => "InSine",