koekeishiya / yabai

A tiling window manager for macOS based on binary space partitioning
MIT License
23.52k stars 647 forks source link

Feature Request: support window vibrancy and blur #1113

Closed yorhodes closed 2 years ago

yorhodes commented 2 years ago

This is a feature in other window manager ecosystems https://www.reddit.com/r/unixporn/comments/rqjrls/i3gaps_local_man_install_arch_tells_no_one/ https://www.reddit.com/r/unixporn/comments/nkxagu/bspwm_i_quite_like_blur/

It looks like this can be implemented in macos fairly easily? https://developer.apple.com/documentation/uikit/uivibrancyeffect?language=objc https://developer.apple.com/documentation/appkit/nsvisualeffectview?language=objc

I would love to contribute this feature but not sure how feasible and I couldn't find much useful documentation. It seems like the Core Graphics API in use does not match what I found in Apple's docs.

https://github.com/koekeishiya/yabai/blob/846723a2629daf995882359f26967889654a0b4d/src/osax/payload.m#L654

versus

https://developer.apple.com/documentation/coregraphics/1456404-cgcontextsetalpha?language=objc

What are your thoughts @koekeishiya

FelixKratz commented 2 years ago

This would be for background blur:

extern CGError SLSSetWindowBackgroundBlurRadius(int cid, uint32_t wid, uint32_t radius);

and the other things needed for vibrancy effects I think are listed in the bottom of this file: https://github.com/NUIKit/CGSInternal/blob/master/CGSWindow.h

yorhodes commented 2 years ago

where the hell is the Core Graphics Skylight framework documented?

yorhodes commented 2 years ago

https://developer.apple.com/documentation/appkit/nsvisualeffectview?language=objc

koekeishiya commented 2 years ago

I looked at blur a long time ago and did not like the result: https://github.com/koekeishiya/yabai/issues/493 Maybe I'll revisit in the future.

FelixKratz commented 2 years ago

I don't think #1115 is the way to go about this. Windows with modified alpha will deactivate the background blur. I have quickly hacked together something with limelight: Screen Shot 2022-01-13 at 17 53 57

The way my quick and dirty hack works is by creating a new transparent window behind the actual window where I set SLSSetWindowBackgroundBlurRadius, such that when the window receives an alpha it will be in front of a blurred "backdrop". Theoretically this can also be implemented in yabai directly, but the window ordering groups are broken on monterey.

koekeishiya commented 2 years ago

Window ordering groups work fine on Monterey, it is the movement group that causes the issues as far as I remember, so I do believe your version for enabling window blurs could work.

yorhodes commented 2 years ago

@FelixKratz @koekeishiya any way I can help ship this to yabai or will this only be possible with limelight?

ghost commented 2 years ago

Any update on this?

FelixKratz commented 2 years ago

@FelixKratz @koekeishiya any way I can help ship this to yabai or will this only be possible with limelight?

It is a fairly minor change that can be incorporated the exact same way current window borders are implemented. Create a new window, „glue“ this window to the host, always keep it ordered behind the host and give the window a background blur. Then all inactive windows, which receive an alpha via the scripting addition appear to have a blurred background.

This is exactly what I have done in my above screenshots.

FelixKratz commented 2 years ago

It can be done even easier than described above: The borders have no reason to be in front of the window. Rather, I have chosen to glue them below the window and apply a negative inset to them. This way rounded borders can also be implemented and the distracting border flickering is a non problem, additionally content from the window is not truncated.

When doing it this way it is as simple as giving the border a fill color and a background blur. This is my implementation of it: https://github.com/FelixKratz/yabai/commit/fb48e7617f7e75d246684b9a3cdce37560f835fe including rounded borders as you can see here:

Screen Shot 2022-06-20 at 09 17 59
kevinmonisit commented 2 years ago

I see that a previous pull request #1115 was made for window blurring, but it was closed. But has this new solution been made into a pull request yet?

Would love to see @FelixKratz 's solution come to fruition! :)

FelixKratz commented 2 years ago

I think I have read somewhere that pull requests are generally not welcome on this project. Just create a fork and patch these changes in, thats why I have linked my fork for most of the changes I have made (e.g. the mach ipc for the scripting addition).

This being said, I noticed some people are actually using my fork. Please don't, it is full of things I have changed only for my personal preference and for experimenting. It is only linked so you can cherry-pick changes you like to your own fork.

