Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Window shadows? #4

Closed
last-partizan opened this issue Jul 3, 2022 · 9 comments · Fixed by #43
Closed

Window shadows? #4

last-partizan opened this issue Jul 3, 2022 · 9 comments · Fixed by #43

Comments

@last-partizan
Copy link
Contributor

Hello.

Recently sctk-adwaita support was added to winit (rust-windowing/winit#1967), and i checked it, looks great. Thank you for this project.

Is there a way to add shadows for a window?

@PolyMeilex
Copy link
Owner

Technically, it's possible, I simply did not have enough motivation to work on it, and opted for a simple 1px border instead.

We would have to draw a gradient on all 4 edges, cache it, so it does not get redrawn on every resize (we are software rendered), and update only edges that were affected by the resize.
Another good optimization would be to just draw 1 strip of a gradient and tile/repeat it on the whole width of a window.
As for edges, I'm not sure how to do it, most likely a radial gradient.

@last-partizan
Copy link
Contributor Author

I'd take a look at this.

Is there any good docs on how to draw gradients? (i have some expirience with rust, just underlated to rendering things).

@PolyMeilex
Copy link
Owner

You would most likely use tiny_skia::Shader with tiny skia fill_rect()

You'd have to render that in top surface/texture

sctk-adwaita/src/lib.rs

Lines 401 to 410 in 0cae30e

// -> head-subsurface
if let Ok((canvas, buffer)) = self.pool.buffer(
header_width as i32,
header_height as i32,
4 * header_width as i32,
wl_shm::Format::Argb8888,
) {
let mut pixmap = PixmapMut::from_bytes(canvas, header_width, header_height)?;
pixmap.fill(Color::TRANSPARENT);

Left one:

sctk-adwaita/src/lib.rs

Lines 521 to 540 in 0cae30e

// -> left-subsurface
if let Ok((canvas, buffer)) = self.pool.buffer(
w,
h,
4 * (BORDER_SIZE * left_scale) as i32,
wl_shm::Format::Argb8888,
) {
let mut bg = Paint::default();
bg.set_color_rgba8(255, 0, 0, 255);
let mut pixmap = PixmapMut::from_bytes(canvas, w as u32, h as u32)?;
pixmap.fill(Color::TRANSPARENT);
let size = 1.0;
pixmap.fill_rect(
Rect::from_xywh(w as f32 - size, 0.0, w as f32, h as f32)?,
&border_paint,
Transform::identity(),
None,
);

Right one:

sctk-adwaita/src/lib.rs

Lines 564 to 575 in 0cae30e

// -> right-subsurface
if let Ok((canvas, buffer)) = self.pool.buffer(
w,
h,
4 * (BORDER_SIZE * right_scale) as i32,
wl_shm::Format::Argb8888,
) {
let mut bg = Paint::default();
bg.set_color_rgba8(255, 0, 0, 255);
let mut pixmap = PixmapMut::from_bytes(canvas, w as u32, h as u32)?;
pixmap.fill(Color::TRANSPARENT);

Bottom one:

sctk-adwaita/src/lib.rs

Lines 470 to 478 in 0cae30e

// -> bottom-subsurface
if let Ok((canvas, buffer)) = self.pool.buffer(
w,
h,
(4 * bottom_scale * (width + 2 * BORDER_SIZE)) as i32,
wl_shm::Format::Argb8888,
) {
let mut pixmap = PixmapMut::from_bytes(canvas, w as u32, h as u32)?;
pixmap.fill(Color::TRANSPARENT);

Basically, there is a texture per edge.

last-partizan added a commit to last-partizan/sctk-adwaita that referenced this issue Jul 6, 2022
@Tim-Paik
Copy link

It's cumbersome to make comfortable shadows, I thought, maybe it would be easier to pre-render and hardcode into the code?
I think it can be implemented by referring to here:
https://docs.cocos.com/creator/2.0/manual/en/ui/sliced-sprite.html

@last-partizan
Copy link
Contributor Author

Currently i don't have much time to spare for this, but if anyone wants to give it a try, it would be great.

@lictex
Copy link

lictex commented Jun 10, 2023

It's cumbersome to make comfortable shadows, I thought, maybe it would be easier to pre-render and hardcode into the code? I think it can be implemented by referring to here: https://docs.cocos.com/creator/2.0/manual/en/ui/sliced-sprite.html

i tried this (here) and it seems to work for basic cases but

  • for small windows there are some badly overlaps
  • dragging area for resizing becomes super large
  • 12 draw_pixmap() calls per draw. not sure how expensive this is, at least i dont feel its more laggy than before
  • might be blurry on hidpi displays (shadows shouldnt be affected much by this though)

idk how to make these better really (especially the first two, which makes me think this is actually.. unusable)

image image

@last-partizan
Copy link
Contributor Author

It looks good, and if that issue with resize handles can be resolved, it would be usable.

I think issue with small windows can be ignored for now.

Looks like libdecor is ready: kovidgoyal/kitty#3284 (comment), but i haven't seen rust integration. So, we can use this until we have better options.

@Tim-Paik
Copy link

I seem to have a little idea, maybe we can set a threshold, and when it is less than this threshold, only the shadows of the four corners are drawn instead of the shadows of the four sides, so as to prevent the overlap problem, can this be achieved?

Or we can be more straightforward and stop drawing shadows directly when the window is too small.

@Friz64
Copy link
Contributor

Friz64 commented Nov 25, 2023

I had a go at this in #43, feedback appreciated.

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 a pull request may close this issue.

5 participants