eww icon indicating copy to clipboard operation
eww copied to clipboard

Implement explicitly setting a center of rotation

Open mario-kr opened this issue 1 year ago • 3 comments

Description

The transform-Widget provides "rotate" to rotate its child. However, the default center of rotation is (0, 0) (aka top-left), so it was not possible to, for example, rotate a child in-place.

This commit implements the additional options rotation-center-x and rotation-center-y. Both are optional, and the default value is 0.0 for each, so previous configurations should produce the same results.

Usage

(defwindow grid
  :stacking "fg"
  :windowtype "dock"
  :wm-ignore true
  :geometry (geometry
    :x "10px"
    :y "10px"
    :width "100px"
    :height "100px")
  (transform
    ;:rotate {-0.5 * percentloop}
    :rotate 15
    :transform-origin-x "50%"
    :transform-origin-y "50%"
    (box :orientation 'v' :style 'padding: 5px;'
      (box :orientation 'h'
        (label :style 'background-color: grey;' ' ')
        (label :style 'background-color: green;' ' '))
      (box :orientation 'h'
        (label :style 'background-color: red;' ' ')
        (transform
          :rotate {2*percentloop}
          :transform-origin-x "30%"
          :transform-origin-y "50%"
          :translate-x "-20%"
          (box
            (box :space-evenly true
              (label :style 'background-color: yellow;' ' ')
              (label :style 'background-color: black;' ' ')
              (label :style 'background-color: yellow;' ' '))))))))

(deflisten percentloop :initial 0 `i=0; while true; do let i=$i+1; echo $i; sleep .05; done`)
* {
    all: unset;
    margin: 0px;
    padding: 0px;
}

Showcase

I made a 5 second video of above configuration, but can't embed it here.

Additional Notes

  • There are artifacts, if, for example in the above configuration, the transform of the whole grid would be a static rotate. As this does not happen when everything is moving, maybe a redraw is missing somewhere.
  • The behaviour if both rotation-center-* and translate-* needs to be mentioned, though it is not "wrong". If an in-place/centered rotation is wanted, and a shift to the right, the shift to the right needs to be added on top of the rotation-center-value to get an in-place rotation.

Checklist

Please make sure you can check all the boxes that apply to this PR.

  • [ ] All widgets I've added are correctly documented.
  • [x] I added my changes to CHANGELOG.md, if appropriate.
  • [ ] The documentation in the docs/content/main directory has been adjusted to reflect my changes.
  • [x] I used cargo fmt to automatically format all code before committing

mario-kr avatar May 25 '23 20:05 mario-kr

  • I feel like we would want the origin to be relative to the position of the widget, such that you don't need to add the translation to the rotation-center value -- especially given that you'll most likely want to use percentages for the origin
  • I'd just call it transform-origin, keeping the consistency with how the same thing is called in CSS
  • I'm not sure if I correctly understand the kind of artifacts you're referring to -- I'll see if I can reproduce them, but obviously optimally, there wouldn't be any visual artifacts here 😉

elkowar avatar Jun 08 '23 19:06 elkowar

Hi, sorry for the late response; I'll try to answer point by point:

  • If I understand correctly, then the translate-x/-y values should be added onto the origin, so that e.g. 50%/50% origin will always turn out to be an in-place rotation? As for units, the current implementation understands both percentages and pixels, so maximum flexibility for the user.
  • I renamed the variables to transform-origin. I am a bit unsure, if this is the same as in CSS, though that may be based on my inexperience with CSS in general.
  • IIRC I only changed the first :rotate value to 95 or something similar.

According to the documentation, the current transform-order is: rotate -> translate -> scale. But, looking at the code (https://github.com/elkowar/eww/blob/master/crates/eww/src/widgets/transform.rs#L165) it seems to be: scale -> rotate -> translate Point 1 might affect this order too; scale after all changes the size of a widget, so any other transformation might possibly be affected. On the other hand, the current implementation retrieves the allocated_width/height exactly once, and uses that same value for all transformations, so the transformation might currently actually be independent of each other (somewhat)?

mario-kr avatar Jul 08 '23 08:07 mario-kr

Update: I noticed #1103 when I looked at this project regarding the wrong EWW_NET values, and decided to renew this PR a bit.

  • rebased to master, fixed any hiccups due to a different way of defining properties since I last worked on this
  • updated the example rotation config

mario-kr avatar Jun 04 '24 10:06 mario-kr

please do not merge yet, I want to double-check it's correct

mario-kr avatar Aug 29 '24 17:08 mario-kr

Ok, that was a bit close for comfort, but re-checking what I did was the right decision.

The non-warping version is the one with the previously documented method-order, rotate->translate->scale.

I have rebuild this newest force-pushed commit both with nix build and nix develop -> cargo build --bin eww, both times yielding the desired result of the contents not being warped.

Sry for the mix-up.

mario-kr avatar Aug 29 '24 17:08 mario-kr

thank you for double-checking!

just as a heads-up: there should be no difference in how you build if you execute the commands the way you stated ^^

w-lfchen avatar Aug 29 '24 17:08 w-lfchen