weeebdev commented 2 years ago

FelixKratz@fb48e76

what do you use for desktop customization? It looks amazing

yorhodes commented 2 years ago

@weeebdev https://github.com/FelixKratz/SketchyBar

weeebdev commented 2 years ago

@weeebdev https://github.com/FelixKratz/SketchyBar

Thanks. Do you consider adding a rounded corners on the border?

koekeishiya commented 2 years ago

This will be fixed with the changes being made for #1430

Tushar1729-k commented 2 years ago

how do I install my own fork of yabai?

FelixKratz commented 1 year ago

It is possible to bind a CAContext to an SLSSurface and add a CABackdropLayer with CAFilters to create further backdrop effects, i.e. stronger blur, vibrancy, saturation, darken, lighten, etc.... is this something worth discussing for yabai?

koekeishiya commented 1 year ago

If it can be added to an arbitrary window using the scripting-addition, yes. If it is going to work in the same way as the current version that relies on the borders, then I'm not particularly interested in making adjustments at this time.

FelixKratz commented 1 year ago

Yeah, that is possible -- I just tried it and I am able to add arbitrary surfaces to arbitrary windows. The surface moves and orders with the window fully automatically. This could also be used to make a more robust border system.

But it has to be handled with caution, because these surfaces will continue to exist even after yabai exits.

koekeishiya commented 1 year ago

But it has to be handled with caution, because these surfaces will continue to exist even after yabai exits.

Maybe it is time to work on having fully persistent state, which would also solve this new issue.

koekeishiya commented 1 year ago

@FelixKratz

I assume this works more or less in the following way?

  1. Create a new CAContext
  2. Create a new CALayer and set up filters
  3. Set the CALayer as the layer for the CAContext
  4. Create and setup a surface for the arbitrary window.
  5. Bind the surface to the CAContext we created using its id?
FelixKratz commented 1 year ago

@FelixKratz

I assume this works more or less in the following way?

  1. Create a new CAContext
  2. Create a new CALayer and set up filters
  3. Set the CALayer as the layer for the CAContext
  4. Create and setup a surface for the arbitrary window.
  5. Bind the surface to the CAContext we created using its id?

Yes, this is what I was testing with:

  [CATransaction begin];
  CAContext* context = [CAContext contextWithCGSConnection:_connection options:nil];
  CABackdropLayer* layer = [[CABackdropLayer alloc] init];
  layer.frame = bounds;
  layer.windowServerAware = true;
  layer.cornerRadius = 10;
  layer.borderWidth = 2;
  layer.borderColor = CGColorCreateGenericRGB(1, 1, 1, 1);
  CAFilter* blur = [[CAFilter alloc] init];
  [blur initWithType:kCAFilterGaussianBlur];

  NSNumber *normalize = [NSNumber numberWithBool:true];
  [blur setValue:normalize forKey:@"inputNormalizeEdges"];
  NSNumber *radius = [NSNumber numberWithFloat:100.0f];
  [blur setValue:radius forKey:@"inputRadius"];

  CAFilter* saturate = [[CAFilter alloc] init];
  [saturate initWithType:kCAFilterColorSaturate];

  NSNumber *saturation = [NSNumber numberWithFloat:1.2f];
  [saturate setValue:saturation forKey:@"inputAmount"];

  NSArray* filters = @[saturate, blur];
  [layer setFilters:filters];

  context.layer = layer;

  uint32_t sid = 0;

  SLSAddSurface(_connection, wid, &sid);
  SLSSetSurfaceBounds(_connection, wid, sid, bounds);
  SLSSetSurfaceResolution(_connection, wid, sid, 2.0);
  SLSSetSurfaceColorSpace(_connection, wid, sid, context.colorSpace);

  SLSBindSurface(_connection, wid, sid, 4, 0, context.contextId);
  SLSOrderSurface(_connection, wid, sid, 1, 0);

  [CATransaction commit];
Bellavene commented 1 year ago

Can we at least get rid of the gray(alpha channel) background appearing while animations are on?

JoshSald commented 9 months ago

@FelixKratz after https://github.com/koekeishiya/yabai/issues/1889 what has been your solution for this? I'd completely forgotten to update for a while and missed that announcement much to my surprsie. Does your Janky Borders project facilitate blurred windows?