Compare commits

...
Sign in to create a new pull request.

53 commits

Author SHA1 Message Date
Yaroslav
15a8fd21be fix: crash when moving to scratchpad tiled window (#202) 2023-07-23 23:01:01 -04:00
Basil
5636008aa5 Update README.md (#204) 2023-07-23 23:01:01 -04:00
Sntx_
a8ba60bc73 README: Inline the repology badge and swayfx mascot (#193)
* README: Inline the repology badge and swayfx mascot

* README: Removed unused style from html tag
2023-07-23 23:01:01 -04:00
William McKinnon
b51d999cc4 ver: bump to 0.3.2 2023-07-23 23:01:01 -04:00
Evy Garden
638603bad3 Fix toplevel borders (#171)
* added check for smart

* expose gaps_to_edge

* add smart variable
2023-07-23 23:01:00 -04:00
William McKinnon
30bd277a2e updated branding 2023-07-23 23:01:00 -04:00
Erik Reider
12f40a396b Fixed blur/surfaces dst_box not being offset by the titlebar height (#185) 2023-07-23 23:01:00 -04:00
RAR27
20a4be295e fix: crash when splitting inside stacking container (#187) 2023-07-23 23:01:00 -04:00
rti
8f0b76ac72 fix: consider dim introduced transparency for blur (#184)
The blur rendering logic includes the optimization to render blur only
for transparent surfaces. This patch considers surfaces as transparent
also when the transparency is only introduced by the dim color.

We can now have windows, that are opaque by default become transparent
with blurred background as soon as they loose focus.

Example configuration:

```
blur on
blur_passes 3
blur_radius 5

default_dim_inactive 0.15
dim_inactive_colors.unfocused #00000000
```
2023-07-23 23:01:00 -04:00
RAR27
8a83db8edd fix: crash when moving tabbed container to scratchpad (#182)
when `scratchpad_minimize` enabled
2023-07-23 23:01:00 -04:00
William McKinnon
ba8da50fe0 ver: bump to 0.3.1 2023-07-23 23:01:00 -04:00
William McKinnon
9e00c176c5 added layer namespace information 2023-07-23 23:01:00 -04:00
William McKinnon
eb94643f03 default scratchpad_minimize to false and add warning 2023-07-23 23:01:00 -04:00
Erik Reider
141be09611 fix: update stencil if the output size changes (#178) 2023-07-23 23:01:00 -04:00
RAR27
44312080f4 fix: crash when splitting inside tabbed container (#180) 2023-07-23 23:01:00 -04:00
Erik Reider
b24f012edf fix: blur not being able to blur edges of damage (#168) 2023-07-23 23:01:00 -04:00
William McKinnon
27039feedd Update README.md 2023-07-23 23:01:00 -04:00
William McKinnon
868c995ee5 added blur-xray explanation 2023-07-23 23:01:00 -04:00
Ricardo Steijn
4ba271e2ce flake: remove libinput patch (#163)
This was backported to SwayFX in 3c2e38b
2023-07-23 23:01:00 -04:00
William McKinnon
527ecb056a upstream: ipc: add LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM entry 2023-07-23 23:01:00 -04:00
William McKinnon
e0907376fc fix: layer old damage not being offset by the monitor layout coords 2023-07-23 23:01:00 -04:00
William McKinnon
085f37d6d1 bump version to 0.3 2023-07-23 23:01:00 -04:00
William McKinnon
8cce675a08 updated README to reflect 0.3 2023-07-23 23:01:00 -04:00
Erik Reider
f2b5518196 Fix layer surface damage not being extended if using effects (#160) 2023-07-23 23:01:00 -04:00
William McKinnon
62b22d757d fix: maybe-uninitialized error 2023-07-23 23:01:00 -04:00
Erik Reider
9f4f88b0cd Add blur, shadow, and corner radius to layer-shell surfaces (#144)
Co-authored-by: Will McKinnon <contact@willmckinnon.com>
2023-07-23 23:01:00 -04:00
William McKinnon
e469583b0d improved blur optimization checks 2023-07-23 23:01:00 -04:00
William McKinnon
2054450dd2 add link to fedora copr package, remove extra lines about discord server 2023-07-23 23:01:00 -04:00
Erik Reider
6b94df785b Fix damage being extended after clearing the previous frame (#158)
* Fix damage being extended after clearing the previous frame

* Ensure that damage expansion only occurs if it's smaller than the monitor
2023-07-23 23:01:00 -04:00
Erik Reider
61f208e414 Flipped the order of which the stencil add function is called (#157) 2023-07-23 23:01:00 -04:00
Erik Reider
177c631ced Move stencil into each framebuffer (#156)
* Move stencil into each framebuffer

Also fixes the stencil being added to the wrong framebuffer

* Initialize texture members on framebuffer init

* removed bind arg

* renamed init to create, changed existing create to update

* moved stencil buffer creation to new function

* removed some now misleading comments

---------

Co-authored-by: William McKinnon <contact@willmckinnon.com>
2023-07-23 23:01:00 -04:00
William McKinnon
5e503231ac removed stdint import 2023-05-15 01:20:27 -04:00
William McKinnon
00213d548a Merge remote-tracking branch 'origin/master' into blur_simplify 2023-05-15 01:13:03 -04:00
William McKinnon
f94e24709f ensure damage doesnt expand beyond output size 2023-05-14 21:04:17 -04:00
William McKinnon
e6d1ee8b4d moved blur damage to damage_surface_iterator 2023-05-14 21:03:58 -04:00
William McKinnon
690f5c37ff moved extended damage to the top of output_render 2023-05-14 18:21:15 -04:00
William McKinnon
13d368544d moved initial damage expansion to output.c 2023-05-12 12:18:42 -04:00
William McKinnon
b8c668bb44 removed unneeded conditional 2023-05-12 12:15:48 -04:00
Erik Reider
74ee0b7d26 Fixed damage highlight not clearing correct framebuffer 2023-05-10 12:28:57 +02:00
Erik Reider
57b2e2f90a Fixed blur artifacting 2023-05-10 12:11:24 +02:00
William McKinnon
e0415f15bf moved get_blur_size back to original spot (reduce diff size) 2023-05-10 01:34:18 -04:00
William McKinnon
58fd78f389 returned extended damage 2023-05-10 01:32:37 -04:00
William McKinnon
e065838dd9 removed uneeded parameter from get_main_buffer_blur 2023-05-10 00:27:06 -04:00
William McKinnon
2b286dfe8f added back region expansion 2023-05-07 12:42:09 -04:00
William McKinnon
139c33f7c5 renamed ws iterator function 2023-05-07 00:54:19 -04:00
William McKinnon
00694dd059 moved workspace optimized check function to workspace.c 2023-05-07 00:51:03 -04:00
William McKinnon
171e6c59b1 removed unneeded damage scale 2023-05-07 00:19:24 -04:00
William McKinnon
c0d72c357b cleaned up render_output 2023-05-07 00:19:24 -04:00
William McKinnon
88a41baa30 removed extraneous fx_renderer_scissor 2023-05-07 00:19:24 -04:00
William McKinnon
f7851c21ae moved damage expansion to output.c 2023-05-07 00:19:24 -04:00
William McKinnon
434f3ddfce simplified optimized blur check 2023-05-07 00:19:24 -04:00
William McKinnon
1dff31248b removed has_blur 2023-05-07 00:19:24 -04:00
William McKinnon
621906481a suplified conditional in find_con_effect_iterator 2023-05-07 00:19:24 -04:00
42 changed files with 1026 additions and 354 deletions

View file

@ -1,12 +1,14 @@
<div align = center>
# SwayFX: A Beautiful Sway Fork
![swayfx logo](assets/swayfx_logo.svg)
<hr>
https://discord.gg/qsSx397rkh
</div>
![swayfx_screenshot](assets/swayfx_screenshot.jpg)
![swayfx screenshot](assets/swayfx_screenshot.jpg)
Sway is an incredible window manager, and certainly one of the most well established wayland window managers. However, it is restricted to only include the functionality that existed in i3. This fork ditches the simple wlr_renderer, and replaces it with our fx_renderer, capable of rendering with fancy GLES2 effects. This, along with a couple of minor changes, expands sway's featureset to include the following:
+ **Blur**
@ -17,20 +19,36 @@ Sway is an incredible window manager, and certainly one of the most well establi
+ **Scratchpad treated as minimize**: Allows docks, or panels with a taskbar, to correctly interpret minimize / unminimize requests ([thanks to LCBCrion](https://github.com/swaywm/sway/issues/6457))
+ **nixify the repo**: Allows nixos users to easily contribute to and test this project
<span>
<img src="https://repology.org/badge/vertical-allrepos/swayfx.svg" height="282"/>
<img src="assets/swayfx_mascot.png" width="500"/>
</span>
[SwayFX is also available on the Fedora copr](https://copr.fedorainfracloud.org/coprs/swayfx/swayfx/)
## New Configuration Options
+ Window blur:
- `blur enable|disable`
- `blur_xray enable|disable`: this will set floating windows to blur based on the background, not the windows below. You probably want to set this to `disable` :)
- `blur_passes <integer value 0 - 10>`
- `blur_radius <integer value 0 - 10>`
+ Corner radius: `corner_radius <val>`
+ Smart corner radius: `smart_corner_radius enable|disable`
+ Window shadows:
- `shadows enable|disable`
- `shadows_on_csd enable|disable` (**Note**: The shadow might not fit some windows)
- `shadow_blur_radius <integer value 0 - 100>`
- `shadow_color <hex color with alpha> ex, #0000007F`
+ Window blur: *ONLY ON SWAYFX-GIT, NOT YET RELEASED*
- `blur enable|disable`
- `blur_xray enable|disable`
- `blur_passes <integer value 0 - 10>`
- `blur_radius <integer value 0 - 10>`
+ LayerShell effects (to blur panels / notifications etc):
- `layer_effects <layer namespace> <effects>`
- The current layer namespaces can be shown with `swaymsg -r -t get_outputs | jq '.[0].layer_shell_surfaces | .[] | .namespace'`
- Example: `layer_effects "waybar" blur enable; shadows enable; corner_radius 6`
- Note: If an application uses gtk, its namespace is likely to be "gtk-layer-shell"
- SwayIPC Example: `swaymsg "layer_effects 'waybar' 'blur enable; shadows enable; corner_radius 6'"`
- Available Effects:
- `blur <enable|disable>`
- `shadows <enable|disable>`
- `corner_radius <int>`
+ Dim unfocused windows:
- `default_dim_inactive <float value 0.0 - 1.0>`
- `for_window [CRITERIA_HERE] dim_inactive <float value 0.0 - 1.0>`
@ -38,16 +56,14 @@ Sway is an incredible window manager, and certainly one of the most well establi
- `dim_inactive_colors.urgent <hex color> ex, #900000FF`
+ Application saturation: `for_window [CRITERIA HERE] saturation <set|plus|minus> <val 0.0 <-> 2.0>`
+ Keep/remove separator border between titlebar and content: `titlebar_separator enable|disable`
+ Treat Scratchpad as minimized: `scratchpad_minimize enable|disable`
+ Treat Scratchpad as minimized: `scratchpad_minimize enable|disable`: **we recommend keeping this setting off, as there are many kinks to iron out here**
## Roadmap
+ fade in / out animations
+ window movement animations
## Installation
[![Packaging status](https://repology.org/badge/vertical-allrepos/swayfx.svg)](https://repology.org/project/swayfx/versions)
## Compiling From Source
### Nix
@ -64,7 +80,7 @@ You can also bring up a development shell and follow the build instructions belo
nix develop
```
### Compiling from Source
### Manual Steps
Install dependencies:
@ -104,4 +120,13 @@ Here's a quick outline of where most of our changes lie vs the main sway reposit
+ `sway/desktop/fx_renderer.c`: the meat and potatoes of this project, structured as similarly to wlr_renderer as possible
+ `sway/desktop/shaders`: where all of the shaders that fx_renderer uses live
Please join our (for the time being very small) Discord server for development chatter! https://discord.gg/R5hYhC2BFg
## Acknowledgements
The SwayFX team would like to first and foremost thank the maintainers and contributors of the Sway window manager. We are but a humble group of Sway enthusiasts who wanted to expand upon your creation.
We would also like to thank the talented artists in our community for contibuting the visual assets that give this project charm:
+ pkdesuwu and honchokomodo for creating the swayfx mascot: https://twitter.com/pkdesuwu/status/1664517033017368576
+ spooky_skeleton for the swayfx logo, and [Basil](https://basil.cafe) for making some fine adjustments to it
Lastly, we would like to thank you, the community, for enjoying and using window manager that we have spent so much time maintaining.

191
assets/swayfx_logo.svg Normal file
View file

@ -0,0 +1,191 @@
<svg width="460" height="540" viewBox="0 0 460 540" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_dd_1507_417)">
<path d="M115.288 499.64C109.869 499.64 104.792 498.616 100.056 496.568C99.544 496.355 99.1173 496.013 98.776 495.544C98.4347 495.032 98.264 494.499 98.264 493.944C98.264 493.219 98.4987 492.6 98.968 492.088C99.48 491.533 100.12 491.256 100.888 491.256C101.315 491.256 101.72 491.341 102.104 491.512C106.029 493.261 110.232 494.136 114.712 494.136C122.179 494.136 125.912 491.683 125.912 486.776C125.912 485.496 125.421 484.429 124.44 483.576C123.501 482.723 122.328 482.061 120.92 481.592C119.512 481.08 117.507 480.483 114.904 479.8C111.448 478.904 108.653 478.051 106.52 477.24C104.387 476.387 102.552 475.128 101.016 473.464C99.48 471.8 98.712 469.581 98.712 466.808C98.712 464.376 99.352 462.179 100.632 460.216C101.912 458.211 103.789 456.632 106.264 455.48C108.781 454.285 111.789 453.688 115.288 453.688C119.981 453.688 124.227 454.392 128.024 455.8C129.219 456.227 129.816 457.08 129.816 458.36C129.816 459.043 129.581 459.661 129.112 460.216C128.643 460.771 128.024 461.048 127.256 461.048C127 461.048 126.659 460.963 126.232 460.792C122.904 459.64 119.469 459.064 115.928 459.064C112.557 459.064 109.805 459.704 107.672 460.984C105.581 462.264 104.536 464.056 104.536 466.36C104.536 467.896 105.027 469.155 106.008 470.136C107.032 471.075 108.291 471.821 109.784 472.376C111.32 472.888 113.389 473.443 115.992 474.04C119.363 474.851 122.072 475.661 124.12 476.472C126.211 477.283 127.981 478.541 129.432 480.248C130.925 481.955 131.672 484.259 131.672 487.16C131.672 489.549 130.989 491.704 129.624 493.624C128.259 495.501 126.339 496.973 123.864 498.04C121.389 499.107 118.531 499.64 115.288 499.64ZM147.159 499.32C146.306 499.32 145.538 499.064 144.855 498.552C144.172 498.04 143.703 497.4 143.447 496.632L134.359 470.008C134.231 469.624 134.167 469.261 134.167 468.92C134.167 468.109 134.444 467.427 134.999 466.872C135.554 466.317 136.236 466.04 137.047 466.04C137.644 466.04 138.178 466.211 138.647 466.552C139.159 466.851 139.5 467.256 139.671 467.768L147.159 492.408L154.583 468.344C154.796 467.661 155.18 467.107 155.735 466.68C156.332 466.253 156.994 466.04 157.719 466.04C158.444 466.04 159.084 466.253 159.639 466.68C160.236 467.107 160.642 467.661 160.855 468.344L168.279 492.408L175.767 467.768C175.938 467.256 176.258 466.851 176.727 466.552C177.239 466.211 177.794 466.04 178.391 466.04C179.202 466.04 179.884 466.317 180.439 466.872C180.994 467.427 181.271 468.109 181.271 468.92C181.271 469.261 181.207 469.624 181.079 470.008L171.991 496.632C171.735 497.4 171.266 498.04 170.583 498.552C169.9 499.064 169.132 499.32 168.279 499.32C167.426 499.32 166.658 499.064 165.975 498.552C165.292 498.04 164.802 497.379 164.503 496.568L157.719 475.384L150.935 496.568C150.636 497.379 150.146 498.04 149.463 498.552C148.78 499.064 148.012 499.32 147.159 499.32ZM196.064 499.64C194.186 499.64 192.437 499.256 190.816 498.488C189.237 497.72 187.978 496.611 187.04 495.16C186.101 493.667 185.632 491.96 185.632 490.04C185.632 486.883 186.869 484.365 189.344 482.488C191.861 480.611 195.53 479.672 200.352 479.672H208.096V479.16C208.096 476.344 207.392 474.317 205.984 473.08C204.618 471.843 202.464 471.224 199.52 471.224C197.898 471.224 196.448 471.352 195.168 471.608C193.93 471.864 192.544 472.248 191.008 472.76C190.666 472.845 190.389 472.888 190.176 472.888C189.536 472.888 188.981 472.653 188.512 472.184C188.042 471.715 187.808 471.139 187.808 470.456C187.808 469.304 188.362 468.493 189.472 468.024C193.098 466.488 196.789 465.72 200.544 465.72C203.488 465.72 205.962 466.317 207.968 467.512C210.016 468.707 211.509 470.264 212.448 472.184C213.429 474.061 213.92 476.109 213.92 478.328V496.44C213.92 497.251 213.621 497.933 213.024 498.488C212.469 499.043 211.786 499.32 210.976 499.32C210.165 499.32 209.482 499.043 208.928 498.488C208.373 497.933 208.096 497.251 208.096 496.44V494.776C204.938 498.019 200.928 499.64 196.064 499.64ZM198.24 494.52C200.117 494.52 201.93 494.072 203.68 493.176C205.429 492.237 206.901 491.085 208.096 489.72V484.344H201.12C194.677 484.344 191.456 486.029 191.456 489.4C191.456 490.936 191.968 492.173 192.992 493.112C194.058 494.051 195.808 494.52 198.24 494.52ZM230.415 514.04C229.647 514.04 228.985 513.763 228.431 513.208C227.919 512.653 227.663 511.992 227.663 511.224C227.663 510.883 227.727 510.541 227.855 510.2L232.015 499.512L219.983 470.2C219.812 469.773 219.727 469.368 219.727 468.984C219.727 468.173 220.004 467.491 220.559 466.936C221.113 466.339 221.796 466.04 222.607 466.04C223.204 466.04 223.737 466.211 224.207 466.552C224.719 466.893 225.081 467.32 225.295 467.832L235.151 492.28L245.199 467.96C245.753 466.68 246.649 466.04 247.887 466.04C248.697 466.04 249.38 466.339 249.935 466.936C250.489 467.491 250.767 468.173 250.767 468.984C250.767 469.368 250.703 469.731 250.575 470.072L233.103 512.056C232.505 513.379 231.609 514.04 230.415 514.04Z" fill="#49D1F8"/>
</g>
<g filter="url(#filter1_dd_1507_417)">
<path d="M275.784 489C275.784 488.872 275.784 488.744 275.848 488.552C273.928 488.936 272.072 489.384 270.216 489.832C268.68 490.152 267.144 490.536 265.608 490.984C265.224 491.048 264.904 491.304 264.584 491.432C263.304 491.688 262.088 491.944 260.872 491.56C260.808 491.56 260.744 491.56 260.744 491.56C260.424 491.304 260.168 491.048 259.848 490.792C260.104 490.472 260.296 490.088 260.616 489.96C262.792 488.744 265.16 488.04 267.592 487.4C270.408 486.696 273.288 485.992 276.168 485.288C276.552 485.16 276.744 484.968 276.872 484.584C277.32 482.536 277.896 480.488 278.28 478.44C278.472 477.672 278.344 476.776 278.216 475.944C277.192 470.376 273.928 466.664 268.68 464.616C265.736 463.464 262.728 462.824 259.656 462.184C257.928 461.8 256.2 461.288 254.472 460.776C253.896 460.648 253.384 460.328 252.936 459.944C251.912 459.176 251.656 458.088 252.36 457C252.936 456.168 253.64 455.4 254.408 454.76C256.84 452.84 259.592 451.432 262.344 450.152C268.936 447.016 275.848 444.648 282.888 442.6C291.784 439.912 300.808 437.736 309.896 436.008C317.704 434.536 325.448 433.192 333.256 431.784C334.344 431.592 335.432 431.336 336.52 431.08C336.904 431.016 337.224 430.824 337.608 430.696C339.336 429.928 341.064 429.864 342.856 430.632C343.88 431.144 343.88 431.784 343.176 432.744C342.536 433.64 341.704 433.64 340.744 433.704C339.848 433.832 338.952 434.152 338.056 434.344C333.64 435.112 329.224 435.88 324.808 436.648C309.448 439.208 294.28 442.216 279.432 447.016C273.992 448.808 268.488 450.728 263.368 453.352C261.64 454.248 260.04 455.336 258.376 456.36C257.928 456.68 257.544 457.128 257.224 457.512C256.52 458.408 256.712 459.112 257.736 459.432C258.952 459.88 260.168 460.2 261.384 460.456C264.648 461.288 267.976 461.992 271.176 463.272C273.736 464.296 276.232 465.576 278.088 467.688C278.856 468.584 279.496 469.608 280.2 470.632C280.456 469.736 280.712 468.776 280.904 467.816C282.376 462.184 283.72 456.488 285.576 450.92C285.96 449.832 286.472 448.68 286.92 447.592C287.24 446.568 288.008 446.12 288.968 446.12C289.736 446.12 290.568 446.184 291.272 446.376C292.296 446.696 292.488 447.144 292.296 448.168C291.848 450.28 291.4 452.392 290.952 454.568C290.696 455.592 290.568 456.616 290.312 457.64C289.992 459.048 289.544 460.456 289.224 461.928C287.624 468.904 286.088 475.88 284.488 482.856C284.424 482.984 284.424 483.176 284.36 483.368C284.872 483.304 285.32 483.176 285.768 483.112C288.776 482.536 291.72 481.96 294.728 481.448C296.072 481.192 297.416 481.192 298.76 481.576C299.208 481.768 299.72 482.024 300.104 482.344C300.616 482.792 300.616 483.304 300.04 483.752C299.784 483.944 299.528 484.136 299.272 484.264C296.904 485.416 294.536 486.376 291.976 486.696C290.632 486.888 289.288 486.888 288.072 486.184C287.944 486.12 287.752 486.12 287.56 486.184C286.344 486.376 285.128 486.632 283.912 486.888C283.72 486.952 283.528 487.144 283.464 487.336C281.992 493.224 280.52 499.112 279.112 505.064C278.792 506.344 278.6 507.624 278.28 508.904C277.64 511.144 276.296 513.064 275.08 515.048C274.888 515.368 274.376 515.624 273.928 515.688C272.904 515.944 271.944 515.816 270.984 515.304C270.6 515.112 270.344 514.856 270.472 514.344C271.88 507.624 273.224 500.84 274.632 494.056C274.952 492.328 275.4 490.664 275.784 489ZM326.957 480.744C326.445 479.912 325.997 479.08 325.485 478.184C324.845 478.888 324.269 479.592 323.693 480.232C317.869 487.144 312.365 494.312 307.309 501.8C306.221 503.4 305.389 505.128 304.429 506.856C304.429 506.92 304.365 506.984 304.365 507.048C303.981 507.496 302.701 507.688 301.869 507.304C301.229 507.048 300.909 506.472 301.165 505.768C301.421 504.872 301.741 504.04 302.125 503.272C304.685 498.6 307.181 493.928 310.189 489.64C313.453 484.968 317.101 480.616 320.749 476.264C321.389 475.496 322.029 474.728 322.733 473.96C323.053 473.64 323.053 473.384 322.861 473C320.685 468.52 318.701 463.976 317.357 459.24C316.781 457.192 316.269 455.08 315.885 453.032C315.565 451.304 316.077 450.728 317.741 450.6C318.061 450.6 318.317 450.6 318.637 450.6C319.661 450.664 320.429 451.112 320.813 452.2C322.157 455.912 323.565 459.624 325.037 463.272C325.677 464.936 326.381 466.6 327.085 468.2C327.149 468.392 327.213 468.52 327.341 468.712C327.597 468.392 327.789 468.2 328.045 467.944C335.597 459.432 343.853 451.496 352.237 443.816C354.477 441.832 356.589 439.848 358.829 437.864C360.685 436.328 362.861 435.752 365.293 436.328C366.957 436.776 367.021 437.8 366.125 439.08C365.677 439.848 364.909 440.424 364.269 441C359.021 445.608 353.773 450.216 348.525 454.824C342.125 460.584 336.045 466.664 330.157 473C329.453 473.768 329.453 473.448 329.965 474.408C335.085 484.584 340.845 494.376 347.885 503.336C349.037 504.872 350.189 506.408 351.341 507.944C351.789 508.456 351.661 508.776 351.021 508.968C349.997 509.224 349.037 509.096 348.205 508.264C339.885 500.072 332.589 491.048 326.957 480.744Z" fill="#FF7070"/>
</g>
<g filter="url(#filter2_dd_1507_417)">
<path d="M229.232 390.316L230.299 390.722L231.367 390.316L432.8 313.701V338.646L230.301 415.901L28 338.646V313.665L229.232 390.316Z" stroke="#FF7070" stroke-width="6"/>
</g>
<g filter="url(#filter3_dd_1507_417)">
<path d="M66.5 289.434C62.7345 290.794 58.9314 292.097 55.16 293.389C50.774 294.892 46.43 296.38 42.181 297.947C40.962 298.369 37.071 299.857 33.363 301.287L230.301 376.302L427.398 301.336C417.116 297.431 406.906 293.62 396.714 289.815C378.857 283.15 361.052 276.504 343.002 269.404L342.992 269.4C313.96 257.867 283.919 249.923 253.174 255.757C245.264 257.339 237.513 259.546 229.65 261.785C228.961 261.981 228.272 262.177 227.582 262.373C219.05 264.796 210.378 267.19 201.493 268.671L201.474 268.674L201.455 268.677C193.53 269.893 185.838 269.246 178.403 268.379C177.111 268.229 175.83 268.072 174.557 267.917C168.399 267.164 162.414 266.432 156.242 266.512C139.521 266.761 122.728 269.589 106.5 274.378" stroke="#F5E755" stroke-width="6" stroke-linecap="round"/>
</g>
<g filter="url(#filter4_dd_1507_417)">
<path d="M186.455 188.736C187.159 188.349 187.86 187.965 188.563 187.579C207.223 177.396 227.746 165.892 242.459 150.898C251.254 141.935 257.901 131.804 260.791 120L251.073 117C247.695 132.008 236.928 144.049 224.313 153.602C209.23 165.045 192.372 174.082 175.789 182.972L175.783 182.975L175.704 183.017C169.762 186.203 163.856 189.369 158.078 192.623C117.392 215.759 76.605 251.626 78.595 301.132C78.87 304.42 81.46 306.187 84.388 306.187C85.841 306.187 87.104 305.72 87.932 304.98C88.689 304.304 89.288 303.229 89.204 301.455L89.203 301.443C87.161 254.895 123.715 225.552 159.427 204.058C160.354 203.5 163 204.058 163 204.058C199.6 211.687 238.997 207.877 272.5 192.731L249.5 190.607C227.885 197.443 204.884 199.835 182.222 197.282C180.924 197.136 179.87 196.166 179.615 194.885C179.361 193.603 179.966 192.305 181.11 191.674C182.911 190.681 184.696 189.701 186.455 188.736Z" stroke="#FEDEDC" stroke-width="6" stroke-linejoin="round"/>
</g>
<g filter="url(#filter5_dd_1507_417)">
<path d="M258.177 47.973C252.162 50.673 246.09 53.167 239.968 55.682C238.658 56.22 237.346 56.759 236.031 57.301C228.599 60.366 221.125 63.522 213.783 67.116C211.358 68.297 208.326 69.991 205.009 71.846C204.329 72.225 203.638 72.612 202.937 73.002C198.761 75.327 194.159 77.839 189.465 80.063C184.763 82.292 180.055 84.189 175.681 85.314C171.277 86.447 167.461 86.731 164.416 85.999C163.059 85.658 161.842 85.108 161.121 84.507L161.028 84.43L160.93 84.361C159.252 83.177 158.253 81.222 158.038 78.831C157.822 76.42 158.44 73.796 159.747 71.698L159.761 71.674L159.775 71.651C162.102 67.758 166.125 63.75 170.814 60.072C175.466 56.423 180.586 53.243 184.901 50.965L184.913 50.958C196.538 44.752 208.65 39.73 221.148 35.99C222.596 35.569 224.039 35.145 225.479 34.723C236.493 31.488 247.298 28.316 258.401 27.197L258.416 27.195L258.431 27.194C261.326 26.872 267.423 26.828 272.629 28.046C275.243 28.657 277.355 29.524 278.732 30.606C279.998 31.602 280.558 32.684 280.502 34.094L280.501 34.135L280.5 34.175C280.489 35.057 279.977 36.236 278.413 37.723C276.878 39.182 274.673 40.603 272.119 41.943C268.586 43.797 264.966 45.23 261.993 46.408C260.537 46.985 259.236 47.5 258.177 47.973Z" stroke="#C7E133" stroke-width="6"/>
</g>
<g filter="url(#filter6_dd_1507_417)">
<path d="M389.71 76.516L390.083 76.265C392.8 74.437 395.722 72.465 398.535 70.44C401.352 68.412 404.008 66.367 406.196 64.405C408.422 62.408 409.983 60.655 410.79 59.232C412.739 55.784 411.898 52.084 408.781 48.435C405.631 44.747 400.553 41.719 395.715 40.407C385.786 37.722 375.207 37.265 364.398 37.709C357.435 37.996 350.552 38.641 343.709 39.283C339.838 39.646 335.981 40.008 332.129 40.303H332.125C308.736 42.065 284.825 50.104 263.934 59.999C263.119 60.423 262.33 60.819 261.56 61.205L256.484 63.919C250.793 67.157 245.838 70.557 242.166 74.678C236.743 81.094 235.556 86.226 236.371 90.213C237.206 94.303 240.319 98.067 245.348 101.301C255.444 107.793 271.605 111.042 283.846 110.416C285.729 110.319 287.621 110.202 289.52 110.065C290.985 109.959 292.312 110.93 292.654 112.36C292.665 112.409 292.678 112.458 292.691 112.508C294.263 117.829 299.155 122.194 304.922 124.057C310.84 125.969 317.441 125.916 324.113 125.518C348.176 123.939 371.949 118.316 394.144 109.044C394.155 109.039 394.166 109.034 394.177 109.03C394.187 109.026 394.197 109.022 394.207 109.018C398.721 107.252 402.432 105.467 405.227 102.452C407.812 99.224 408.756 95.346 407.322 92.464C406.41 90.681 404.774 89.417 402.499 88.555C400.193 87.681 397.434 87.305 394.697 87.21L394.67 87.209C390.951 87.047 387.255 87.235 383.539 87.619C382.173 87.76 380.887 86.957 380.414 85.668C379.941 84.38 380.403 82.935 381.536 82.16L389.71 76.516Z" stroke="#C7E133" stroke-width="6" stroke-linejoin="round"/>
</g>
<g filter="url(#filter7_dd_1507_417)">
<path d="M311.562 204.936C311.265 203.386 311.733 201.847 313.059 200.137C314.398 198.409 316.403 196.801 318.52 195.437C324.363 191.703 340.499 183.83 356.211 179.635C364.083 177.534 371.566 176.435 377.48 177.079C383.336 177.716 387.067 179.953 388.719 184.037C389.803 186.722 389.839 188.968 389.239 190.918C388.624 192.919 387.254 194.88 385.078 196.782C380.663 200.642 373.486 203.776 365.152 206.152C356.898 208.505 347.846 210.022 339.975 210.837C332.041 211.659 325.555 211.741 322.38 211.336L322.37 211.335L322.359 211.334C319.712 211.014 317.009 210.272 314.952 209.096C312.91 207.927 311.819 206.534 311.562 204.936Z" stroke="#C7E133" stroke-width="6"/>
</g>
<g filter="url(#filter8_dd_1507_417)">
<path d="M187.525 143.975C182.106 145.895 174.583 144.865 169.358 141.584C166.794 139.974 165.019 137.968 164.219 135.783C163.45 133.681 163.455 131.074 165.072 127.877C166.558 124.994 169.678 121.27 173.963 117.393C178.205 113.554 183.406 109.731 188.842 106.615C194.297 103.487 199.861 101.144 204.839 100.147C209.861 99.142 213.86 99.583 216.651 101.418L216.665 101.427L216.678 101.435C219.596 103.312 221.015 107.453 220.433 111.366C219.484 117.612 214.631 124.654 207.988 130.872C201.407 137.03 193.586 141.893 187.525 143.975Z" stroke="#C7E133" stroke-width="6"/>
</g>
<g filter="url(#filter9_dd_1507_417)">
<path d="M261.356 181.033C259.417 180.802 257.464 180.358 255.939 179.615C254.438 178.884 253.669 178.031 253.386 177.091C253.113 176.075 253.391 174.914 254.643 173.448C255.916 171.959 257.877 170.571 259.92 169.455C267.612 165.388 275.796 161.94 284.175 159.3C284.412 159.225 284.64 159.121 284.852 158.989C285.052 158.865 285.254 158.747 285.457 158.634C285.474 158.625 285.491 158.615 285.508 158.606C308.412 145.294 335.096 138.705 361.545 138.312C361.571 138.311 361.598 138.311 361.625 138.309C363.725 138.222 365.9 138.521 367.51 139.209C369.077 139.878 369.686 140.693 369.83 141.539C369.928 142.366 369.647 143.291 368.788 144.387C367.904 145.517 366.587 146.579 365.174 147.491L365.168 147.495C355.489 153.77 344.655 158.785 333.358 162.04C332.058 162.415 331.169 163.614 331.189 164.967C331.2 165.707 331.074 166.432 330.816 167.095C329.552 170.158 326.275 171.992 321.875 173.593L321.84 173.605C302.684 180.838 281.769 183.475 261.356 181.033Z" stroke="#C7E133" stroke-width="6" stroke-linejoin="round"/>
</g>
<g filter="url(#filter10_dd_1507_417)">
<path d="M147.692 120.75L147.731 120.889C148.017 121.825 147.93 122.941 147.37 124.322C146.805 125.716 145.837 127.173 144.676 128.614C138.353 136.251 127.33 143.121 117.173 143.312C113.983 143.31 111.862 142.908 110.564 142.373C109.308 141.855 109.12 141.356 109.076 141.201C109.002 140.94 108.963 140.229 109.694 138.89C110.408 137.582 111.695 135.993 113.626 134.225L113.635 134.216C113.813 134.052 114.006 133.873 114.212 133.683C117.839 130.325 125.598 123.142 133.118 118.827C137.17 116.502 140.592 115.348 143.016 115.553C144.114 115.646 144.956 116.011 145.65 116.676C146.381 117.377 147.148 118.606 147.692 120.75Z" stroke="#C7E133" stroke-width="6"/>
</g>
<defs>
<filter id="filter0_dd_1507_417" x="74.264" y="429.688" width="200.502" height="108.352" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="6"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.286275 0 0 0 0 0.819608 0 0 0 0 0.972549 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1507_417"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="12"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.286275 0 0 0 0 0.819608 0 0 0 0 0.972549 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_1507_417" result="effect2_dropShadow_1507_417"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_1507_417" result="shape"/>
</filter>
<filter id="filter1_dd_1507_417" x="227.656" y="405.864" width="163.365" height="134.08" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="4"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.439216 0 0 0 0 0.439216 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1507_417"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="12"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.439216 0 0 0 0 0.439216 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_1507_417" result="effect2_dropShadow_1507_417"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_1507_417" result="shape"/>
</filter>
<filter id="filter2_dd_1507_417" x="1" y="285.312" width="458.8" height="157.8" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="6"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.439216 0 0 0 0 0.439216 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1507_417"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="12"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.439216 0 0 0 0 0.439216 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_1507_417" result="effect2_dropShadow_1507_417"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_1507_417" result="shape"/>
</filter>
<filter id="filter3_dd_1507_417" x="0.980591" y="226.794" width="458.862" height="176.718" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="6"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.960784 0 0 0 0 0.905882 0 0 0 0 0.333333 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1507_417"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="12"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.960784 0 0 0 0 0.905882 0 0 0 0 0.333333 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_1507_417" result="effect2_dropShadow_1507_417"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_1507_417" result="shape"/>
</filter>
<filter id="filter4_dd_1507_417" x="51.5248" y="90" width="247.975" height="243.187" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="6"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.996078 0 0 0 0 0.870588 0 0 0 0 0.862745 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1507_417"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="12"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.996078 0 0 0 0 0.870588 0 0 0 0 0.862745 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_1507_417" result="effect2_dropShadow_1507_417"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_1507_417" result="shape"/>
</filter>
<filter id="filter5_dd_1507_417" x="130.996" y="0.000289917" width="176.51" height="113.402" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="6"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.780392 0 0 0 0 0.882353 0 0 0 0 0.2 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1507_417"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="12"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.780392 0 0 0 0 0.882353 0 0 0 0 0.2 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_1507_417" result="effect2_dropShadow_1507_417"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_1507_417" result="shape"/>
</filter>
<filter id="filter6_dd_1507_417" x="209.137" y="10.5606" width="229.698" height="142.181" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="6"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.780392 0 0 0 0 0.882353 0 0 0 0 0.2 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1507_417"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="12"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.780392 0 0 0 0 0.882353 0 0 0 0 0.2 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_1507_417" result="effect2_dropShadow_1507_417"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_1507_417" result="shape"/>
</filter>
<filter id="filter7_dd_1507_417" x="284.475" y="149.896" width="132.153" height="88.6769" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="6"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.780392 0 0 0 0 0.882353 0 0 0 0 0.2 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1507_417"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="12"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.780392 0 0 0 0 0.882353 0 0 0 0 0.2 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_1507_417" result="effect2_dropShadow_1507_417"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_1507_417" result="shape"/>
</filter>
<filter id="filter8_dd_1507_417" x="136.721" y="72.6216" width="110.838" height="99.3166" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="6"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.780392 0 0 0 0 0.882353 0 0 0 0 0.2 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1507_417"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="12"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.780392 0 0 0 0 0.882353 0 0 0 0 0.2 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_1507_417" result="effect2_dropShadow_1507_417"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_1507_417" result="shape"/>
</filter>
<filter id="filter9_dd_1507_417" x="226.287" y="111.294" width="170.562" height="97.6261" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="6"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.780392 0 0 0 0 0.882353 0 0 0 0 0.2 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1507_417"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="12"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.780392 0 0 0 0 0.882353 0 0 0 0 0.2 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_1507_417" result="effect2_dropShadow_1507_417"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_1507_417" result="shape"/>
</filter>
<filter id="filter10_dd_1507_417" x="82.0369" y="88.53" width="92.8538" height="81.7821" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="6"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.780392 0 0 0 0 0.882353 0 0 0 0 0.2 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1507_417"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="12"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.780392 0 0 0 0 0.882353 0 0 0 0 0.2 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_1507_417" result="effect2_dropShadow_1507_417"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_1507_417" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 28 KiB

BIN
assets/swayfx_mascot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View file

@ -1,8 +1,8 @@
# Maintainer: Erik Reider <erik.reider@protonmail.com>
_pkgname=swayfx
pkgname="$_pkgname"
pkgver=0.2
pkgrel=2
pkgver=0.3.2
pkgrel=1
license=("MIT")
pkgdesc="SwayFX: Sway, but with eye candy!"
makedepends=(

View file

@ -4,11 +4,11 @@
# Change to current Sway base version!
%global SwayBaseVersion 1.8.1
# Change to current SwayFX tag!
%global Tag 0.2
%global Tag 0.3.2
Name: {{{ git_dir_name }}}
Version: %{Tag}
Release: 3%{?dist}
Release: 1%{?dist}
Summary: SwayFX: Sway, but with eye candy!
License: MIT
URL: https://github.com/WillPower3309/swayfx

View file

@ -41,7 +41,7 @@ dim_inactive_colors.unfocused #000000FF
dim_inactive_colors.urgent #900000FF
# Move minimized windows into Scratchpad (enable|disable)
scratchpad_minimize enable
scratchpad_minimize disable
### Output configuration
#

6
flake.lock generated
View file

@ -18,11 +18,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1683048793,
"narHash": "sha256-XA1Y70qnX08eAYFfq4k9L1Bdu37+zm28B32w7d+155o=",
"lastModified": 1684585791,
"narHash": "sha256-lYPboblKrchmbkGMoAcAivomiOscZCjtGxxTSCY51SM=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "e4ad893057db74091ed0e3edf509a72fb83051df",
"rev": "eea79d584eff53bf7a76aeb63f8845da6d386129",
"type": "github"
},
"original": {

View file

@ -22,8 +22,18 @@
in
{
overlays.default = final: prev: {
swayfx-unwrapped = prev.sway-unwrapped.overrideAttrs
(old: { src = builtins.path { path = prev.lib.cleanSource ./.; }; });
swayfx-unwrapped = prev.sway-unwrapped.overrideAttrs (old: {
src = builtins.path { path = prev.lib.cleanSource ./.; };
patches =
let
removePatches = [
"LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM.patch"
];
in
builtins.filter
(patch: !builtins.elem (patch.name or null) removePatches)
(old.patches or [ ]);
});
};
packages = nixpkgs.lib.genAttrs targetSystems (system:

View file

@ -97,6 +97,11 @@ void container_resize_tiled(struct sway_container *parent, uint32_t axis,
struct sway_container *container_find_resize_parent(struct sway_container *con,
uint32_t edge);
/**
* Effect handlers value parsers
*/
bool cmd_corner_radius_parse_value(char *arg, int* result);
/**
* Handlers shared by exec and exec_always.
*/
@ -157,6 +162,7 @@ sway_cmd cmd_input;
sway_cmd cmd_seat;
sway_cmd cmd_ipc;
sway_cmd cmd_kill;
sway_cmd cmd_layer_effects;
sway_cmd cmd_layout;
sway_cmd cmd_log_colors;
sway_cmd cmd_mark;

View file

@ -500,6 +500,8 @@ struct sway_config {
bool titlebar_separator;
bool scratchpad_minimize;
list_t *layer_criteria;
char *swaynag_command;
struct swaynag_instance swaynag_config_errors;
list_t *symbols;
@ -761,6 +763,12 @@ void translate_keysyms(struct input_config *input_config);
void binding_add_translated(struct sway_binding *binding, list_t *bindings);
int config_get_blur_size();
bool config_should_parameters_blur();
bool config_should_parameters_shadow();
/* Global config singleton. */
extern struct sway_config *config;

View file

@ -5,18 +5,23 @@
#include <stdbool.h>
#include <wlr/types/wlr_output.h>
#include "sway/desktop/fx_renderer/fx_stencilbuffer.h"
#include "sway/desktop/fx_renderer/fx_texture.h"
struct fx_framebuffer {
struct fx_texture texture;
GLuint fb;
struct fx_stencilbuffer stencil_buffer;
struct fx_texture texture;
};
struct fx_framebuffer fx_framebuffer_create();
void fx_framebuffer_bind(struct fx_framebuffer *buffer);
void fx_framebuffer_create(struct fx_framebuffer *buffer, int width, int height, bool bind);
void fx_framebuffer_update(struct fx_framebuffer *buffer, int width, int height);
void fx_framebuffer_add_stencil_buffer(struct fx_framebuffer *buffer, int width, int height);
void fx_framebuffer_release(struct fx_framebuffer *buffer);
#endif

View file

@ -33,6 +33,7 @@ struct decoration_data {
float *dim_color;
bool has_titlebar;
bool blur;
bool shadow;
};
struct blur_shader {
@ -119,8 +120,6 @@ struct fx_renderer {
int viewport_width, viewport_height;
GLuint stencil_buffer_id;
struct fx_framebuffer wlr_buffer; // Just the framebuffer used by wlroots
struct fx_framebuffer main_buffer; // The main FB used for rendering
struct fx_framebuffer blur_buffer; // Contains the blurred background for tiled windows
@ -162,8 +161,6 @@ void fx_renderer_fini(struct fx_renderer *renderer);
void fx_renderer_begin(struct fx_renderer *renderer, int width, int height);
void fx_renderer_end(struct fx_renderer *renderer);
void fx_renderer_clear(const float color[static 4]);
void fx_renderer_scissor(struct wlr_box *box);

View file

@ -0,0 +1,18 @@
#ifndef FX_STENCILBUFFER_H
#define FX_STENCILBUFFER_H
#include <GLES2/gl2.h>
#include <stdbool.h>
#include <wlr/render/wlr_texture.h>
struct fx_stencilbuffer {
GLuint rb;
int width;
int height;
};
struct fx_stencilbuffer fx_stencilbuffer_create();
void fx_stencilbuffer_release(struct fx_stencilbuffer *stencil_buffer);
#endif

View file

@ -13,6 +13,10 @@ struct fx_texture {
int height;
};
struct fx_texture fx_texture_from_wlr_texture(struct wlr_texture* tex);
struct fx_texture fx_texture_create();
struct fx_texture fx_texture_from_wlr_texture(struct wlr_texture *tex);
void fx_texture_release(struct fx_texture *texture);
#endif

View file

@ -0,0 +1,20 @@
#include <stdbool.h>
#include "sway/layers.h"
#include "sway/config.h"
struct layer_criteria {
char *namespace;
char *cmdlist;
};
void layer_criteria_destroy(struct layer_criteria *criteria);
bool layer_criteria_is_equal(struct layer_criteria *a, struct layer_criteria *b);
bool layer_criteria_already_exists(struct layer_criteria *criteria);
// Gathers all of the matching criterias for a specified `sway_layer_surface`
list_t *layer_criterias_for_sway_layer_surface(struct sway_layer_surface *sway_layer);
// Parses the `layer_criteria` and applies the effects to the `sway_layer_surface`
void layer_criteria_parse(struct sway_layer_surface *sway_layer, struct layer_criteria *criteria);

View file

@ -27,6 +27,10 @@ struct sway_layer_surface {
enum zwlr_layer_shell_v1_layer layer;
struct wl_list subsurfaces;
bool has_shadow;
bool has_blur;
int corner_radius;
};
struct sway_layer_popup {

View file

@ -13,6 +13,12 @@
struct sway_server;
struct sway_container;
struct render_data {
pixman_region32_t *damage;
struct wlr_box *clip_box;
struct decoration_data deco_data;
};
struct sway_output_state {
list_t *workspaces;
struct sway_workspace *active_workspace;

View file

@ -378,4 +378,6 @@ bool view_is_transient_for(struct sway_view *child, struct sway_view *ancestor);
void view_assign_ctx(struct sway_view *view, struct launcher_ctx *ctx);
bool gaps_to_edge(struct sway_view *view);
#endif

View file

@ -92,6 +92,8 @@ struct sway_output *workspace_output_get_highest_available(
void workspace_detect_urgent(struct sway_workspace *workspace);
bool should_workspace_have_blur(struct sway_workspace *ws);
void workspace_for_each_container(struct sway_workspace *ws,
void (*f)(struct sway_container *con, void *data), void *data);

View file

@ -1,7 +1,7 @@
project(
'sway',
'c',
version: '0.2',
version: '0.3.2',
license: 'MIT',
meson_version: '>=0.60.0',
default_options: [
@ -116,6 +116,11 @@ conf_data.set10('HAVE_LIBSYSTEMD', sdbus.found() and sdbus.name() == 'libsystemd
conf_data.set10('HAVE_LIBELOGIND', sdbus.found() and sdbus.name() == 'libelogind')
conf_data.set10('HAVE_BASU', sdbus.found() and sdbus.name() == 'basu')
conf_data.set10('HAVE_TRAY', have_tray)
conf_data.set10('HAVE_LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM', cc.has_header_symbol(
'libinput.h',
'LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM',
dependencies: libinput,
))
scdoc = dependency('scdoc', version: '>=1.9.2', native: true, required: get_option('man-pages'))
if scdoc.found()

View file

@ -84,6 +84,7 @@ static const struct cmd_handler handlers[] = {
{ "gaps", cmd_gaps },
{ "hide_edge_borders", cmd_hide_edge_borders },
{ "input", cmd_input },
{ "layer_effects", cmd_layer_effects },
{ "mode", cmd_mode },
{ "mouse_warping", cmd_mouse_warping },
{ "new_float", cmd_new_float },

View file

@ -12,7 +12,7 @@ struct cmd_results *cmd_blur(int argc, char **argv) {
struct sway_container *con = config->handler_context.container;
bool result = parse_boolean(argv[0], config->blur_enabled);
bool result = parse_boolean(argv[0], true);
if (con == NULL) {
config->blur_enabled = result;
} else {

View file

@ -4,15 +4,24 @@
#include "sway/tree/container.h"
#include "log.h"
bool cmd_corner_radius_parse_value(char *arg, int* result) {
char *inv;
int value = strtol(arg, &inv, 10);
if (*inv != '\0' || value < 0 || value > 99) {
return false;
}
*result = value;
return true;
}
struct cmd_results *cmd_corner_radius(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "corner_radius", EXPECTED_EQUAL_TO, 1))) {
return error;
}
char *inv;
int value = strtol(argv[0], &inv, 10);
if (*inv != '\0' || value < 0 || value > 99) {
int value = 0;
if (!cmd_corner_radius_parse_value(argv[0], &value)) {
return cmd_results_new(CMD_FAILURE, "Invalid size specified");
}

View file

@ -0,0 +1,33 @@
#include <ctype.h>
#include "log.h"
#include "stringop.h"
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/layer_criteria.h"
#include "sway/output.h"
#include "util.h"
struct cmd_results *cmd_layer_effects(int argc, char **argv) {
struct cmd_results *error = NULL;
if ((error = checkarg(argc, "layer_effects", EXPECTED_AT_LEAST, 2))) {
return error;
}
struct layer_criteria *criteria = malloc(sizeof(struct layer_criteria));
criteria->namespace = malloc(strlen(argv[0]) + 1);
strcpy(criteria->namespace, argv[0]);
criteria->cmdlist = join_args(argv + 1, argc - 1);
// Check if the rule already exists
if (layer_criteria_already_exists(criteria)) {
sway_log(SWAY_DEBUG, "layer_effect already exists: '%s' '%s'",
criteria->namespace, criteria->cmdlist);
layer_criteria_destroy(criteria);
return cmd_results_new(CMD_SUCCESS, NULL);
}
list_add(config->layer_criteria, criteria);
sway_log(SWAY_DEBUG, "layer_effect: '%s' '%s' added", criteria->namespace, criteria->cmdlist);
return cmd_results_new(CMD_SUCCESS, NULL);
}

View file

@ -17,7 +17,7 @@ struct cmd_results *cmd_shadows(int argc, char **argv) {
struct sway_container *con = config->handler_context.container;
bool result = parse_boolean(argv[0], config->shadow_enabled);
bool result = parse_boolean(argv[0], true);
if (con == NULL) {
config->shadow_enabled = result;
} else {

View file

@ -21,6 +21,7 @@
#include "sway/commands.h"
#include "sway/config.h"
#include "sway/criteria.h"
#include "sway/layer_criteria.h"
#include "sway/desktop/transaction.h"
#include "sway/swaynag.h"
#include "sway/tree/arrange.h"
@ -157,6 +158,12 @@ void free_config(struct sway_config *config) {
}
list_free(config->criteria);
}
if (config->layer_criteria) {
for (int i = 0; i < config->layer_criteria->length; ++i) {
layer_criteria_destroy(config->layer_criteria->items[i]);
}
list_free(config->layer_criteria);
}
list_free(config->no_focus);
list_free(config->active_bar_modifiers);
list_free_items_and_destroy(config->config_chain);
@ -352,7 +359,9 @@ static void config_defaults(struct sway_config *config) {
config->blur_params.radius = 5;
config->titlebar_separator = true;
config->scratchpad_minimize = true;
config->scratchpad_minimize = false;
if (!(config->layer_criteria = create_list())) goto cleanup;
// The keysym to keycode translation
struct xkb_rule_names rules = {0};
@ -1084,3 +1093,15 @@ void translate_keysyms(struct input_config *input_config) {
sway_log(SWAY_DEBUG, "Translated keysyms using config for device '%s'",
input_config->identifier);
}
int config_get_blur_size() {
return pow(2, config->blur_params.num_passes) * config->blur_params.radius;
}
bool config_should_parameters_blur() {
return config->blur_params.radius > 0 && config->blur_params.num_passes > 0;
}
bool config_should_parameters_shadow() {
return config->shadow_blur_sigma > 0 && config->shadow_color[3] > 0.0;
}

View file

@ -1,21 +1,30 @@
#include "log.h"
#include "sway/desktop/fx_renderer/fx_framebuffer.h"
#include "sway/desktop/fx_renderer/fx_stencilbuffer.h"
#include "sway/desktop/fx_renderer/fx_texture.h"
struct fx_framebuffer fx_framebuffer_create() {
return (struct fx_framebuffer) {
.fb = -1,
.stencil_buffer = fx_stencilbuffer_create(),
.texture = fx_texture_create(),
};
}
void fx_framebuffer_bind(struct fx_framebuffer *buffer) {
glBindFramebuffer(GL_FRAMEBUFFER, buffer->fb);
}
void fx_framebuffer_create(struct fx_framebuffer *buffer, int width, int height, bool bind) {
bool firstAlloc = false;
void fx_framebuffer_update(struct fx_framebuffer *buffer, int width, int height) {
bool first_alloc = false;
// Create a new framebuffer
if (buffer->fb == (uint32_t) -1) {
glGenFramebuffers(1, &buffer->fb);
firstAlloc = true;
first_alloc = true;
}
if (buffer->texture.id == 0) {
firstAlloc = true;
first_alloc = true;
glGenTextures(1, &buffer->texture.id);
glBindTexture(GL_TEXTURE_2D, buffer->texture.id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@ -24,7 +33,7 @@ void fx_framebuffer_create(struct fx_framebuffer *buffer, int width, int height,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
if (firstAlloc || buffer->texture.width != width || buffer->texture.height != height) {
if (first_alloc || buffer->texture.width != width || buffer->texture.height != height) {
glBindTexture(GL_TEXTURE_2D, buffer->texture.id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
@ -44,23 +53,43 @@ void fx_framebuffer_create(struct fx_framebuffer *buffer, int width, int height,
sway_log(SWAY_DEBUG, "Framebuffer created, status %i", status);
}
// Bind the default framebuffer
glBindTexture(GL_TEXTURE_2D, 0);
if (bind) {
fx_framebuffer_bind(buffer);
}
void fx_framebuffer_add_stencil_buffer(struct fx_framebuffer *buffer, int width, int height) {
bool first_alloc = false;
if (buffer->stencil_buffer.rb == (uint32_t) -1) {
glGenRenderbuffers(1, &buffer->stencil_buffer.rb);
first_alloc = true;
}
if (first_alloc || buffer->stencil_buffer.width != width || buffer->stencil_buffer.height != height) {
glBindRenderbuffer(GL_RENDERBUFFER, buffer->stencil_buffer.rb);
glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, buffer->stencil_buffer.rb);
buffer->stencil_buffer.width = width;
buffer->stencil_buffer.height = height;
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
sway_log(SWAY_ERROR, "Stencil buffer incomplete, couldn't create! (FB status: %i)", status);
return;
}
sway_log(SWAY_DEBUG, "Stencil buffer created, status %i", status);
}
}
void fx_framebuffer_release(struct fx_framebuffer *buffer) {
// Release the framebuffer
if (buffer->fb != (uint32_t) -1 && buffer->fb) {
glDeleteFramebuffers(1, &buffer->fb);
}
buffer->fb= -1;
buffer->fb = -1;
if (buffer->texture.id) {
glDeleteTextures(1, &buffer->texture.id);
}
buffer->texture.id = 0;
buffer->texture.width = -1;
buffer->texture.height = -1;
// Release the stencil buffer
fx_stencilbuffer_release(&buffer->stencil_buffer);
// Release the texture
fx_texture_release(&buffer->texture);
}

View file

@ -13,6 +13,7 @@
#include <wlr/util/box.h>
#include "log.h"
#include "sway/desktop/fx_renderer/fx_framebuffer.h"
#include "sway/desktop/fx_renderer/fx_renderer.h"
#include "sway/desktop/fx_renderer/matrix.h"
#include "sway/server.h"
@ -35,30 +36,6 @@ static const GLfloat verts[] = {
0, 1, // bottom left
};
static void create_stencil_buffer(GLuint *buffer_id, int width, int height) {
if (*buffer_id != (uint32_t) -1) {
return;
}
glGenRenderbuffers(1, buffer_id);
glBindRenderbuffer(GL_RENDERBUFFER, *buffer_id);
glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, *buffer_id);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
sway_log(SWAY_ERROR, "Stencilbuffer incomplete, couldn't create! (FB status: %i)", status);
return;
}
sway_log(SWAY_DEBUG, "Stencilbuffer created, status %i", status);
}
static void release_stencil_buffer(GLuint *buffer_id) {
if (*buffer_id != (uint32_t)-1 && buffer_id) {
glDeleteRenderbuffers(1, buffer_id);
}
*buffer_id = -1;
}
static GLuint compile_shader(GLuint type, const GLchar *src) {
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &src, NULL);
@ -288,12 +265,10 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl) {
return NULL;
}
renderer->main_buffer.fb = -1;
renderer->blur_buffer.fb = -1;
renderer->effects_buffer.fb = -1;
renderer->effects_buffer_swapped.fb = -1;
renderer->stencil_buffer_id = -1;
renderer->main_buffer = fx_framebuffer_create();
renderer->blur_buffer = fx_framebuffer_create();
renderer->effects_buffer = fx_framebuffer_create();
renderer->effects_buffer_swapped = fx_framebuffer_create();
renderer->blur_buffer_dirty = true;
@ -414,7 +389,6 @@ void fx_renderer_fini(struct fx_renderer *renderer) {
fx_framebuffer_release(&renderer->blur_buffer);
fx_framebuffer_release(&renderer->effects_buffer);
fx_framebuffer_release(&renderer->effects_buffer_swapped);
release_stencil_buffer(&renderer->stencil_buffer_id);
}
void fx_renderer_begin(struct fx_renderer *renderer, int width, int height) {
@ -432,10 +406,13 @@ void fx_renderer_begin(struct fx_renderer *renderer, int width, int height) {
renderer->wlr_buffer.fb = wlr_fb;
// Create the framebuffers
fx_framebuffer_create(&renderer->main_buffer, width, height, true);
fx_framebuffer_create(&renderer->effects_buffer, width, height, false);
fx_framebuffer_create(&renderer->effects_buffer_swapped, width, height, false);
create_stencil_buffer(&renderer->stencil_buffer_id, width, height);
fx_framebuffer_update(&renderer->main_buffer, width, height);
fx_framebuffer_update(&renderer->effects_buffer, width, height);
fx_framebuffer_update(&renderer->effects_buffer_swapped, width, height);
// Add a stencil buffer to the main buffer & bind the main buffer
fx_framebuffer_bind(&renderer->main_buffer);
fx_framebuffer_add_stencil_buffer(&renderer->main_buffer, width, height);
// refresh projection matrix
matrix_projection(renderer->projection, width, height,
@ -447,12 +424,6 @@ void fx_renderer_begin(struct fx_renderer *renderer, int width, int height) {
fx_framebuffer_bind(&renderer->main_buffer);
}
void fx_renderer_end(struct fx_renderer *renderer) {
// Release the main buffer
fx_framebuffer_release(&renderer->main_buffer);
release_stencil_buffer(&renderer->stencil_buffer_id);
}
void fx_renderer_clear(const float color[static 4]) {
glClearColor(color[0], color[1], color[2], color[3]);
glClearStencil(0);

View file

@ -0,0 +1,21 @@
#include <assert.h>
#include <wlr/render/gles2.h>
#include "sway/desktop/fx_renderer/fx_stencilbuffer.h"
struct fx_stencilbuffer fx_stencilbuffer_create() {
return (struct fx_stencilbuffer) {
.rb = -1,
.width = -1,
.height = -1,
};
}
void fx_stencilbuffer_release(struct fx_stencilbuffer *stencil_buffer) {
if (stencil_buffer->rb != (uint32_t) -1 && stencil_buffer->rb) {
glDeleteRenderbuffers(1, &stencil_buffer->rb);
}
stencil_buffer->rb = -1;
stencil_buffer->width = -1;
stencil_buffer->height = -1;
}

View file

@ -3,7 +3,16 @@
#include "sway/desktop/fx_renderer/fx_texture.h"
struct fx_texture fx_texture_from_wlr_texture(struct wlr_texture* texture) {
struct fx_texture fx_texture_create() {
return (struct fx_texture) {
.id = 0,
.target = 0,
.width = -1,
.height = -1,
};
}
struct fx_texture fx_texture_from_wlr_texture(struct wlr_texture *texture) {
assert(wlr_texture_is_gles2(texture));
struct wlr_gles2_texture_attribs texture_attrs;
@ -17,3 +26,12 @@ struct fx_texture fx_texture_from_wlr_texture(struct wlr_texture* texture) {
.height = texture->height,
};
}
void fx_texture_release(struct fx_texture *texture) {
if (texture->id) {
glDeleteTextures(1, &texture->id);
}
texture->id = 0;
texture->width = -1;
texture->height = -1;
}

View file

@ -6,6 +6,7 @@
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_subcompositor.h>
#include "log.h"
#include "sway/layer_criteria.h"
#include "sway/desktop/transaction.h"
#include "sway/input/cursor.h"
#include "sway/input/input-manager.h"
@ -15,6 +16,21 @@
#include "sway/server.h"
#include "sway/tree/arrange.h"
#include "sway/tree/workspace.h"
#include "wlr-layer-shell-unstable-v1-protocol.h"
static void layer_parse_criteria(struct sway_layer_surface *sway_layer) {
enum zwlr_layer_shell_v1_layer layer = sway_layer->layer;
if (layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND) {
return;
}
list_t *criterias = layer_criterias_for_sway_layer_surface(sway_layer);
for (int i = 0; i < criterias->length; i++) {
struct layer_criteria *criteria = criterias->items[i];
layer_criteria_parse(sway_layer, criteria);
}
list_free(criterias);
}
static void apply_exclusive(struct wlr_box *usable_area,
uint32_t anchor, int32_t exclusive,
@ -306,6 +322,7 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
wl_list_insert(&output->layers[layer_surface->current.layer],
&layer->link);
layer->layer = layer_surface->current.layer;
layer_parse_criteria(layer);
}
arrange_layers(output);
}
@ -317,6 +334,13 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
bool extent_changed =
memcmp(&old_extent, &layer->extent, sizeof(struct wlr_box)) != 0;
if (extent_changed || layer_changed) {
int blur_size = layer->has_blur? config_get_blur_size(): 0;
int shadow_sigma = layer->has_shadow? config->shadow_blur_sigma: 0;
int effect_size = MAX(blur_size, shadow_sigma);
old_extent.x += output->lx - effect_size;
old_extent.y += output->ly - effect_size;
old_extent.width += effect_size * 2;
old_extent.height += effect_size * 2;
output_damage_box(output, &old_extent);
output_damage_surface(output, layer->geo.x, layer->geo.y,
layer_surface->surface, true);
@ -393,6 +417,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
struct wlr_output *wlr_output = sway_layer->layer_surface->output;
sway_assert(wlr_output, "wlr_layer_surface_v1 has null output");
struct sway_output *output = wlr_output->data;
layer_parse_criteria(sway_layer);
output_damage_surface(output, sway_layer->geo.x, sway_layer->geo.y,
sway_layer->layer_surface->surface, true);
wlr_surface_send_enter(sway_layer->layer_surface->surface,
@ -685,6 +710,10 @@ void handle_layer_shell_surface(struct wl_listener *listener, void *data) {
sway_layer->layer_surface = layer_surface;
layer_surface->data = sway_layer;
sway_layer->has_blur = false;
sway_layer->has_shadow = false;
sway_layer->corner_radius = 0;
struct sway_output *output = layer_surface->output->data;
sway_layer->output_destroy.notify = handle_output_destroy;
wl_signal_add(&output->events.disable, &sway_layer->output_destroy);

View file

@ -199,6 +199,13 @@ void output_layer_for_each_toplevel_surface(struct sway_output *output,
wl_list_for_each(layer_surface, layer_surfaces, link) {
struct wlr_layer_surface_v1 *wlr_layer_surface_v1 =
layer_surface->layer_surface;
struct render_data *data = user_data;
data->deco_data.blur = layer_surface->layer != ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND ?
layer_surface->has_blur : false;
data->deco_data.shadow = layer_surface->has_shadow;
data->deco_data.corner_radius = layer_surface->corner_radius;
output_surface_for_each_surface(output, wlr_layer_surface_v1->surface,
layer_surface->geo.x, layer_surface->geo.y, iterator,
user_data);
@ -689,6 +696,37 @@ static void damage_surface_iterator(struct sway_output *output,
ceil(output->wlr_output->scale) - surface->current.scale);
}
pixman_region32_translate(&damage, box.x, box.y);
// Extend view/layer damage size
int effect_size = 0;
if (view && view->container->blur_enabled) {
// Don't check for shadow, gets extended in `output_damage_whole_container`
effect_size = config_get_blur_size();
} else if (wlr_surface_is_layer_surface(surface)) {
struct wlr_layer_surface_v1 *layer = wlr_layer_surface_v1_from_wlr_surface(surface);
struct sway_layer_surface *sway_layer = layer_from_wlr_layer_surface_v1(layer);
int blur_size = sway_layer->has_blur? config_get_blur_size(): 0;
int shadow_sigma = sway_layer->has_shadow? config->shadow_blur_sigma: 0;
effect_size = MAX(blur_size, shadow_sigma);
}
if (effect_size > 0) {
if (pixman_region32_not_empty(&damage)) {
int output_width, output_height;
wlr_output_transformed_resolution(output->wlr_output, &output_width, &output_height);
int32_t damage_width = damage.extents.x2 - damage.extents.x1;
int32_t damage_height = damage.extents.y2 - damage.extents.y1;
if (damage_width > output_width || damage_height > output_height) {
pixman_region32_intersect_rect(&damage, &damage, 0, 0, output_width, output_height);
} else {
wlr_region_expand(&damage, &damage, effect_size);
}
}
box.x -= effect_size;
box.y -= effect_size;
box.width += effect_size * 2;
box.height += effect_size * 2;
}
if (wlr_damage_ring_add(&output->damage_ring, &damage)) {
wlr_output_schedule_frame(output->wlr_output);
}
@ -745,12 +783,14 @@ static void damage_child_views_iterator(struct sway_container *con,
void output_damage_whole_container(struct sway_output *output,
struct sway_container *con) {
int shadow_sigma = con->shadow_enabled ? config->shadow_blur_sigma : 0;
// Pad the box by 1px, because the width is a double and might be a fraction
struct wlr_box box = {
.x = con->current.x - output->lx - 1,
.y = con->current.y - output->ly - 1,
.width = con->current.width + 2,
.height = con->current.height + 2,
.x = con->current.x - output->lx - 1 - shadow_sigma,
.y = con->current.y - output->ly - 1 - shadow_sigma,
.width = con->current.width + 2 + shadow_sigma * 2,
.height = con->current.height + 2 + shadow_sigma * 2,
};
scale_box(&box, output->wlr_output->scale);
if (wlr_damage_ring_add_box(&output->damage_ring, &box)) {
@ -973,7 +1013,6 @@ void handle_new_output(struct wl_listener *listener, void *data) {
transaction_commit_dirty();
// From sway upstream (fixes damage_ring bounds being INT_MAX)
int width, height;
wlr_output_transformed_resolution(output->wlr_output, &width, &height);
wlr_damage_ring_set_bounds(&output->damage_ring, width, height);

View file

@ -23,7 +23,6 @@
#include "sway/desktop/fx_renderer/fx_renderer.h"
#include "sway/input/input-manager.h"
#include "sway/input/seat.h"
#include "sway/layers.h"
#include "sway/output.h"
#include "sway/server.h"
#include "sway/tree/arrange.h"
@ -32,19 +31,6 @@
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"
struct render_data {
pixman_region32_t *damage;
struct wlr_box *clip_box;
struct decoration_data deco_data;
};
struct workspace_effect_info {
bool container_wants_blur;
bool container_wants_shadow;
bool should_render_optimized_blur;
int expanded_size;
};
struct decoration_data get_undecorated_decoration_data() {
return (struct decoration_data) {
.alpha = 1.0f,
@ -54,17 +40,10 @@ struct decoration_data get_undecorated_decoration_data() {
.saturation = 1.0f,
.has_titlebar = false,
.blur = false,
.shadow = false,
};
}
int get_blur_size() {
return pow(2, config->blur_params.num_passes) * config->blur_params.radius;
}
bool should_parameters_blur() {
return config->blur_params.radius > 0 && config->blur_params.num_passes > 0;
}
// TODO: contribute wlroots function to allow creating an fbox from a box?
struct wlr_fbox wlr_fbox_from_wlr_box(struct wlr_box *box) {
return (struct wlr_fbox) {
@ -241,7 +220,7 @@ void render_blur_segments(struct fx_renderer *renderer,
// Blurs the main_buffer content and returns the blurred framebuffer
struct fx_framebuffer *get_main_buffer_blur(struct fx_renderer *renderer, struct sway_output *output,
pixman_region32_t *original_damage, const float box_matrix[static 9], const struct wlr_box *box) {
pixman_region32_t *original_damage, const struct wlr_box *box) {
struct wlr_output *wlr_output = output->wlr_output;
struct wlr_box monitor_box = get_monitor_box(wlr_output);
@ -255,9 +234,9 @@ struct fx_framebuffer *get_main_buffer_blur(struct fx_renderer *renderer, struct
pixman_region32_t damage;
pixman_region32_init(&damage);
pixman_region32_copy(&damage, original_damage);
wlr_region_transform(&damage, &damage, transform,
monitor_box.width, monitor_box.height);
wlr_region_expand(&damage, &damage, get_blur_size());
wlr_region_transform(&damage, &damage, transform, monitor_box.width, monitor_box.height);
wlr_region_expand(&damage, &damage, config_get_blur_size());
// Initially blur main_buffer content into the effects_buffers
struct fx_framebuffer *current_buffer = &renderer->main_buffer;
@ -269,18 +248,12 @@ struct fx_framebuffer *get_main_buffer_blur(struct fx_renderer *renderer, struct
// damage region will be scaled, make a temp
pixman_region32_t tempDamage;
pixman_region32_init(&tempDamage);
// When DOWNscaling, we make the region twice as small because it's the TARGET
wlr_region_scale(&tempDamage, &damage, 0.5f);
int blur_radius = config->blur_params.radius;
int blur_passes = config->blur_params.num_passes;
// First pass
render_blur_segments(renderer, gl_matrix, &tempDamage, &current_buffer,
&renderer->shaders.blur1, box, blur_radius);
// Downscale
for (int i = 1; i < blur_passes; ++i) {
for (int i = 0; i < blur_passes; ++i) {
wlr_region_scale(&tempDamage, &damage, 1.0f / (1 << (i + 1)));
render_blur_segments(renderer, gl_matrix, &tempDamage, &current_buffer,
&renderer->shaders.blur1, box, blur_radius);
@ -347,13 +320,12 @@ void render_blur(bool optimized, struct sway_output *output,
wlr_region_scale(&inverse_opaque, &inverse_opaque, wlr_output->scale);
struct fx_framebuffer *buffer = &renderer->blur_buffer;
if (!buffer->texture.id || (!optimized && !config->blur_xray)) {
if (!buffer->texture.id || !optimized) {
pixman_region32_translate(&inverse_opaque, dst_box->x, dst_box->y);
pixman_region32_intersect(&inverse_opaque, &inverse_opaque, &damage);
// Render the blur into its own buffer
buffer = get_main_buffer_blur(renderer, output, &inverse_opaque,
wlr_output->transform_matrix, dst_box);
buffer = get_main_buffer_blur(renderer, output, &inverse_opaque, dst_box);
}
// Draw the blurred texture
@ -372,6 +344,61 @@ damage_finish:
pixman_region32_fini(&inverse_opaque);
}
// _box.x and .y are expected to be layout-local
// _box.width and .height are expected to be output-buffer-local
void render_box_shadow(struct sway_output *output, pixman_region32_t *output_damage,
const struct wlr_box *_box, const float color[static 4],
float blur_sigma, float corner_radius) {
struct wlr_output *wlr_output = output->wlr_output;
struct fx_renderer *renderer = output->renderer;
struct wlr_box box;
memcpy(&box, _box, sizeof(struct wlr_box));
box.x -= blur_sigma;
box.y -= blur_sigma;
box.width += 2 * blur_sigma;
box.height += 2 * blur_sigma;
pixman_region32_t damage = create_damage(box, output_damage);
// don't damage area behind window since we dont render it anyway
struct wlr_box inner_box;
memcpy(&inner_box, _box, sizeof(struct wlr_box));
inner_box.x += corner_radius;
inner_box.y += corner_radius;
inner_box.width -= 2 * corner_radius;
inner_box.height -= 2 * corner_radius;
pixman_region32_t inner_damage = create_damage(inner_box, output_damage);
pixman_region32_subtract(&damage, &damage, &inner_damage);
bool damaged = pixman_region32_not_empty(&damage);
if (!damaged) {
goto damage_finish;
}
float matrix[9];
wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0,
wlr_output->transform_matrix);
// ensure the box is updated as per the output orientation
struct wlr_box transformed_box;
int width, height;
wlr_output_transformed_resolution(wlr_output, &width, &height);
wlr_box_transform(&transformed_box, &box,
wlr_output_transform_invert(wlr_output->transform), width, height);
int nrects;
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
for (int i = 0; i < nrects; ++i) {
scissor_output(wlr_output, &rects[i]);
fx_render_box_shadow(renderer, &transformed_box, color, matrix,
corner_radius, blur_sigma);
}
damage_finish:
pixman_region32_fini(&damage);
}
static void render_surface_iterator(struct sway_output *output,
struct sway_view *view, struct wlr_surface *surface,
@ -407,13 +434,14 @@ static void render_surface_iterator(struct sway_output *output,
struct decoration_data deco_data = data->deco_data;
deco_data.corner_radius *= wlr_output->scale;
// render blur (view->surface == surface excludes blurring subsurfaces)
if (deco_data.blur && should_parameters_blur() && view->surface == surface) {
// render blur
bool is_subsurface = view ? view->surface != surface : false;
if (deco_data.blur && config_should_parameters_blur() && !is_subsurface) {
pixman_region32_t opaque_region;
pixman_region32_init(&opaque_region);
bool has_alpha = false;
if (deco_data.alpha < 1.0) {
if (deco_data.alpha < 1.0 || deco_data.dim_color[3] < 1.0) {
has_alpha = true;
pixman_region32_union_rect(&opaque_region, &opaque_region, 0, 0, 0, 0);
} else {
@ -422,12 +450,12 @@ static void render_surface_iterator(struct sway_output *output,
}
if (has_alpha) {
bool should_optimize_blur = view ? !container_is_floating(view->container) || config->blur_xray : false;
struct wlr_box monitor_box = get_monitor_box(wlr_output);
wlr_box_transform(&monitor_box, &monitor_box,
wlr_output_transform_invert(wlr_output->transform), monitor_box.width, monitor_box.height);
struct wlr_fbox blur_src_box = wlr_fbox_from_wlr_box(&monitor_box);
bool is_floating = container_is_floating(view->container);
render_blur(!is_floating, output, output_damage, &blur_src_box, &dst_box, &opaque_region,
render_blur(should_optimize_blur, output, output_damage, &blur_src_box, &dst_box, &opaque_region,
surface->current.width, surface->current.height, surface->current.scale,
deco_data.corner_radius, deco_data.has_titlebar);
}
@ -435,6 +463,7 @@ static void render_surface_iterator(struct sway_output *output,
pixman_region32_fini(&opaque_region);
}
// Render surface texture
struct wlr_fbox src_box;
wlr_surface_get_buffer_source_box(surface, &src_box);
struct fx_texture fx_texture = fx_texture_from_wlr_texture(texture);
@ -445,6 +474,30 @@ static void render_surface_iterator(struct sway_output *output,
wlr_output);
}
// view will be NULL every time
static void render_layer_iterator(struct sway_output *output,
struct sway_view *view, struct wlr_surface *surface,
struct wlr_box *_box, void *_data) {
struct render_data *data = _data;
struct decoration_data deco_data = data->deco_data;
// Ignore effects if this is a subsurface
if (wl_list_length(&surface->current.subsurfaces_above) > 0) {
deco_data = get_undecorated_decoration_data();
}
// render the layer's surface
render_surface_iterator(output, view, surface, _box, _data);
// render shadow
if (deco_data.shadow && config_should_parameters_shadow()) {
int corner_radius = deco_data.corner_radius *= output->wlr_output->scale;
scale_box(_box, output->wlr_output->scale);
render_box_shadow(output, data->damage, _box, config->shadow_color,
config->shadow_blur_sigma, corner_radius);
}
}
static void render_layer_toplevel(struct sway_output *output,
pixman_region32_t *damage, struct wl_list *layer_surfaces) {
struct render_data data = {
@ -452,7 +505,7 @@ static void render_layer_toplevel(struct sway_output *output,
.deco_data = get_undecorated_decoration_data(),
};
output_layer_for_each_toplevel_surface(output, layer_surfaces,
render_surface_iterator, &data);
render_layer_iterator, &data);
}
static void render_layer_popups(struct sway_output *output,
@ -462,7 +515,7 @@ static void render_layer_popups(struct sway_output *output,
.deco_data = get_undecorated_decoration_data(),
};
output_layer_for_each_popup_surface(output, layer_surfaces,
render_surface_iterator, &data);
render_layer_iterator, &data);
}
#if HAVE_XWAYLAND
@ -497,7 +550,7 @@ void render_whole_output(struct fx_renderer *renderer, struct wlr_output *wlr_ou
render_texture(wlr_output, output_damage, texture, NULL, &monitor_box, matrix, get_undecorated_decoration_data());
}
void render_monitor_blur(struct sway_output *output, pixman_region32_t *damage) {
void render_output_blur(struct sway_output *output, pixman_region32_t *damage) {
struct wlr_output *wlr_output = output->wlr_output;
struct fx_renderer *renderer = output->renderer;
@ -506,12 +559,13 @@ void render_monitor_blur(struct sway_output *output, pixman_region32_t *damage)
pixman_region32_init_rect(&fake_damage, 0, 0, monitor_box.width, monitor_box.height);
// Render the blur
struct fx_framebuffer *buffer = get_main_buffer_blur(renderer, output, &fake_damage,
wlr_output->transform_matrix, &monitor_box);
struct fx_framebuffer *buffer = get_main_buffer_blur(renderer, output, &fake_damage, &monitor_box);
// Render the newly blurred content into the blur_buffer
fx_framebuffer_create(&renderer->blur_buffer,
output->renderer->viewport_width, output->renderer->viewport_height, true);
fx_framebuffer_update(&renderer->blur_buffer,
output->renderer->viewport_width, output->renderer->viewport_height);
fx_framebuffer_bind(&renderer->blur_buffer);
// Clear the damaged region of the blur_buffer
float clear_color[] = { 0, 0, 0, 0 };
int nrects;
@ -646,62 +700,6 @@ damage_finish:
pixman_region32_fini(&damage);
}
// _box.x and .y are expected to be layout-local
// _box.width and .height are expected to be output-buffer-local
void render_box_shadow(struct sway_output *output, pixman_region32_t *output_damage,
const struct wlr_box *_box, const float color[static 4],
float blur_sigma, float corner_radius) {
struct wlr_output *wlr_output = output->wlr_output;
struct fx_renderer *renderer = output->renderer;
struct wlr_box box;
memcpy(&box, _box, sizeof(struct wlr_box));
box.x -= blur_sigma;
box.y -= blur_sigma;
box.width += 2 * blur_sigma;
box.height += 2 * blur_sigma;
pixman_region32_t damage = create_damage(box, output_damage);
// don't damage area behind window since we dont render it anyway
struct wlr_box inner_box;
memcpy(&inner_box, _box, sizeof(struct wlr_box));
inner_box.x += corner_radius;
inner_box.y += corner_radius;
inner_box.width -= 2 * corner_radius;
inner_box.height -= 2 * corner_radius;
pixman_region32_t inner_damage = create_damage(inner_box, output_damage);
pixman_region32_subtract(&damage, &damage, &inner_damage);
bool damaged = pixman_region32_not_empty(&damage);
if (!damaged) {
goto damage_finish;
}
float matrix[9];
wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0,
wlr_output->transform_matrix);
// ensure the box is updated as per the output orientation
struct wlr_box transformed_box;
int width, height;
wlr_output_transformed_resolution(wlr_output, &width, &height);
wlr_box_transform(&transformed_box, &box,
wlr_output_transform_invert(wlr_output->transform), width, height);
int nrects;
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
for (int i = 0; i < nrects; ++i) {
scissor_output(wlr_output, &rects[i]);
fx_render_box_shadow(renderer, &transformed_box, color, matrix,
corner_radius, blur_sigma);
}
damage_finish:
pixman_region32_fini(&damage);
}
void premultiply_alpha(float color[4], float opacity) {
color[3] *= opacity;
color[0] *= color[3];
@ -722,12 +720,27 @@ static void render_view_toplevels(struct sway_view *view, struct sway_output *ou
clip_box.y = state.y - output->ly;
clip_box.width = state.width;
clip_box.height = state.height;
bool smart = config->hide_edge_borders_smart == ESMART_ON ||
(config->hide_edge_borders_smart == ESMART_NO_GAPS &&
!gaps_to_edge(view));
if (state.fullscreen_mode == FULLSCREEN_NONE
&& (state.border == B_PIXEL || state.border == B_NORMAL)) {
&& (state.border == B_PIXEL || state.border == B_NORMAL)
&& !smart) {
clip_box.x += state.border_thickness;
clip_box.y += state.border_thickness;
clip_box.width -= state.border_thickness * 2;
clip_box.height -= state.border_thickness * 2;
if (deco_data.has_titlebar) {
// Shift the box downward to compensate for the titlebar
int titlebar_thickness = container_titlebar_height();
clip_box.y += titlebar_thickness;
clip_box.height -= state.border_thickness + titlebar_thickness;
} else {
// Regular border
clip_box.y += state.border_thickness;
clip_box.height -= state.border_thickness * 2;
}
}
data.clip_box = &clip_box;
@ -790,16 +803,25 @@ static void render_saved_view(struct sway_view *view, struct sway_output *output
dst_box.height = state.height;
if (state.border == B_PIXEL || state.border == B_NORMAL) {
dst_box.x += state.border_thickness;
dst_box.y += state.border_thickness;
dst_box.width -= state.border_thickness * 2;
dst_box.height -= state.border_thickness * 2;
if (deco_data.has_titlebar) {
// Shift the box downward to compensate for the titlebar
int titlebar_thickness = container_titlebar_height();
dst_box.y += titlebar_thickness;
dst_box.height -= state.border_thickness + titlebar_thickness;
} else {
// Regular border
dst_box.y += state.border_thickness;
dst_box.height -= state.border_thickness * 2;
}
}
scale_box(&dst_box, wlr_output->scale);
deco_data.corner_radius *= wlr_output->scale;
// render blur
if (deco_data.blur && should_parameters_blur()) {
if (deco_data.blur && config_should_parameters_blur()) {
struct wlr_gles2_texture_attribs attribs;
wlr_gles2_texture_get_attribs(saved_buf->buffer->texture, &attribs);
@ -812,14 +834,15 @@ static void render_saved_view(struct sway_view *view, struct sway_output *output
wlr_box_transform(&monitor_box, &monitor_box,
wlr_output_transform_invert(wlr_output->transform), monitor_box.width, monitor_box.height);
struct wlr_fbox src_box = wlr_fbox_from_wlr_box(&monitor_box);
bool is_floating = container_is_floating(view->container);
render_blur(!is_floating, output, damage, &src_box, &dst_box, &opaque_region,
bool should_optimize_blur = !container_is_floating(view->container) || config->blur_xray;
render_blur(should_optimize_blur, output, damage, &src_box, &dst_box, &opaque_region,
saved_buf->width, saved_buf->height, 1, deco_data.corner_radius, deco_data.has_titlebar);
pixman_region32_fini(&opaque_region);
}
}
// Render saved surface texture
struct fx_texture fx_texture = fx_texture_from_wlr_texture(saved_buf->buffer->texture);
render_texture(wlr_output, damage, &fx_texture,
&saved_buf->source_box, &dst_box, matrix, deco_data);
@ -846,7 +869,6 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,
render_view_toplevels(view, output, damage, deco_data);
}
// Only draw shadows on CSD windows if shadows_on_csd is enabled
if (state->border == B_CSD && !config->shadows_on_csd_enabled) {
return;
}
@ -1377,6 +1399,10 @@ static void render_containers_linear(struct sway_output *output,
for (int i = 0; i < parent->children->length; ++i) {
struct sway_container *child = parent->children->items[i];
if (container_is_scratchpad_hidden(child)) {
continue;
}
if (child->view) {
struct sway_view *view = child->view;
struct border_colors *colors;
@ -1417,6 +1443,7 @@ static void render_containers_linear(struct sway_output *output,
.saturation = child->saturation,
.has_titlebar = has_titlebar,
.blur = child->blur_enabled,
.shadow = child->shadow_enabled,
};
render_view(output, damage, child, colors, deco_data);
if (has_titlebar) {
@ -1455,7 +1482,7 @@ static void render_containers_tabbed(struct sway_output *output,
struct decoration_data deco_data = {
.alpha = current->alpha,
.dim_color = view_is_urgent(current->view)
.dim_color = current->view && view_is_urgent(current->view)
? config->dim_inactive_colors.urgent
: config->dim_inactive_colors.unfocused,
.dim = current->current.focused || parent->focused ? 0.0f : current->dim,
@ -1466,6 +1493,7 @@ static void render_containers_tabbed(struct sway_output *output,
.saturation = current->saturation,
.has_titlebar = true,
.blur = current->blur_enabled,
.shadow = current->shadow_enabled,
};
// Render tabs
@ -1551,7 +1579,7 @@ static void render_containers_stacked(struct sway_output *output,
struct decoration_data deco_data = {
.alpha = current->alpha,
.dim_color = view_is_urgent(current->view)
.dim_color = current->view && view_is_urgent(current->view)
? config->dim_inactive_colors.urgent
: config->dim_inactive_colors.unfocused,
.dim = current->current.focused || parent->focused ? 0.0f : current->dim,
@ -1561,6 +1589,7 @@ static void render_containers_stacked(struct sway_output *output,
? 0 : current->corner_radius,
.has_titlebar = true,
.blur = current->blur_enabled,
.shadow = current->shadow_enabled,
};
// Render titles
@ -1708,6 +1737,7 @@ static void render_floating_container(struct sway_output *soutput,
.corner_radius = con->corner_radius,
.has_titlebar = has_titlebar,
.blur = con->blur_enabled,
.shadow = con->shadow_enabled,
};
render_view(soutput, damage, con, colors, deco_data);
if (has_titlebar) {
@ -1750,75 +1780,6 @@ static void render_seatops(struct sway_output *output,
}
}
struct find_effect_iter_data {
struct workspace_effect_info *effect_info;
bool blur_buffer_dirty;
};
static bool find_con_effect_iterator(struct sway_container *con, void* _data) {
struct sway_view *view = con->view;
struct find_effect_iter_data *data = _data;
struct workspace_effect_info *effect_info = data->effect_info;
if (!view) {
return false;
}
if (con->blur_enabled && !view->surface->opaque) {
effect_info->container_wants_blur = true;
bool is_floating = container_is_floating(con);
// Check if we should render optimized blur
if (data->blur_buffer_dirty
// Only test floating windows when xray is enabled
&& (!is_floating || (is_floating && config->blur_xray))) {
effect_info->should_render_optimized_blur = true;
}
}
if (con->shadow_enabled) {
effect_info->container_wants_shadow = true;
}
// Stop the iteration if all of the effects have been found.
// Ensures that no effect is skipped if returning early
return effect_info->container_wants_blur
&& effect_info->container_wants_shadow
&& effect_info->should_render_optimized_blur;
}
static struct workspace_effect_info get_workspace_effect_info(struct sway_output *sway_output) {
struct fx_renderer *renderer = sway_output->renderer;
struct sway_workspace *workspace = sway_output->current.active_workspace;
struct workspace_effect_info effect_info = {
.container_wants_blur = false,
.container_wants_shadow = false,
.should_render_optimized_blur = false,
.expanded_size = 0
};
if (!workspace_is_visible(workspace)) {
return effect_info;
}
// Iterate through the workspace containers and check if any effects are requested
struct find_effect_iter_data iter_data = {
.effect_info = &effect_info,
.blur_buffer_dirty = renderer->blur_buffer_dirty
};
workspace_find_container(workspace, find_con_effect_iterator, &iter_data);
// Set the expanded damage region
bool shadow_enabled = effect_info.container_wants_shadow || config->shadow_enabled;
int shadow_sigma = shadow_enabled ? config->shadow_blur_sigma : 0;
bool blur_enabled = effect_info.container_wants_blur || config->blur_enabled;
int blur_size = blur_enabled ? get_blur_size() : 0;
// +1 as a margin of error
effect_info.expanded_size = MAX(shadow_sigma, blur_size) + 1;
return effect_info;
}
void output_render(struct sway_output *output, struct timespec *when,
pixman_region32_t *damage) {
struct wlr_output *wlr_output = output->wlr_output;
@ -1829,12 +1790,18 @@ void output_render(struct sway_output *output, struct timespec *when,
return;
}
/* we need to track extended damage for blur (as it is expanded in output.c),
before we expand it again later in this function
*/
pixman_region32_t extended_damage;
pixman_region32_init(&extended_damage);
pixman_region32_copy(&extended_damage, damage);
struct sway_container *fullscreen_con = root->fullscreen_global;
if (!fullscreen_con) {
fullscreen_con = workspace->current.fullscreen;
}
struct wlr_box monitor_box = get_monitor_box(wlr_output);
wlr_box_transform(&monitor_box, &monitor_box,
wlr_output_transform_invert(wlr_output->transform),
@ -1842,56 +1809,25 @@ void output_render(struct sway_output *output, struct timespec *when,
fx_renderer_begin(renderer, monitor_box.width, monitor_box.height);
int width, height;
wlr_output_transformed_resolution(wlr_output, &width, &height);
int output_width, output_height;
wlr_output_transformed_resolution(wlr_output, &output_width, &output_height);
if (debug.damage == DAMAGE_RERENDER) {
pixman_region32_union_rect(damage, damage, 0, 0, width, height);
}
bool has_blur = false;
bool blur_optimize_should_render = false;
bool damage_not_empty = pixman_region32_not_empty(damage);
pixman_region32_t extended_damage;
pixman_region32_init(&extended_damage);
if (!fullscreen_con && !server.session_lock.locked && damage_not_empty) {
// Check if there are any windows to blur
struct workspace_effect_info effect_info = get_workspace_effect_info(output);
has_blur = effect_info.container_wants_blur || config->blur_enabled;
if (effect_info.should_render_optimized_blur) {
blur_optimize_should_render = true;
// Damage the whole output
pixman_region32_union_rect(damage, damage, 0, 0, width, height);
}
// Extend the damaged region
int expanded_size = effect_info.expanded_size;
if (expanded_size > 0) {
int32_t damage_width = damage->extents.x2 - damage->extents.x1;
int32_t damage_height = damage->extents.y2 - damage->extents.y1;
// Limit the damage extent to the size of the monitor to prevent overflow
if (damage_width > width || damage_height > height) {
pixman_region32_intersect_rect(damage, damage, 0, 0, width, height);
}
wlr_region_expand(damage, damage, expanded_size);
pixman_region32_copy(&extended_damage, damage);
wlr_region_expand(damage, damage, expanded_size);
} else {
pixman_region32_copy(&extended_damage, damage);
}
} else {
pixman_region32_union_rect(damage, damage, 0, 0, output_width, output_height);
pixman_region32_copy(&extended_damage, damage);
}
if (debug.damage == DAMAGE_HIGHLIGHT && damage_not_empty) {
fx_renderer_clear((float[]){1, 1, 0, 1});
}
if (!damage_not_empty) {
if (!pixman_region32_not_empty(damage)) {
// Output isn't damaged but needs buffer swap
goto renderer_end;
}
if (debug.damage == DAMAGE_HIGHLIGHT) {
fx_framebuffer_bind(&renderer->wlr_buffer);
fx_renderer_clear((float[]){1, 1, 0, 1});
fx_framebuffer_bind(&renderer->main_buffer);
}
if (server.session_lock.locked) {
float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
if (server.session_lock.lock == NULL) {
@ -1965,6 +1901,25 @@ void output_render(struct sway_output *output, struct timespec *when,
render_unmanaged(output, damage, &root->xwayland_unmanaged);
#endif
} else {
bool workspace_has_blur = should_workspace_have_blur(workspace);
if (workspace_has_blur) {
if (config_should_parameters_blur() && renderer->blur_buffer_dirty) {
// Needs to be extended before clearing
pixman_region32_union_rect(damage, damage, 0, 0, output_width, output_height);
pixman_region32_union_rect(&extended_damage, &extended_damage, 0, 0, output_width, output_height);
}
// ensure that the damage isn't expanding past the output's size
int32_t damage_width = damage->extents.x2 - damage->extents.x1;
int32_t damage_height = damage->extents.y2 - damage->extents.y1;
if (damage_width > output_width || damage_height > output_height) {
pixman_region32_intersect_rect(damage, damage, 0, 0, output_width, output_height);
pixman_region32_intersect_rect(&extended_damage, &extended_damage, 0, 0, output_width, output_height);
} else {
wlr_region_expand(damage, damage, config_get_blur_size());
}
}
float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f};
int nrects;
@ -1979,9 +1934,9 @@ void output_render(struct sway_output *output, struct timespec *when,
render_layer_toplevel(output, damage,
&output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);
bool blur_enabled = has_blur && should_parameters_blur();
if (blur_enabled && blur_optimize_should_render && renderer->blur_buffer_dirty) {
render_monitor_blur(output, damage);
// check if the background needs to be blurred
if (config_should_parameters_blur() && renderer->blur_buffer_dirty && workspace_has_blur) {
render_output_blur(output, damage);
}
render_workspace(output, damage, workspace, workspace->current.focused);
@ -2015,6 +1970,7 @@ void output_render(struct sway_output *output, struct timespec *when,
.saturation = focus->saturation,
.has_titlebar = false,
.blur = false,
.shadow = false,
};
render_view_popups(focus->view, output, damage, deco_data);
}
@ -2029,6 +1985,7 @@ render_overlay:
renderer_end:
// Draw the contents of our buffer into the wlr buffer
fx_framebuffer_bind(&renderer->wlr_buffer);
float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
if (pixman_region32_not_empty(&extended_damage)) {
int nrects;
@ -2038,34 +1995,29 @@ renderer_end:
fx_renderer_clear(clear_color);
}
}
render_whole_output(renderer, wlr_output, &extended_damage, &renderer->main_buffer.texture);
fx_renderer_scissor(NULL);
fx_renderer_end(renderer);
// Draw the software cursors
wlr_renderer_begin(output->server->wlr_renderer, wlr_output->width, wlr_output->height);
wlr_output_render_software_cursors(wlr_output, damage);
wlr_renderer_end(output->server->wlr_renderer);
fx_renderer_scissor(NULL);
pixman_region32_t frame_damage;
pixman_region32_init(&frame_damage);
enum wl_output_transform transform = wlr_output_transform_invert(wlr_output->transform);
/*
* Extend the frame damage by the blur size to properly calc damage for the
* next buffer swap. Thanks Emersion for your excellent damage tracking blog-post!
*/
wlr_region_transform(&frame_damage, &extended_damage, transform, width, height);
wlr_region_transform(&frame_damage, &extended_damage, transform, output_width, output_height);
pixman_region32_fini(&extended_damage);
if (debug.damage != DAMAGE_DEFAULT || blur_optimize_should_render) {
if (debug.damage != DAMAGE_DEFAULT) {
pixman_region32_union_rect(&frame_damage, &frame_damage,
0, 0, wlr_output->width, wlr_output->height);
}
wlr_output_set_damage(wlr_output, &frame_damage);
pixman_region32_fini(&extended_damage);
pixman_region32_fini(&frame_damage);
if (!wlr_output_commit(wlr_output)) {

View file

@ -10,6 +10,7 @@
#include "log.h"
#include "sway/config.h"
#include "sway/ipc-json.h"
#include "sway/layers.h"
#include "sway/tree/container.h"
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"
@ -273,7 +274,8 @@ static json_object *ipc_json_create_node(int id, const char* type, char *name,
return object;
}
static void ipc_json_describe_wlr_output(struct wlr_output *wlr_output, json_object *object) {
static void ipc_json_describe_wlr_output(struct wlr_output *wlr_output,
struct sway_output *output, json_object *object) {
json_object_object_add(object, "primary", json_object_new_boolean(false));
json_object_object_add(object, "make",
json_object_new_string(wlr_output->make ? wlr_output->make : "Unknown"));
@ -299,7 +301,7 @@ static void ipc_json_describe_wlr_output(struct wlr_output *wlr_output, json_obj
static void ipc_json_describe_output(struct sway_output *output,
json_object *object) {
ipc_json_describe_wlr_output(output->wlr_output, object);
ipc_json_describe_wlr_output(output->wlr_output, output, object);
}
static void ipc_json_describe_enabled_output(struct sway_output *output,
@ -331,6 +333,63 @@ static void ipc_json_describe_enabled_output(struct sway_output *output,
json_object_object_add(object, "adaptive_sync_status",
json_object_new_string(adaptive_sync_status));
struct json_object *layers = json_object_new_array();
size_t len = sizeof(output->layers) / sizeof(output->layers[0]);
for (size_t i = 0; i < len; ++i) {
struct sway_layer_surface *lsurface;
wl_list_for_each(lsurface, &output->layers[i], link) {
json_object *layer = json_object_new_object();
json_object_object_add(layer, "namespace",
json_object_new_string(lsurface->layer_surface->namespace));
char *layer_name = NULL;
switch (lsurface->layer) {
case ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND:
layer_name = "background";
break;
case ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM:
layer_name = "bottom";
break;
case ZWLR_LAYER_SHELL_V1_LAYER_TOP:
layer_name = "top";
break;
case ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY:
layer_name = "overlay";
break;
}
json_object_object_add(layer, "layer",
json_object_new_string(layer_name));
json_object *extent = json_object_new_object();
json_object_object_add(extent, "width",
json_object_new_int(lsurface->extent.width));
json_object_object_add(extent, "height",
json_object_new_int(lsurface->extent.height));
json_object_object_add(extent, "x",
json_object_new_int(lsurface->extent.x));
json_object_object_add(extent, "y",
json_object_new_int(lsurface->extent.y));
json_object_object_add(layer, "extent", extent);
json_object *effects = json_object_new_array();
if (lsurface->has_blur) {
json_object_array_add(effects, json_object_new_string("blur"));
}
if (lsurface->has_shadow) {
json_object_array_add(effects, json_object_new_string("shadows"));
}
if (lsurface->corner_radius > 0) {
json_object_array_add(effects, json_object_new_string("corner_radius"));
}
json_object_object_add(layer, "effects", effects);
json_object_array_add(layers, layer);
}
}
json_object_object_add(object, "layer_shell_surfaces", layers);
struct sway_workspace *ws = output_get_active_workspace(output);
if (!sway_assert(ws, "Expected output to have a workspace")) {
return;
@ -413,7 +472,7 @@ json_object *ipc_json_describe_non_desktop_output(struct sway_output_non_desktop
json_object *object = json_object_new_object();
ipc_json_describe_wlr_output(wlr_output, object);
ipc_json_describe_wlr_output(wlr_output, NULL, object);
json_object_object_add(object, "non_desktop", json_object_new_boolean(true));
json_object_object_add(object, "type", json_object_new_string("output"));
@ -905,6 +964,11 @@ static json_object *describe_libinput_device(struct libinput_device *device) {
case LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE:
accel_profile = "adaptive";
break;
#if HAVE_LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM
case LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM:
accel_profile = "custom";
break;
#endif
}
json_object_object_add(object, "accel_profile",
json_object_new_string(accel_profile));
@ -1053,9 +1117,9 @@ json_object *ipc_json_describe_input(struct sway_input_device *device) {
struct xkb_keymap *keymap = keyboard->keymap;
struct xkb_state *state = keyboard->xkb_state;
json_object_object_add(object, "repeat_delay",
json_object_object_add(object, "repeat_delay",
json_object_new_int(keyboard->repeat_info.delay));
json_object_object_add(object, "repeat_rate",
json_object_object_add(object, "repeat_rate",
json_object_new_int(keyboard->repeat_info.rate));
json_object *layouts_arr = json_object_new_array();

88
sway/layer_criteria.c Normal file
View file

@ -0,0 +1,88 @@
#include <ctype.h>
#include "log.h"
#include "stringop.h"
#include "sway/commands.h"
#include "sway/layer_criteria.h"
#include "util.h"
void layer_criteria_destroy(struct layer_criteria *criteria) {
free(criteria->namespace);
free(criteria->cmdlist);
free(criteria);
}
bool layer_criteria_is_equal(struct layer_criteria *a, struct layer_criteria *b) {
return strcmp(a->namespace, b->namespace) == 0
&& strcmp(a->cmdlist, b->cmdlist) == 0;
}
bool layer_criteria_already_exists(struct layer_criteria *criteria) {
list_t *criterias = config->layer_criteria;
for (int i = 0; i < criterias->length; ++i) {
struct layer_criteria *existing = criterias->items[i];
if (layer_criteria_is_equal(criteria, existing)) {
return true;
}
}
return false;
}
list_t *layer_criterias_for_sway_layer_surface(struct sway_layer_surface *sway_layer) {
list_t *criterias = config->layer_criteria;
list_t *matches = create_list();
for (int i = 0; i < criterias->length; ++i) {
struct layer_criteria *criteria = criterias->items[i];
if (strcmp(criteria->namespace, sway_layer->layer_surface->namespace) == 0) {
list_add(matches, criteria);
}
}
return matches;
}
void layer_criteria_parse(struct sway_layer_surface *sway_layer, struct layer_criteria *criteria) {
char matched_delim = ';';
char *head = malloc(strlen(criteria->cmdlist) + 1);
strcpy(head, criteria->cmdlist);
do {
// Trim leading whitespaces
for (; isspace(*head); ++head) {}
// Split command list
char *cmd = argsep(&head, ";,", &matched_delim);
for (; isspace(*cmd); ++cmd) {}
if (strcmp(cmd, "") == 0) {
sway_log(SWAY_INFO, "Ignoring empty layer effect.");
continue;
}
sway_log(SWAY_INFO, "Handling layer effect '%s'", cmd);
int argc;
char **argv = split_args(cmd, &argc);
// Strip all quotes from each token
for (int i = 1; i < argc; ++i) {
if (*argv[i] == '\"' || *argv[i] == '\'') {
strip_quotes(argv[i]);
}
}
if (strcmp(argv[0], "blur") == 0) {
sway_layer->has_blur = parse_boolean(argv[1], true);
continue;
} else if (strcmp(argv[0], "shadows") == 0) {
sway_layer->has_shadow = parse_boolean(argv[1], true);
continue;
} else if (strcmp(argv[0], "corner_radius") == 0) {
int value;
if (cmd_corner_radius_parse_value(argv[1], &value)) {
sway_layer->corner_radius = value;
continue;
}
sway_log(SWAY_ERROR,
"Invalid layer_effects corner_radius size! Got \"%s\"",
argv[1]);
return;
} else {
sway_log(SWAY_ERROR, "Invalid layer_effects effect! Got \"%s\"", cmd);
return;
}
} while(head);
}

View file

@ -5,6 +5,7 @@ sway_sources = files(
'decoration.c',
'ipc-json.c',
'ipc-server.c',
'layer_criteria.c',
'lock.c',
'main.c',
'realtime.c',
@ -16,6 +17,7 @@ sway_sources = files(
'desktop/desktop.c',
'desktop/fx_renderer/fx_framebuffer.c',
'desktop/fx_renderer/fx_renderer.c',
'desktop/fx_renderer/fx_stencilbuffer.c',
'desktop/fx_renderer/fx_texture.c',
'desktop/fx_renderer/matrix.c',
'desktop/idle_inhibit_v1.c',
@ -91,6 +93,7 @@ sway_sources = files(
'commands/include.c',
'commands/input.c',
'commands/layout.c',
'commands/layer_effects.c',
'commands/mode.c',
'commands/mouse_warping.c',
'commands/move.c',

View file

@ -230,6 +230,11 @@ following properties:
: string
: The transform currently in use for the output. This can be _normal_, _90_,
_180_, _270_, _flipped-90_, _flipped-180_, or _flipped-270_
|- layer_shell_surfaces
: array
: An array of all layer-shell surfaces attached to the output. Each object
contains _namespace_, _layer_, _effects_, and _extent_ object that contains _x_, _y_
_width_, and _height_
|- current_workspace
: string
: The workspace currently visible on the output or _null_ for disabled outputs
@ -259,6 +264,35 @@ following properties:
"scale": 1.0,
"subpixel_hinting": "rgb",
"transform": "normal",
"layer_shell_surfaces": [
{
"namespace": "wallpaper",
"layer": "background",
"extent": {
"width": 2560,
"height": 1440,
"x": 0,
"y": 0
},
"effects": [
]
},
{
"namespace": "waybar",
"layer": "top",
"extent": {
"width": 2548,
"height": 31,
"x": 6,
"y": 6
},
"effects": [
"blur",
"shadow",
"corner_rounding"
]
}
],
"current_workspace": "1",
"modes": [
{

View file

@ -787,6 +787,25 @@ The default colors are:
Whenever a window that matches _criteria_ appears, run list of commands.
See *CRITERIA* for more details.
*layer_effects* <layer-namespace> <effects>
Apply effects on specific layer shell surfaces, eg "waybar" or "rofi".
At least one effect needs to be provided. The <layer-namespace> can be
gotten through *sway-ipc*. Note: Surfaces in the _bottom_ layer cannot
use these effects.
Effects:
- *blur* <enable|disable>
- *shadows* <enable|disable>
- *corner_radius* <integer>
Example:
layer_effects "waybar" blur enable; shadows enable; corner_radius 6
SwayIPC Example:
swaymsg "layer_effects 'waybar' 'blur enable; shadows enable'"
*gaps* inner|outer|horizontal|vertical|top|right|bottom|left <amount>
Sets default _amount_ pixels of _inner_ or _outer_ gap, where the inner
affects spacing around each view and outer affects the spacing around each

View file

@ -57,12 +57,15 @@ void root_destroy(struct sway_root *root) {
/* Set minimized state from scratchpad container `show` state */
static void root_scratchpad_set_minimize(struct sway_container *con, bool minimize) {
struct wlr_foreign_toplevel_handle_v1 *foreign_toplevel = con->view->foreign_toplevel;
if (wlr_surface_is_xwayland_surface(con->view->surface)) {
struct wlr_xwayland_surface *xsurface = wlr_xwayland_surface_from_wlr_surface(con->view->surface);
wlr_xwayland_surface_set_minimized(xsurface, minimize);
} else if (foreign_toplevel) {
wlr_foreign_toplevel_handle_v1_set_minimized(foreign_toplevel, minimize);
if (con->view) {
struct wlr_foreign_toplevel_handle_v1 *foreign_toplevel = con->view->foreign_toplevel;
if (wlr_surface_is_xwayland_surface(con->view->surface)) {
struct wlr_xwayland_surface *xsurface = wlr_xwayland_surface_from_wlr_surface(con->view->surface);
wlr_xwayland_surface_set_minimized(xsurface, minimize);
} else if (foreign_toplevel) {
wlr_foreign_toplevel_handle_v1_set_minimized(foreign_toplevel, minimize);
}
}
}

View file

@ -233,7 +233,7 @@ static bool view_is_only_visible(struct sway_view *view) {
return true;
}
static bool gaps_to_edge(struct sway_view *view) {
bool gaps_to_edge(struct sway_view *view) {
struct side_gaps gaps = view->container->pending.workspace->current_gaps;
return gaps.top > 0 || gaps.right > 0 || gaps.bottom > 0 || gaps.left > 0;
}

View file

@ -5,11 +5,13 @@
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <wayland-util.h>
#include "stringop.h"
#include "sway/input/input-manager.h"
#include "sway/input/cursor.h"
#include "sway/input/seat.h"
#include "sway/ipc-server.h"
#include "sway/layers.h"
#include "sway/output.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
@ -690,6 +692,39 @@ void workspace_detect_urgent(struct sway_workspace *workspace) {
}
}
static bool find_blurred_con_iterator(struct sway_container *con, void *data) {
struct sway_view *view = con->view;
if (!view) {
return false;
}
return con->blur_enabled && !view->surface->opaque;
}
bool should_workspace_have_blur(struct sway_workspace *ws) {
if (!workspace_is_visible(ws)) {
return false;
}
if ((bool)workspace_find_container(ws, find_blurred_con_iterator, NULL)) {
return true;
}
// Check if any layer-shell surfaces will render effects
struct sway_output *sway_output = ws->output;
size_t len = sizeof(sway_output->layers) / sizeof(sway_output->layers[0]);
for (size_t i = 0; i < len; ++i) {
struct sway_layer_surface *lsurface;
wl_list_for_each(lsurface, &sway_output->layers[i], link) {
if (lsurface->has_blur && !lsurface->layer_surface->surface->opaque
&& lsurface->layer != ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND) {
return true;
}
}
}
return false;
}
void workspace_for_each_container(struct sway_workspace *ws,
void (*f)(struct sway_container *con, void *data), void *data) {
// Tiling