Merge branch 'hyprwm:main' into main

This commit is contained in:
J. J. Ramsey 2025-01-09 09:27:25 -05:00 committed by GitHub
commit 8332b5c45f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
80 changed files with 4502 additions and 1979 deletions

View file

@ -104,7 +104,7 @@ find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5) pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5)
pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2) pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2)
pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7) pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7)
pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.2.3) pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.3.3)
pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.1) pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.1)
add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}") add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}")
@ -316,6 +316,8 @@ protocolnew("protocols" "kde-server-decoration" true)
protocolnew("protocols" "wlr-data-control-unstable-v1" true) protocolnew("protocols" "wlr-data-control-unstable-v1" true)
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-focus-grab-v1" true) protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-focus-grab-v1" true)
protocolnew("protocols" "wlr-layer-shell-unstable-v1" true) protocolnew("protocols" "wlr-layer-shell-unstable-v1" true)
protocolnew("protocols" "xx-color-management-v4" true)
protocolnew("protocols" "frog-color-management-v1" true)
protocolnew("protocols" "wayland-drm" true) protocolnew("protocols" "wayland-drm" true)
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-ctm-control-v1" true) protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-ctm-control-v1" true)
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-surface-v1" true) protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-surface-v1" true)

View file

@ -81,6 +81,7 @@ general {
# https://wiki.hyprland.org/Configuring/Variables/#decoration # https://wiki.hyprland.org/Configuring/Variables/#decoration
decoration { decoration {
rounding = 10 rounding = 10
rounding_power = 2
# Change transparency of focused and unfocused windows # Change transparency of focused and unfocused windows
active_opacity = 1.0 active_opacity = 1.0

View file

@ -16,11 +16,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1734906446, "lastModified": 1736102453,
"narHash": "sha256-6OWluVE2A8xi+8V3jN9KA72RCgJjYdyyuLBUjxZ2q2U=", "narHash": "sha256-5qb4kb7Xbt8jJFL/oDqOor9Z2+E+A+ql3PiyDvsfWZ0=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "aquamarine", "repo": "aquamarine",
"rev": "eecb74dc79bb6752a2a507e6edee3042390a6091", "rev": "4846091641f3be0ad7542086d52769bb7932bde6",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -105,11 +105,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1734906236, "lastModified": 1736115290,
"narHash": "sha256-vH/ysV2ONGQgYZPtcJKwc8jJivzyVxru2aaOxC20ZOE=", "narHash": "sha256-Jcn6yAzfUMcxy3tN/iZRbi/QgrYm7XLyVRl9g/nbUl4=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprgraphics", "repo": "hyprgraphics",
"rev": "6dea3fba08fd704dd624b6d4b261638fb4003c9c", "rev": "52202272d89da32a9f866c0d10305a5e3d954c50",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -128,11 +128,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1735734474, "lastModified": 1735774328,
"narHash": "sha256-9OV4lOqrEJVLdOrpNN/9msNwAhI6FQTu4N7fufilG08=", "narHash": "sha256-vIRwLS9w+N99EU1aJ+XNOU6mJTxrUBa31i1r82l0V7s=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprland-protocols", "repo": "hyprland-protocols",
"rev": "271df559dd30e4bc5ec6af02d017ac0aaabd63a7", "rev": "e3b6af97ddcfaafbda8e2828c719a5af84f662cb",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -154,11 +154,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1734906472, "lastModified": 1736114838,
"narHash": "sha256-pWPRv/GA/X/iAwoE6gMNUqn/ZeJX1IeLPRpZI0tTPK0=", "narHash": "sha256-FxbuGQExtN37ToWYnGmO6weOYN6WPHN/RAqbr7gNPek=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprland-qtutils", "repo": "hyprland-qtutils",
"rev": "c77109d7e1ddbcdb87cafd32ce411f76328ae152", "rev": "6997fe382dcf396704227d2b98ffdd5066da6959",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -180,11 +180,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1734906259, "lastModified": 1735393019,
"narHash": "sha256-P79t/7HbACO4/PuJBroGpTptvCWJtXTv+gWsF+sM6MI=", "narHash": "sha256-NPpqA8rtmDLsEmZOmz+qR67zsB6Y503Jnv+nSFLKJZ8=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprlang", "repo": "hyprlang",
"rev": "0404833ea18d543df44df935ebf1b497310eb046", "rev": "55608efdaa387af7bfdc0eddb404c409958efa43",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -203,11 +203,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1735316583, "lastModified": 1736164519,
"narHash": "sha256-AiiUwHWHfEdpFzXy7l1x3zInCUa1xcRMrbZ1XRSkzwU=", "narHash": "sha256-1LimBKvDpBbeX+qW7T240WEyw+DBVpDotZB4JYm8Aps=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprutils", "repo": "hyprutils",
"rev": "8f15d45b120b33712f6db477fe5ffb18034d0ea8", "rev": "3c895da64b0eb19870142196fa48c07090b441c4",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -226,11 +226,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1734793513, "lastModified": 1735493474,
"narHash": "sha256-rrrHcXapXJvGFqX+L/Bb0182L25jofAZ0fm1FInvrTQ=", "narHash": "sha256-fktzv4NaqKm94VAkAoVqO/nqQlw+X0/tJJNAeCSfzK4=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprwayland-scanner", "repo": "hyprwayland-scanner",
"rev": "4d7367b6eee87397e2dbca2e78078dd0a4ef4c61", "rev": "de913476b59ee88685fdc018e77b8f6637a2ae0b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -241,11 +241,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1735291276, "lastModified": 1736012469,
"narHash": "sha256-NYVcA06+blsLG6wpAbSPTCyLvxD/92Hy4vlY9WxFI1M=", "narHash": "sha256-/qlNWm/IEVVH7GfgAIyP6EsVZI6zjAx1cV5zNyrs+rI=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "634fd46801442d760e09493a794c4f15db2d0cbb", "rev": "8f3e1f807051e32d8c95cd12b9b421623850a34d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -255,37 +255,20 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-stable": {
"locked": {
"lastModified": 1730741070,
"narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d063c1dd113c91ab27959ba540c0d9753409edf3",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"pre-commit-hooks": { "pre-commit-hooks": {
"inputs": { "inputs": {
"flake-compat": "flake-compat", "flake-compat": "flake-compat",
"gitignore": "gitignore", "gitignore": "gitignore",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ]
"nixpkgs-stable": "nixpkgs-stable"
}, },
"locked": { "locked": {
"lastModified": 1734797603, "lastModified": 1735882644,
"narHash": "sha256-ulZN7ps8nBV31SE+dwkDvKIzvN6hroRY8sYOT0w+E28=", "narHash": "sha256-3FZAG+pGt3OElQjesCAWeMkQ7C/nB1oTHLRQ8ceP110=",
"owner": "cachix", "owner": "cachix",
"repo": "git-hooks.nix", "repo": "git-hooks.nix",
"rev": "f0f0dc4920a903c3e08f5bdb9246bb572fcae498", "rev": "a5a961387e75ae44cc20f0a57ae463da5e959656",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -0,0 +1,366 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="frog_color_management_v1">
<copyright>
Copyright © 2023 Joshua Ashton for Valve Software
Copyright © 2023 Xaver Hugl
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
</copyright>
<description summary="experimental color management protocol">
The aim of this color management extension is to get HDR games working quickly,
and have an easy way to test implementations in the wild before the upstream
protocol is ready to be merged.
For that purpose it's intentionally limited and cut down and does not serve
all uses cases.
</description>
<interface name="frog_color_management_factory_v1" version="1">
<description summary="color management factory">
The color management factory singleton creates color managed surface objects.
</description>
<request name="destroy" type="destructor"></request>
<request name="get_color_managed_surface">
<description summary="create color management interface for surface">
</description>
<arg name="surface" type="object" interface="wl_surface"
summary="target surface" />
<arg name="callback" type="new_id" interface="frog_color_managed_surface"
summary="new color managed surface object" />
</request>
</interface>
<interface name="frog_color_managed_surface" version="1">
<description summary="color managed surface">
Interface for changing surface color management and HDR state.
An implementation must: support every part of the version
of the frog_color_managed_surface interface it exposes.
Including all known enums associated with a given version.
</description>
<request name="destroy" type="destructor">
<description summary="destroy color managed surface">
Destroying the color managed surface resets all known color
state for the surface back to 'undefined' implementation-specific
values.
</description>
</request>
<enum name="transfer_function">
<description summary="known transfer functions">
Extended information on the transfer functions described
here can be found in the Khronos Data Format specification:
https://registry.khronos.org/DataFormat/specs/1.3/dataformat.1.3.html
</description>
<entry name="undefined" value="0"
summary="specifies undefined, implementation-specific handling of the surface's transfer function." />
<entry name="srgb" value="1"
summary="specifies the sRGB non-linear EOTF. An implementation may: display this as Gamma 2.2 for the purposes of being consistent with content rendering across displays, rendering_intent and user expectations." />
<entry name="gamma_22" value="2" summary="specifies gamma 2.2 power curve as the EOTF" />
<entry name="st2084_pq" value="3"
summary="specifies the SMPTE ST2084 Perceptual Quantizer (PQ) EOTF" />
<entry name="scrgb_linear" value="4"
summary="specifies the scRGB (extended sRGB) linear EOTF. Note: Primaries outside the gamut triangle specified can be expressed with negative values for this transfer function." />
</enum>
<request name="set_known_transfer_function">
<description summary="sets a known transfer function for a surface" />
<arg name="transfer_function" type="uint" enum="transfer_function"
summary="transfer function for the surface" />
</request>
<enum name="primaries">
<description summary="known primaries" />
<entry name="undefined" value="0"
summary="specifies undefined, implementation-specific handling" />
<entry name="rec709" value="1" summary="specifies Rec.709/sRGB primaries with D65 white point" />
<entry name="rec2020" value="2"
summary="specifies Rec.2020/HDR10 primaries with D65 white point" />
</enum>
<request name="set_known_container_color_volume">
<description summary="sets the container color volume (primaries) for a surface" />
<arg name="primaries" type="uint" enum="primaries" summary="primaries for the surface" />
</request>
<enum name="render_intent">
<description summary="known render intents">
Extended information on render intents described
here can be found in ICC.1:2022:
https://www.color.org/specification/ICC.1-2022-05.pdf
</description>
<entry name="perceptual" value="0" summary="perceptual" />
</enum>
<request name="set_render_intent">
<description summary="sets the render intent for a surface">
NOTE: On a surface with "perceptual" (default) render intent, handling of the container's
color volume
is implementation-specific, and may differ between different transfer functions it is paired
with:
ie. sRGB + 709 rendering may have it's primaries widened to more of the available display's
gamut
to be be more pleasing for the viewer.
Compared to scRGB Linear + 709 being treated faithfully as 709
(including utilizing negatives out of the 709 gamut triangle)
</description>
<arg name="render_intent" type="uint" enum="render_intent"
summary="render intent for the surface" />
</request>
<request name="set_hdr_metadata">
<description summary="set HDR metadata for a surface">
Forwards HDR metadata from the client to the compositor.
HDR Metadata Infoframe as per CTA 861.G spec.
Usage of this HDR metadata is implementation specific and
outside of the scope of this protocol.
</description>
<arg name="mastering_display_primary_red_x" type="uint">
<description summary="red primary x coordinate">
Mastering Red Color Primary X Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="mastering_display_primary_red_y" type="uint">
<description summary="red primary y coordinate">
Mastering Red Color Primary Y Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="mastering_display_primary_green_x" type="uint">
<description summary="green primary x coordinate">
Mastering Green Color Primary X Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="mastering_display_primary_green_y" type="uint">
<description summary="green primary y coordinate">
Mastering Green Color Primary Y Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="mastering_display_primary_blue_x" type="uint">
<description summary="blue primary x coordinate">
Mastering Blue Color Primary X Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="mastering_display_primary_blue_y" type="uint">
<description summary="blue primary y coordinate">
Mastering Blue Color Primary Y Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="mastering_white_point_x" type="uint">
<description summary="white point x coordinate">
Mastering White Point X Coordinate of the Data.
These are coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="mastering_white_point_y" type="uint">
<description summary="white point y coordinate">
Mastering White Point Y Coordinate of the Data.
These are coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="max_display_mastering_luminance" type="uint">
<description summary="max display mastering luminance">
Max Mastering Display Luminance.
This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
</description>
</arg>
<arg name="min_display_mastering_luminance" type="uint">
<description summary="min display mastering luminance">
Min Mastering Display Luminance.
This value is coded as an unsigned 16-bit value in units of
0.0001 cd/m2, where 0x0001 represents 0.0001 cd/m2 and 0xFFFF
represents 6.5535 cd/m2.
</description>
</arg>
<arg name="max_cll" type="uint">
<description summary="max content light level">
Max Content Light Level.
This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
</description>
</arg>
<arg name="max_fall" type="uint">
<description summary="max frame average light level">
Max Frame Average Light Level.
This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
</description>
</arg>
</request>
<event name="preferred_metadata">
<description summary="preferred metadata for a surface">
Current preferred metadata for a surface.
The application should use this information to tone-map its buffers
to this target before committing.
This metadata does not necessarily correspond to any physical output, but
rather what the compositor thinks would be best for a given surface.
</description>
<arg name="transfer_function" type="uint" enum="transfer_function">
<description summary="output's current transfer function">
Specifies a known transfer function that corresponds to the
output the surface is targeting.
</description>
</arg>
<arg name="output_display_primary_red_x" type="uint">
<description summary="red primary x coordinate">
Output Red Color Primary X Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="output_display_primary_red_y" type="uint">
<description summary="red primary y coordinate">
Output Red Color Primary Y Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="output_display_primary_green_x" type="uint">
<description summary="green primary x coordinate">
Output Green Color Primary X Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="output_display_primary_green_y" type="uint">
<description summary="green primary y coordinate">
Output Green Color Primary Y Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="output_display_primary_blue_x" type="uint">
<description summary="blue primary x coordinate">
Output Blue Color Primary X Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="output_display_primary_blue_y" type="uint">
<description summary="blue primary y coordinate">
Output Blue Color Primary Y Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="output_white_point_x" type="uint">
<description summary="white point x coordinate">
Output White Point X Coordinate of the Data.
These are coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="output_white_point_y" type="uint">
<description summary="white point y coordinate">
Output White Point Y Coordinate of the Data.
These are coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="max_luminance" type="uint">
<description summary="maximum luminance">
Max Output Luminance
The max luminance in nits that the output is capable of rendering in small areas.
Content should: not exceed this value to avoid clipping.
This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
</description>
</arg>
<arg name="min_luminance" type="uint">
<description summary="minimum luminance">
Min Output Luminance
The min luminance that the output is capable of rendering.
Content should: not exceed this value to avoid clipping.
This value is coded as an unsigned 16-bit value in units of
0.0001 cd/m2, where 0x0001 represents 0.0001 cd/m2 and 0xFFFF
represents 6.5535 cd/m2.
</description>
</arg>
<arg name="max_full_frame_luminance" type="uint">
<description summary="maximum full frame luminance">
Max Full Frame Luminance
The max luminance in nits that the output is capable of rendering for the
full frame sustained.
This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
</description>
</arg>
</event>
</interface>
</protocol>

View file

@ -33,6 +33,8 @@ protocols = [
'wayland-drm.xml', 'wayland-drm.xml',
'wlr-data-control-unstable-v1.xml', 'wlr-data-control-unstable-v1.xml',
'wlr-screencopy-unstable-v1.xml', 'wlr-screencopy-unstable-v1.xml',
'xx-color-management-v4.xml',
'frog-color-management-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml', hyprland_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml', hyprland_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml', hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml',

File diff suppressed because it is too large Load diff

View file

@ -31,6 +31,7 @@
#include "protocols/XDGShell.hpp" #include "protocols/XDGShell.hpp"
#include "protocols/XDGOutput.hpp" #include "protocols/XDGOutput.hpp"
#include "protocols/SecurityContext.hpp" #include "protocols/SecurityContext.hpp"
#include "protocols/ColorManagement.hpp"
#include "protocols/core/Compositor.hpp" #include "protocols/core/Compositor.hpp"
#include "protocols/core/Subcompositor.hpp" #include "protocols/core/Subcompositor.hpp"
#include "desktop/LayerSurface.hpp" #include "desktop/LayerSurface.hpp"
@ -569,7 +570,7 @@ void CCompositor::initManagers(eManagersInitStage stage) {
g_pKeybindManager = std::make_unique<CKeybindManager>(); g_pKeybindManager = std::make_unique<CKeybindManager>();
Debug::log(LOG, "Creating the AnimationManager!"); Debug::log(LOG, "Creating the AnimationManager!");
g_pAnimationManager = std::make_unique<CAnimationManager>(); g_pAnimationManager = std::make_unique<CHyprAnimationManager>();
Debug::log(LOG, "Creating the ConfigManager!"); Debug::log(LOG, "Creating the ConfigManager!");
g_pConfigManager = std::make_unique<CConfigManager>(); g_pConfigManager = std::make_unique<CConfigManager>();
@ -964,11 +965,11 @@ SP<CWLSurfaceResource> CCompositor::vectorWindowToSurface(const Vector2D& pos, P
if (PPOPUP) { if (PPOPUP) {
const auto OFF = PPOPUP->coordsRelativeToParent(); const auto OFF = PPOPUP->coordsRelativeToParent();
sl = pos - pWindow->m_vRealPosition.goal() - OFF; sl = pos - pWindow->m_vRealPosition->goal() - OFF;
return PPOPUP->m_pWLSurface->resource(); return PPOPUP->m_pWLSurface->resource();
} }
auto [surf, local] = pWindow->m_pWLSurface->resource()->at(pos - pWindow->m_vRealPosition.goal(), true); auto [surf, local] = pWindow->m_pWLSurface->resource()->at(pos - pWindow->m_vRealPosition->goal(), true);
if (surf) { if (surf) {
sl = local; sl = local;
return surf; return surf;
@ -982,7 +983,7 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindo
return {}; return {};
if (pWindow->m_bIsX11) if (pWindow->m_bIsX11)
return vec - pWindow->m_vRealPosition.goal(); return vec - pWindow->m_vRealPosition->goal();
const auto PPOPUP = pWindow->m_pPopupHead->at(vec); const auto PPOPUP = pWindow->m_pPopupHead->at(vec);
if (PPOPUP) if (PPOPUP)
@ -1001,9 +1002,9 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindo
CBox geom = pWindow->m_pXDGSurface->current.geometry; CBox geom = pWindow->m_pXDGSurface->current.geometry;
if (std::get<1>(iterData) == Vector2D{-1337, -1337}) if (std::get<1>(iterData) == Vector2D{-1337, -1337})
return vec - pWindow->m_vRealPosition.goal(); return vec - pWindow->m_vRealPosition->goal();
return vec - pWindow->m_vRealPosition.goal() - std::get<1>(iterData) + Vector2D{geom.x, geom.y}; return vec - pWindow->m_vRealPosition->goal() - std::get<1>(iterData) + Vector2D{geom.x, geom.y};
} }
PHLMONITOR CCompositor::getMonitorFromOutput(SP<Aquamarine::IOutput> out) { PHLMONITOR CCompositor::getMonitorFromOutput(SP<Aquamarine::IOutput> out) {
@ -1211,7 +1212,7 @@ void CCompositor::focusSurface(SP<CWLSurfaceResource> pSurface, PHLWINDOW pWindo
SP<CWLSurfaceResource> CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, PHLMONITOR monitor, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { SP<CWLSurfaceResource> CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, PHLMONITOR monitor, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) {
for (auto const& lsl : monitor->m_aLayerSurfaceLayers | std::views::reverse) { for (auto const& lsl : monitor->m_aLayerSurfaceLayers | std::views::reverse) {
for (auto const& ls : lsl | std::views::reverse) { for (auto const& ls : lsl | std::views::reverse) {
if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->mapped) || ls->alpha.value() == 0.f) if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->mapped) || ls->alpha->value() == 0.f)
continue; continue;
auto SURFACEAT = ls->popupHead->at(pos, true); auto SURFACEAT = ls->popupHead->at(pos, true);
@ -1229,7 +1230,7 @@ SP<CWLSurfaceResource> CCompositor::vectorToLayerPopupSurface(const Vector2D& po
SP<CWLSurfaceResource> CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<PHLLSREF>* layerSurfaces, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { SP<CWLSurfaceResource> CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<PHLLSREF>* layerSurfaces, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) {
for (auto const& ls : *layerSurfaces | std::views::reverse) { for (auto const& ls : *layerSurfaces | std::views::reverse) {
if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha.value() == 0.f) if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha->value() == 0.f)
continue; continue;
auto [surf, local] = ls->layerSurface->surface->at(pos - ls->geometry.pos(), true); auto [surf, local] = ls->layerSurface->surface->at(pos - ls->geometry.pos(), true);
@ -1378,7 +1379,7 @@ void CCompositor::cleanupFadingOut(const MONITORID& monid) {
if (w->monitorID() != monid && w->m_pMonitor) if (w->monitorID() != monid && w->m_pMonitor)
continue; continue;
if (!w->m_bFadingOut || w->m_fAlpha.value() == 0.f) { if (!w->m_bFadingOut || w->m_fAlpha->value() == 0.f) {
w->m_bFadingOut = false; w->m_bFadingOut = false;
@ -1831,8 +1832,8 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) {
pWindow->m_cRealBorderColorPrevious = pWindow->m_cRealBorderColor; pWindow->m_cRealBorderColorPrevious = pWindow->m_cRealBorderColor;
pWindow->m_cRealBorderColor = grad; pWindow->m_cRealBorderColor = grad;
pWindow->m_fBorderFadeAnimationProgress.setValueAndWarp(0.f); pWindow->m_fBorderFadeAnimationProgress->setValueAndWarp(0.f);
pWindow->m_fBorderFadeAnimationProgress = 1.f; *pWindow->m_fBorderFadeAnimationProgress = 1.f;
}; };
const bool IS_SHADOWED_BY_MODAL = pWindow->m_pXDGSurface && pWindow->m_pXDGSurface->toplevel && pWindow->m_pXDGSurface->toplevel->anyChildModal(); const bool IS_SHADOWED_BY_MODAL = pWindow->m_pXDGSurface && pWindow->m_pXDGSurface->toplevel && pWindow->m_pXDGSurface->toplevel->anyChildModal();
@ -1855,18 +1856,18 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) {
} }
// tick angle if it's not running (aka dead) // tick angle if it's not running (aka dead)
if (!pWindow->m_fBorderAngleAnimationProgress.isBeingAnimated()) if (!pWindow->m_fBorderAngleAnimationProgress->isBeingAnimated())
pWindow->m_fBorderAngleAnimationProgress.setValueAndWarp(0.f); pWindow->m_fBorderAngleAnimationProgress->setValueAndWarp(0.f);
// opacity // opacity
const auto PWORKSPACE = pWindow->m_pWorkspace; const auto PWORKSPACE = pWindow->m_pWorkspace;
if (pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) { if (pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) {
pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaFullscreen.valueOrDefault().applyAlpha(*PFULLSCREENALPHA); *pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaFullscreen.valueOrDefault().applyAlpha(*PFULLSCREENALPHA);
} else { } else {
if (pWindow == m_pLastWindow) if (pWindow == m_pLastWindow)
pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alpha.valueOrDefault().applyAlpha(*PACTIVEALPHA); *pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alpha.valueOrDefault().applyAlpha(*PACTIVEALPHA);
else else
pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaInactive.valueOrDefault().applyAlpha(*PINACTIVEALPHA); *pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaInactive.valueOrDefault().applyAlpha(*PINACTIVEALPHA);
} }
// dim // dim
@ -1879,16 +1880,16 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) {
if (IS_SHADOWED_BY_MODAL) if (IS_SHADOWED_BY_MODAL)
goalDim += (1.F - goalDim) / 2.F; goalDim += (1.F - goalDim) / 2.F;
pWindow->m_fDimPercent = goalDim; *pWindow->m_fDimPercent = goalDim;
// shadow // shadow
if (!pWindow->isX11OverrideRedirect() && !pWindow->m_bX11DoesntWantBorders) { if (!pWindow->isX11OverrideRedirect() && !pWindow->m_bX11DoesntWantBorders) {
if (pWindow == m_pLastWindow) if (pWindow == m_pLastWindow)
pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOL); *pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOL);
else else
pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOLINACTIVE != INT64_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL); *pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOLINACTIVE != INT64_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL);
} else { } else {
pWindow->m_cRealShadowColor.setValueAndWarp(CHyprColor(0, 0, 0, 0)); // no shadow pWindow->m_cRealShadowColor->setValueAndWarp(CHyprColor(0, 0, 0, 0)); // no shadow
} }
pWindow->updateWindowDecos(); pWindow->updateWindowDecos();
@ -1932,11 +1933,11 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor
// additionally, move floating and fs windows manually // additionally, move floating and fs windows manually
if (w->m_bIsFloating) if (w->m_bIsFloating)
w->m_vRealPosition = w->m_vRealPosition.goal() - pMonitorA->vecPosition + pMonitorB->vecPosition; *w->m_vRealPosition = w->m_vRealPosition->goal() - pMonitorA->vecPosition + pMonitorB->vecPosition;
if (w->isFullscreen()) { if (w->isFullscreen()) {
w->m_vRealPosition = pMonitorB->vecPosition; *w->m_vRealPosition = pMonitorB->vecPosition;
w->m_vRealSize = pMonitorB->vecSize; *w->m_vRealSize = pMonitorB->vecSize;
} }
w->updateToplevel(); w->updateToplevel();
@ -1957,11 +1958,11 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor
// additionally, move floating and fs windows manually // additionally, move floating and fs windows manually
if (w->m_bIsFloating) if (w->m_bIsFloating)
w->m_vRealPosition = w->m_vRealPosition.goal() - pMonitorB->vecPosition + pMonitorA->vecPosition; *w->m_vRealPosition = w->m_vRealPosition->goal() - pMonitorB->vecPosition + pMonitorA->vecPosition;
if (w->isFullscreen()) { if (w->isFullscreen()) {
w->m_vRealPosition = pMonitorA->vecPosition; *w->m_vRealPosition = pMonitorA->vecPosition;
w->m_vRealSize = pMonitorA->vecSize; *w->m_vRealSize = pMonitorA->vecSize;
} }
w->updateToplevel(); w->updateToplevel();
@ -2135,14 +2136,14 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo
if (w->m_bIsMapped && !w->isHidden()) { if (w->m_bIsMapped && !w->isHidden()) {
if (POLDMON) { if (POLDMON) {
if (w->m_bIsFloating) if (w->m_bIsFloating)
w->m_vRealPosition = w->m_vRealPosition.goal() - POLDMON->vecPosition + pMonitor->vecPosition; *w->m_vRealPosition = w->m_vRealPosition->goal() - POLDMON->vecPosition + pMonitor->vecPosition;
if (w->isFullscreen()) { if (w->isFullscreen()) {
w->m_vRealPosition = pMonitor->vecPosition; *w->m_vRealPosition = pMonitor->vecPosition;
w->m_vRealSize = pMonitor->vecSize; *w->m_vRealSize = pMonitor->vecSize;
} }
} else { } else {
w->m_vRealPosition = Vector2D{(int)w->m_vRealPosition.goal().x % (int)pMonitor->vecSize.x, (int)w->m_vRealPosition.goal().y % (int)pMonitor->vecSize.y}; *w->m_vRealPosition = Vector2D{(int)w->m_vRealPosition->goal().x % (int)pMonitor->vecSize.x, (int)w->m_vRealPosition->goal().y % (int)pMonitor->vecSize.y};
} }
} }
@ -2216,9 +2217,9 @@ void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) {
continue; continue;
if (!FULLSCREEN) if (!FULLSCREEN)
w->m_fAlpha = 1.f; *w->m_fAlpha = 1.f;
else if (!w->isFullscreen()) else if (!w->isFullscreen())
w->m_fAlpha = !w->m_bCreatedOverFullscreen ? 0.f : 1.f; *w->m_fAlpha = !w->m_bCreatedOverFullscreen ? 0.f : 1.f;
} }
} }
@ -2227,7 +2228,7 @@ void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) {
if (pWorkspace->m_iID == PMONITOR->activeWorkspaceID() || pWorkspace->m_iID == PMONITOR->activeSpecialWorkspaceID()) { if (pWorkspace->m_iID == PMONITOR->activeWorkspaceID() || pWorkspace->m_iID == PMONITOR->activeSpecialWorkspaceID()) {
for (auto const& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { for (auto const& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
if (!ls->fadingOut) if (!ls->fadingOut)
ls->alpha = FULLSCREEN && pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; *ls->alpha = FULLSCREEN && pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f;
} }
} }
} }
@ -2317,7 +2318,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, SFullscreenS
updateFullscreenFadeOnWorkspace(PWORKSPACE); updateFullscreenFadeOnWorkspace(PWORKSPACE);
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal(), true); g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize->goal(), true);
PWORKSPACE->forceReportSizesToWindows(); PWORKSPACE->forceReportSizesToWindows();
@ -2573,7 +2574,7 @@ PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITO
const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, getMonitorFromID(monID), NAME, SPECIAL, isEmpty)); const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, getMonitorFromID(monID), NAME, SPECIAL, isEmpty));
PWORKSPACE->m_fAlpha.setValueAndWarp(0); PWORKSPACE->m_fAlpha->setValueAndWarp(0);
return PWORKSPACE; return PWORKSPACE;
} }
@ -2659,7 +2660,7 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor
const PHLWINDOW pFirstWindowOnWorkspace = pWorkspace->getFirstWindow(); const PHLWINDOW pFirstWindowOnWorkspace = pWorkspace->getFirstWindow();
const int visibleWindowsOnWorkspace = pWorkspace->getWindows(std::nullopt, true); const int visibleWindowsOnWorkspace = pWorkspace->getWindows(std::nullopt, true);
const auto PWINDOWMONITOR = pWindow->m_pMonitor.lock(); const auto PWINDOWMONITOR = pWindow->m_pMonitor.lock();
const auto POSTOMON = pWindow->m_vRealPosition.goal() - PWINDOWMONITOR->vecPosition; const auto POSTOMON = pWindow->m_vRealPosition->goal() - PWINDOWMONITOR->vecPosition;
const auto PWORKSPACEMONITOR = pWorkspace->m_pMonitor.lock(); const auto PWORKSPACEMONITOR = pWorkspace->m_pMonitor.lock();
if (!pWindow->m_bIsFloating) if (!pWindow->m_bIsFloating)
@ -2696,7 +2697,7 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor
g_pLayoutManager->getCurrentLayout()->onWindowCreatedTiling(pWindow); g_pLayoutManager->getCurrentLayout()->onWindowCreatedTiling(pWindow);
if (pWindow->m_bIsFloating) if (pWindow->m_bIsFloating)
pWindow->m_vRealPosition = POSTOMON + PWORKSPACEMONITOR->vecPosition; *pWindow->m_vRealPosition = POSTOMON + PWORKSPACEMONITOR->vecPosition;
} }
pWindow->updateToplevel(); pWindow->updateToplevel();
@ -2721,8 +2722,8 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor
g_pCompositor->updateSuspendedStates(); g_pCompositor->updateSuspendedStates();
if (!WASVISIBLE && pWindow->m_pWorkspace && pWindow->m_pWorkspace->isVisible()) { if (!WASVISIBLE && pWindow->m_pWorkspace && pWindow->m_pWorkspace->isVisible()) {
pWindow->m_fMovingFromWorkspaceAlpha.setValueAndWarp(0.F); pWindow->m_fMovingFromWorkspaceAlpha->setValueAndWarp(0.F);
pWindow->m_fMovingFromWorkspaceAlpha = 1.F; *pWindow->m_fMovingFromWorkspaceAlpha = 1.F;
} }
} }
@ -2985,4 +2986,22 @@ void CCompositor::onNewMonitor(SP<Aquamarine::IOutput> output) {
g_pHyprRenderer->damageMonitor(PNEWMONITOR); g_pHyprRenderer->damageMonitor(PNEWMONITOR);
PNEWMONITOR->onMonitorFrame(); PNEWMONITOR->onMonitorFrame();
if (PROTO::colorManagement && shouldChangePreferredImageDescription())
PROTO::colorManagement->onImagePreferredChanged();
}
SImageDescription CCompositor::getPreferredImageDescription() {
if (!PROTO::colorManagement) {
Debug::log(ERR, "FIXME: color management protocol is not enabled, returning empty image description");
return SImageDescription{};
}
Debug::log(WARN, "FIXME: color management protocol is enabled, determine correct preferred image description");
// should determine some common settings to avoid unnecessary transformations while keeping maximum displayable precision
return SImageDescription{.primaries = NColorPrimaries::BT709};
}
bool CCompositor::shouldChangePreferredImageDescription() {
Debug::log(WARN, "FIXME: color management protocol is enabled and outputs changed, check preferred image description changes");
return false;
} }

View file

@ -23,6 +23,7 @@
#include "helpers/Monitor.hpp" #include "helpers/Monitor.hpp"
#include "desktop/Workspace.hpp" #include "desktop/Workspace.hpp"
#include "desktop/Window.hpp" #include "desktop/Window.hpp"
#include "protocols/types/ColorManagement.hpp"
#include "render/Renderer.hpp" #include "render/Renderer.hpp"
#include "render/OpenGL.hpp" #include "render/OpenGL.hpp"
#include "hyprerror/HyprError.hpp" #include "hyprerror/HyprError.hpp"
@ -169,6 +170,9 @@ class CCompositor {
void updateSuspendedStates(); void updateSuspendedStates();
void onNewMonitor(SP<Aquamarine::IOutput> output); void onNewMonitor(SP<Aquamarine::IOutput> output);
SImageDescription getPreferredImageDescription();
bool shouldChangePreferredImageDescription();
std::string explicitConfigPath; std::string explicitConfigPath;
private: private:

View file

@ -139,6 +139,12 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.type = CONFIG_OPTION_INT, .type = CONFIG_OPTION_INT,
.data = SConfigOptionDescription::SRangeData{0, 0, 20}, .data = SConfigOptionDescription::SRangeData{0, 0, 20},
}, },
SConfigOptionDescription{
.value = "decoration:rounding_power",
.description = "rouding power of corners (2 is a circle)",
.type = CONFIG_OPTION_FLOAT,
.data = SConfigOptionDescription::SFloatData{2, 2, 10},
},
SConfigOptionDescription{ SConfigOptionDescription{
.value = "decoration:active_opacity", .value = "decoration:active_opacity",
.description = "opacity of active windows. [0.0 - 1.0]", .description = "opacity of active windows. [0.0 - 1.0]",
@ -1626,6 +1632,12 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.type = CONFIG_OPTION_INT, .type = CONFIG_OPTION_INT,
.data = SConfigOptionDescription::SRangeData{2, 0, 10}, //##TODO RANGE? .data = SConfigOptionDescription::SRangeData{2, 0, 10}, //##TODO RANGE?
}, },
SConfigOptionDescription{
.value = "master:center_master_slaves_on_right",
.description = "set if the slaves should appear on right of master when slave_count_for_center_master > 2",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true},
},
SConfigOptionDescription{ SConfigOptionDescription{
.value = "master:center_ignores_reserved", .value = "master:center_ignores_reserved",
.description = "centers the master window on monitor ignoring reserved areas", .description = "centers the master window on monitor ignoring reserved areas",
@ -1646,4 +1658,22 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.type = CONFIG_OPTION_BOOL, .type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true}, .data = SConfigOptionDescription::SBoolData{true},
}, },
SConfigOptionDescription{
.value = "experimental:wide_color_gamut",
.description = "force wide color gamut for all supported outputs",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "experimental:hdr",
.description = "force static hdr for all supported outputs",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "experimental:xx_color_management_v4",
.description = "enable color management protocol",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
}; };

View file

@ -11,6 +11,7 @@
#include "../protocols/LayerShell.hpp" #include "../protocols/LayerShell.hpp"
#include "../xwayland/XWayland.hpp" #include "../xwayland/XWayland.hpp"
#include "../protocols/OutputManagement.hpp" #include "../protocols/OutputManagement.hpp"
#include "managers/AnimationManager.hpp"
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
@ -32,6 +33,7 @@
#include <hyprutils/string/String.hpp> #include <hyprutils/string/String.hpp>
#include <filesystem> #include <filesystem>
using namespace Hyprutils::String; using namespace Hyprutils::String;
using namespace Hyprutils::Animation;
//NOLINTNEXTLINE //NOLINTNEXTLINE
extern "C" char** environ; extern "C" char** environ;
@ -427,6 +429,7 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("debug:colored_stdout_logs", Hyprlang::INT{1}); m_pConfig->addConfigValue("debug:colored_stdout_logs", Hyprlang::INT{1});
m_pConfig->addConfigValue("decoration:rounding", Hyprlang::INT{0}); m_pConfig->addConfigValue("decoration:rounding", Hyprlang::INT{0});
m_pConfig->addConfigValue("decoration:rounding_power", {2.F});
m_pConfig->addConfigValue("decoration:blur:enabled", Hyprlang::INT{1}); m_pConfig->addConfigValue("decoration:blur:enabled", Hyprlang::INT{1});
m_pConfig->addConfigValue("decoration:blur:size", Hyprlang::INT{8}); m_pConfig->addConfigValue("decoration:blur:size", Hyprlang::INT{8});
m_pConfig->addConfigValue("decoration:blur:passes", Hyprlang::INT{1}); m_pConfig->addConfigValue("decoration:blur:passes", Hyprlang::INT{1});
@ -478,6 +481,7 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("master:mfact", {0.55f}); m_pConfig->addConfigValue("master:mfact", {0.55f});
m_pConfig->addConfigValue("master:new_status", {"slave"}); m_pConfig->addConfigValue("master:new_status", {"slave"});
m_pConfig->addConfigValue("master:slave_count_for_center_master", Hyprlang::INT{2}); m_pConfig->addConfigValue("master:slave_count_for_center_master", Hyprlang::INT{2});
m_pConfig->addConfigValue("master:center_master_slaves_on_right", Hyprlang::INT{1});
m_pConfig->addConfigValue("master:center_ignores_reserved", Hyprlang::INT{0}); m_pConfig->addConfigValue("master:center_ignores_reserved", Hyprlang::INT{0});
m_pConfig->addConfigValue("master:new_on_active", {"none"}); m_pConfig->addConfigValue("master:new_on_active", {"none"});
m_pConfig->addConfigValue("master:new_on_top", Hyprlang::INT{0}); m_pConfig->addConfigValue("master:new_on_top", Hyprlang::INT{0});
@ -574,7 +578,7 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("opengl:nvidia_anti_flicker", Hyprlang::INT{1}); m_pConfig->addConfigValue("opengl:nvidia_anti_flicker", Hyprlang::INT{1});
m_pConfig->addConfigValue("opengl:force_introspection", Hyprlang::INT{1}); // TODO: remove this. I don't think it does us any good to disable intro. m_pConfig->addConfigValue("opengl:force_introspection", Hyprlang::INT{1}); // TODO: remove this. I don't think it does us any good to disable intro.
m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{2}); m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{0});
m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0});
m_pConfig->addConfigValue("cursor:min_refresh_rate", Hyprlang::INT{24}); m_pConfig->addConfigValue("cursor:min_refresh_rate", Hyprlang::INT{24});
m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{0});
@ -589,7 +593,7 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("cursor:sync_gsettings_theme", Hyprlang::INT{1}); m_pConfig->addConfigValue("cursor:sync_gsettings_theme", Hyprlang::INT{1});
m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0});
m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1}); m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1});
m_pConfig->addConfigValue("cursor:use_cpu_buffer", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:use_cpu_buffer", Hyprlang::INT{2});
m_pConfig->addConfigValue("cursor:warp_back_after_non_mouse_input", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:warp_back_after_non_mouse_input", Hyprlang::INT{0});
m_pConfig->addConfigValue("autogenerated", Hyprlang::INT{0}); m_pConfig->addConfigValue("autogenerated", Hyprlang::INT{0});
@ -618,6 +622,10 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("ecosystem:no_update_news", Hyprlang::INT{0}); m_pConfig->addConfigValue("ecosystem:no_update_news", Hyprlang::INT{0});
m_pConfig->addConfigValue("experimental:wide_color_gamut", Hyprlang::INT{0});
m_pConfig->addConfigValue("experimental:hdr", Hyprlang::INT{0});
m_pConfig->addConfigValue("experimental:xx_color_management_v4", Hyprlang::INT{0});
// devices // devices
m_pConfig->addSpecialCategory("device", {"name"}); m_pConfig->addSpecialCategory("device", {"name"});
m_pConfig->addSpecialConfigValue("device", "sensitivity", {0.F}); m_pConfig->addSpecialConfigValue("device", "sensitivity", {0.F});
@ -679,7 +687,6 @@ CConfigManager::CConfigManager() {
m_pConfig->commence(); m_pConfig->commence();
setDefaultAnimationVars();
resetHLConfig(); resetHLConfig();
Debug::log(INFO, Debug::log(INFO,
@ -778,76 +785,46 @@ void CConfigManager::reload() {
} }
void CConfigManager::setDefaultAnimationVars() { void CConfigManager::setDefaultAnimationVars() {
if (isFirstLaunch) { m_AnimationTree.createNode("__internal_fadeCTM");
INITANIMCFG("__internal_fadeCTM"); m_AnimationTree.createNode("global");
INITANIMCFG("global"); // global
INITANIMCFG("windows"); m_AnimationTree.createNode("windows", "global");
INITANIMCFG("layers"); m_AnimationTree.createNode("layers", "global");
INITANIMCFG("fade"); m_AnimationTree.createNode("fade", "global");
INITANIMCFG("border"); m_AnimationTree.createNode("border", "global");
INITANIMCFG("borderangle"); m_AnimationTree.createNode("borderangle", "global");
m_AnimationTree.createNode("workspaces", "global");
// layer
m_AnimationTree.createNode("layersIn", "layers");
m_AnimationTree.createNode("layersOut", "layers");
// windows // windows
INITANIMCFG("windowsIn"); m_AnimationTree.createNode("windowsIn", "windows");
INITANIMCFG("windowsOut"); m_AnimationTree.createNode("windowsOut", "windows");
INITANIMCFG("windowsMove"); m_AnimationTree.createNode("windowsMove", "windows");
// layers
INITANIMCFG("layersIn");
INITANIMCFG("layersOut");
// fade // fade
INITANIMCFG("fadeIn"); m_AnimationTree.createNode("fadeIn", "fade");
INITANIMCFG("fadeOut"); m_AnimationTree.createNode("fadeOut", "fade");
INITANIMCFG("fadeSwitch"); m_AnimationTree.createNode("fadeSwitch", "fade");
INITANIMCFG("fadeShadow"); m_AnimationTree.createNode("fadeShadow", "fade");
INITANIMCFG("fadeDim"); m_AnimationTree.createNode("fadeDim", "fade");
m_AnimationTree.createNode("fadeLayers", "fade");
// border m_AnimationTree.createNode("fadeLayersIn", "fadeLayers");
m_AnimationTree.createNode("fadeLayersOut", "fadeLayers");
// workspaces // workspaces
INITANIMCFG("workspaces"); m_AnimationTree.createNode("workspacesIn", "workspaces");
INITANIMCFG("workspacesIn"); m_AnimationTree.createNode("workspacesOut", "workspaces");
INITANIMCFG("workspacesOut"); m_AnimationTree.createNode("specialWorkspace", "workspaces");
INITANIMCFG("specialWorkspace"); m_AnimationTree.createNode("specialWorkspaceIn", "specialWorkspace");
INITANIMCFG("specialWorkspaceIn"); m_AnimationTree.createNode("specialWorkspaceOut", "specialWorkspace");
INITANIMCFG("specialWorkspaceOut");
}
// init the values // init the root nodes
animationConfig["global"] = {false, "default", "", 8.f, 1, &animationConfig["general"], nullptr}; m_AnimationTree.setConfigForNode("global", 1, 8.f, "", "default");
m_AnimationTree.setConfigForNode("__internal_fadeCTM", 1, 5.f, "", "linear");
animationConfig["__internal_fadeCTM"] = {false, "linear", "", 5.F, 1, &animationConfig["__internal_fadeCTM"], nullptr};
CREATEANIMCFG("windows", "global");
CREATEANIMCFG("layers", "global");
CREATEANIMCFG("fade", "global");
CREATEANIMCFG("border", "global");
CREATEANIMCFG("borderangle", "global");
CREATEANIMCFG("workspaces", "global");
CREATEANIMCFG("layersIn", "layers");
CREATEANIMCFG("layersOut", "layers");
CREATEANIMCFG("windowsIn", "windows");
CREATEANIMCFG("windowsOut", "windows");
CREATEANIMCFG("windowsMove", "windows");
CREATEANIMCFG("fadeIn", "fade");
CREATEANIMCFG("fadeOut", "fade");
CREATEANIMCFG("fadeSwitch", "fade");
CREATEANIMCFG("fadeShadow", "fade");
CREATEANIMCFG("fadeDim", "fade");
CREATEANIMCFG("fadeLayers", "fade");
CREATEANIMCFG("fadeLayersIn", "fadeLayers");
CREATEANIMCFG("fadeLayersOut", "fadeLayers");
CREATEANIMCFG("workspacesIn", "workspaces");
CREATEANIMCFG("workspacesOut", "workspaces");
CREATEANIMCFG("specialWorkspace", "workspaces");
CREATEANIMCFG("specialWorkspaceIn", "specialWorkspace");
CREATEANIMCFG("specialWorkspaceOut", "specialWorkspace");
} }
std::optional<std::string> CConfigManager::resetHLConfig() { std::optional<std::string> CConfigManager::resetHLConfig() {
@ -855,6 +832,8 @@ std::optional<std::string> CConfigManager::resetHLConfig() {
m_vWindowRules.clear(); m_vWindowRules.clear();
g_pKeybindManager->clearKeybinds(); g_pKeybindManager->clearKeybinds();
g_pAnimationManager->removeAllBeziers(); g_pAnimationManager->removeAllBeziers();
g_pAnimationManager->addBezierWithName("linear", Vector2D(0.0, 0.0), Vector2D(1.0, 1.0));
m_mAdditionalReservedAreas.clear(); m_mAdditionalReservedAreas.clear();
m_dBlurLSNamespaces.clear(); m_dBlurLSNamespaces.clear();
m_vWorkspaceRules.clear(); m_vWorkspaceRules.clear();
@ -1645,8 +1624,8 @@ void CConfigManager::ensureVRR(PHLMONITOR pMonitor) {
} }
} }
SAnimationPropertyConfig* CConfigManager::getAnimationPropertyConfig(const std::string& name) { SP<SAnimationPropertyConfig> CConfigManager::getAnimationPropertyConfig(const std::string& name) {
return &animationConfig[name]; return m_AnimationTree.getConfig(name);
} }
void CConfigManager::addParseError(const std::string& err) { void CConfigManager::addParseError(const std::string& err) {
@ -1709,8 +1688,8 @@ ICustomConfigValueData::~ICustomConfigValueData() {
; // empty ; // empty
} }
std::unordered_map<std::string, SAnimationPropertyConfig> CConfigManager::getAnimationConfig() { const std::unordered_map<std::string, SP<SAnimationPropertyConfig>>& CConfigManager::getAnimationConfig() {
return animationConfig; return m_AnimationTree.getFullConfig();
} }
void CConfigManager::addPluginConfigVar(HANDLE handle, const std::string& name, const Hyprlang::CConfigValue& value) { void CConfigManager::addPluginConfigVar(HANDLE handle, const std::string& name, const Hyprlang::CConfigValue& value) {
@ -2056,17 +2035,6 @@ std::optional<std::string> CConfigManager::handleBezier(const std::string& comma
return {}; return {};
} }
void CConfigManager::setAnimForChildren(SAnimationPropertyConfig* const ANIM) {
for (auto& [name, anim] : animationConfig) {
if (anim.pParentAnimation == ANIM && !anim.overridden) {
// if a child isnt overridden, set the values of the parent
anim.pValues = ANIM->pValues;
setAnimForChildren(&anim);
}
}
};
std::optional<std::string> CConfigManager::handleAnimation(const std::string& command, const std::string& args) { std::optional<std::string> CConfigManager::handleAnimation(const std::string& command, const std::string& args) {
const auto ARGS = CVarList(args); const auto ARGS = CVarList(args);
@ -2075,14 +2043,9 @@ std::optional<std::string> CConfigManager::handleAnimation(const std::string& co
// anim name // anim name
const auto ANIMNAME = ARGS[0]; const auto ANIMNAME = ARGS[0];
const auto PANIM = animationConfig.find(ANIMNAME); if (!m_AnimationTree.nodeExists(ANIMNAME))
if (PANIM == animationConfig.end())
return "no such animation"; return "no such animation";
PANIM->second.overridden = true;
PANIM->second.pValues = &PANIM->second;
// This helper casts strings like "1", "true", "off", "yes"... to int. // This helper casts strings like "1", "true", "off", "yes"... to int.
int64_t enabledInt = configStringToInt(ARGS[1]).value_or(0) == 1; int64_t enabledInt = configStringToInt(ARGS[1]).value_or(0) == 1;
@ -2090,43 +2053,36 @@ std::optional<std::string> CConfigManager::handleAnimation(const std::string& co
if (enabledInt != 0 && enabledInt != 1) if (enabledInt != 0 && enabledInt != 1)
return "invalid animation on/off state"; return "invalid animation on/off state";
PANIM->second.internalEnabled = configStringToInt(ARGS[1]).value_or(0) == 1; int64_t speed = -1;
if (PANIM->second.internalEnabled) {
// speed // speed
if (isNumber(ARGS[2], true)) { if (isNumber(ARGS[2], true)) {
PANIM->second.internalSpeed = std::stof(ARGS[2]); speed = std::stof(ARGS[2]);
if (PANIM->second.internalSpeed <= 0) { if (speed <= 0) {
PANIM->second.internalSpeed = 1.f; speed = 1.f;
return "invalid speed"; return "invalid speed";
} }
} else { } else {
PANIM->second.internalSpeed = 10.f; speed = 10.f;
return "invalid speed"; return "invalid speed";
} }
// curve std::string bezierName = ARGS[3];
PANIM->second.internalBezier = ARGS[3]; m_AnimationTree.setConfigForNode(ANIMNAME, enabledInt, speed, ARGS[3], ARGS[4]);
if (!g_pAnimationManager->bezierExists(ARGS[3])) { if (!g_pAnimationManager->bezierExists(bezierName)) {
PANIM->second.internalBezier = "default"; const auto PANIMNODE = m_AnimationTree.getConfig(ANIMNAME);
PANIMNODE->internalBezier = "default";
return "no such bezier"; return "no such bezier";
} }
// style
PANIM->second.internalStyle = ARGS[4];
if (ARGS[4] != "") { if (ARGS[4] != "") {
auto ERR = g_pAnimationManager->styleValidInConfigVar(ANIMNAME, ARGS[4]); auto ERR = g_pAnimationManager->styleValidInConfigVar(ANIMNAME, ARGS[4]);
if (ERR != "") if (ERR != "")
return ERR; return ERR;
} }
}
// now, check for children, recursively
setAnimForChildren(&PANIM->second);
return {}; return {};
} }
@ -2785,7 +2741,7 @@ bool CConfigManager::shouldUseSoftwareCursors() {
switch (*PNOHW) { switch (*PNOHW) {
case 0: return false; case 0: return false;
case 1: return true; case 1: return true;
default: return g_pHyprRenderer->isNvidia(); default: break;
} }
return true; return true;

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <hyprutils/animation/AnimationConfig.hpp>
#define CONFIG_MANAGER_H #define CONFIG_MANAGER_H
#include <map> #include <map>
@ -23,9 +24,6 @@
#include <hyprlang.hpp> #include <hyprlang.hpp>
#define INITANIMCFG(name) animationConfig[name] = {}
#define CREATEANIMCFG(name, parent) animationConfig[name] = {false, "", "", 0.f, -1, &animationConfig["global"], &animationConfig[parent]}
#define HANDLE void* #define HANDLE void*
struct SWorkspaceRule { struct SWorkspaceRule {
@ -54,18 +52,6 @@ struct SMonitorAdditionalReservedArea {
int right = 0; int right = 0;
}; };
struct SAnimationPropertyConfig {
bool overridden = true;
std::string internalBezier = "";
std::string internalStyle = "";
float internalSpeed = 0.f;
int internalEnabled = -1;
SAnimationPropertyConfig* pValues = nullptr;
SAnimationPropertyConfig* pParentAnimation = nullptr;
};
struct SPluginKeyword { struct SPluginKeyword {
HANDLE handle = nullptr; HANDLE handle = nullptr;
std::string name = ""; std::string name = "";
@ -181,7 +167,7 @@ class CConfigManager {
std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas; std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas;
std::unordered_map<std::string, SAnimationPropertyConfig> getAnimationConfig(); const std::unordered_map<std::string, SP<Hyprutils::Animation::SAnimationPropertyConfig>>& getAnimationConfig();
void addPluginConfigVar(HANDLE handle, const std::string& name, const Hyprlang::CConfigValue& value); void addPluginConfigVar(HANDLE handle, const std::string& name, const Hyprlang::CConfigValue& value);
void addPluginKeyword(HANDLE handle, const std::string& name, Hyprlang::PCONFIGHANDLERFUNC fun, Hyprlang::SHandlerOptions opts = {}); void addPluginKeyword(HANDLE handle, const std::string& name, Hyprlang::PCONFIGHANDLERFUNC fun, Hyprlang::SHandlerOptions opts = {});
@ -201,7 +187,7 @@ class CConfigManager {
void addParseError(const std::string&); void addParseError(const std::string&);
SAnimationPropertyConfig* getAnimationPropertyConfig(const std::string&); SP<Hyprutils::Animation::SAnimationPropertyConfig> getAnimationPropertyConfig(const std::string&);
void addExecRule(const SExecRequestedRule&); void addExecRule(const SExecRequestedRule&);
@ -259,6 +245,7 @@ class CConfigManager {
}; };
std::unordered_map<std::string, std::function<CWindowOverridableVar<float>*(PHLWINDOW)>> mfWindowProperties = { std::unordered_map<std::string, std::function<CWindowOverridableVar<float>*(PHLWINDOW)>> mfWindowProperties = {
{"roundingpower", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.roundingPower; }},
{"scrollmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollMouse; }}, {"scrollmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollMouse; }},
{"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollTouchpad; }}}; {"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollTouchpad; }}};
@ -273,7 +260,7 @@ class CConfigManager {
std::vector<std::string> configPaths; // stores all the config paths std::vector<std::string> configPaths; // stores all the config paths
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
std::unordered_map<std::string, SAnimationPropertyConfig> animationConfig; // stores all the animations with their set values Hyprutils::Animation::CAnimationConfigTree m_AnimationTree;
std::string m_szCurrentSubmap = ""; // For storing the current keybind submap std::string m_szCurrentSubmap = ""; // For storing the current keybind submap
@ -300,7 +287,6 @@ class CConfigManager {
std::string m_szConfigErrors = ""; std::string m_szConfigErrors = "";
// internal methods // internal methods
void setAnimForChildren(SAnimationPropertyConfig* const);
void updateBlurredLS(const std::string&, const bool); void updateBlurredLS(const std::string&, const bool);
void setDefaultAnimationVars(); void setDefaultAnimationVars();
std::optional<std::string> resetHLConfig(); std::optional<std::string> resetHLConfig();

View file

@ -94,6 +94,7 @@ general {
# https://wiki.hyprland.org/Configuring/Variables/#decoration # https://wiki.hyprland.org/Configuring/Variables/#decoration
decoration { decoration {
rounding = 10 rounding = 10
rounding_power = 2
# Change transparency of focused and unfocused windows # Change transparency of focused and unfocused windows
active_opacity = 1.0 active_opacity = 1.0

View file

@ -248,8 +248,8 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) {
"focusHistoryID": {}, "focusHistoryID": {},
"inhibitingIdle": {} "inhibitingIdle": {}
}},)#", }},)#",
(uintptr_t)w.get(), (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y, (uintptr_t)w.get(), (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition->goal().x, (int)w->m_vRealPosition->goal().y,
(int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, (int)w->m_vRealSize->goal().x, (int)w->m_vRealSize->goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID,
escapeJSONStrings(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), ((int)w->m_bIsFloating == 1 ? "true" : "false"), (w->m_bIsPseudotiled ? "true" : "false"), escapeJSONStrings(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), ((int)w->m_bIsFloating == 1 ? "true" : "false"), (w->m_bIsPseudotiled ? "true" : "false"),
(int64_t)w->monitorID(), escapeJSONStrings(w->m_szClass), escapeJSONStrings(w->m_szTitle), escapeJSONStrings(w->m_szInitialClass), (int64_t)w->monitorID(), escapeJSONStrings(w->m_szClass), escapeJSONStrings(w->m_szTitle), escapeJSONStrings(w->m_szInitialClass),
escapeJSONStrings(w->m_szInitialTitle), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"), escapeJSONStrings(w->m_szInitialTitle), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"),
@ -261,11 +261,12 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) {
"{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: " "{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: "
"{}\n\txwayland: {}\n\tpinned: " "{}\n\txwayland: {}\n\tpinned: "
"{}\n\tfullscreen: {}\n\tfullscreenClient: {}\n\tgrouped: {}\n\ttags: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\tinhibitingIdle: {}\n\n", "{}\n\tfullscreen: {}\n\tfullscreenClient: {}\n\tgrouped: {}\n\ttags: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\tinhibitingIdle: {}\n\n",
(uintptr_t)w.get(), w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y, (uintptr_t)w.get(), w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition->goal().x, (int)w->m_vRealPosition->goal().y,
(int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, (!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), (int)w->m_vRealSize->goal().x, (int)w->m_vRealSize->goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID,
(int)w->m_bIsFloating, (int)w->m_bIsPseudotiled, (int64_t)w->monitorID(), w->m_szClass, w->m_szTitle, w->m_szInitialClass, w->m_szInitialTitle, w->getPID(), (!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), (int)w->m_bIsFloating, (int)w->m_bIsPseudotiled, (int64_t)w->monitorID(), w->m_szClass, w->m_szTitle,
(int)w->m_bIsX11, (int)w->m_bPinned, (uint8_t)w->m_sFullscreenState.internal, (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format), w->m_szInitialClass, w->m_szInitialTitle, w->getPID(), (int)w->m_bIsX11, (int)w->m_bPinned, (uint8_t)w->m_sFullscreenState.internal,
(uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w), (int)g_pInputManager->isWindowInhibiting(w, false)); (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w),
(int)g_pInputManager->isWindowInhibiting(w, false));
} }
} }
@ -732,8 +733,8 @@ static std::string animationsRequest(eHyprCtlOutputFormat format, std::string re
ret += "animations:\n"; ret += "animations:\n";
for (auto const& ac : g_pConfigManager->getAnimationConfig()) { for (auto const& ac : g_pConfigManager->getAnimationConfig()) {
ret += std::format("\n\tname: {}\n\t\toverriden: {}\n\t\tbezier: {}\n\t\tenabled: {}\n\t\tspeed: {:.2f}\n\t\tstyle: {}\n", ac.first, (int)ac.second.overridden, ret += std::format("\n\tname: {}\n\t\toverriden: {}\n\t\tbezier: {}\n\t\tenabled: {}\n\t\tspeed: {:.2f}\n\t\tstyle: {}\n", ac.first, (int)ac.second->overridden,
ac.second.internalBezier, ac.second.internalEnabled, ac.second.internalSpeed, ac.second.internalStyle); ac.second->internalBezier, ac.second->internalEnabled, ac.second->internalSpeed, ac.second->internalStyle);
} }
ret += "beziers:\n"; ret += "beziers:\n";
@ -755,8 +756,8 @@ static std::string animationsRequest(eHyprCtlOutputFormat format, std::string re
"speed": {:.2f}, "speed": {:.2f},
"style": "{}" "style": "{}"
}},)#", }},)#",
ac.first, ac.second.overridden ? "true" : "false", escapeJSONStrings(ac.second.internalBezier), ac.second.internalEnabled ? "true" : "false", ac.first, ac.second->overridden ? "true" : "false", escapeJSONStrings(ac.second->internalBezier), ac.second->internalEnabled ? "true" : "false",
ac.second.internalSpeed, escapeJSONStrings(ac.second.internalStyle)); ac.second->internalSpeed, escapeJSONStrings(ac.second->internalStyle));
} }
ret[ret.length() - 1] = ']'; ret[ret.length() - 1] = ']';
@ -1150,34 +1151,26 @@ static std::string cursorPosRequest(eHyprCtlOutputFormat format, std::string req
} }
static std::string dispatchBatch(eHyprCtlOutputFormat format, std::string request) { static std::string dispatchBatch(eHyprCtlOutputFormat format, std::string request) {
// split by ; // split by ; ignores ; inside [] and adds ; on last command
request = request.substr(9); request = request.substr(9);
std::string curitem = "";
std::string reply = ""; std::string reply = "";
auto nextItem = [&]() {
auto idx = request.find_first_of(';');
if (idx != std::string::npos) {
curitem = request.substr(0, idx);
request = request.substr(idx + 1);
} else {
curitem = request;
request = "";
}
curitem = trim(curitem);
};
nextItem();
const std::string DELIMITER = "\n\n\n"; const std::string DELIMITER = "\n\n\n";
int bracket = 0;
size_t idx = 0;
while (curitem != "" || request != "") { for (size_t i = 0; i <= request.size(); ++i) {
reply += g_pHyprCtl->getReply(curitem) + DELIMITER; char ch = (i < request.size()) ? request[i] : ';';
if (ch == '[')
nextItem(); ++bracket;
else if (ch == ']')
--bracket;
else if (ch == ';' && bracket == 0) {
if (idx < i)
reply += g_pHyprCtl->getReply(trim(request.substr(idx, i - idx))).append(DELIMITER);
idx = i + 1;
continue;
}
} }
return reply.substr(0, std::max(static_cast<int>(reply.size() - DELIMITER.size()), 0)); return reply.substr(0, std::max(static_cast<int>(reply.size() - DELIMITER.size()), 0));

View file

@ -4,6 +4,7 @@
#include "../protocols/LayerShell.hpp" #include "../protocols/LayerShell.hpp"
#include "../protocols/core/Compositor.hpp" #include "../protocols/core/Compositor.hpp"
#include "../managers/SeatManager.hpp" #include "../managers/SeatManager.hpp"
#include "../managers/AnimationManager.hpp"
PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) { PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) {
PHLLS pLS = SP<CLayerSurface>(new CLayerSurface(resource)); PHLLS pLS = SP<CLayerSurface>(new CLayerSurface(resource));
@ -31,16 +32,13 @@ PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) {
pLS->forceBlur = g_pConfigManager->shouldBlurLS(pLS->szNamespace); pLS->forceBlur = g_pConfigManager->shouldBlurLS(pLS->szNamespace);
pLS->alpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeLayersIn"), pLS, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(0.f, pLS->alpha, g_pConfigManager->getAnimationPropertyConfig("fadeLayersIn"), pLS, AVARDAMAGE_ENTIRE);
pLS->realPosition.create(g_pConfigManager->getAnimationPropertyConfig("layersIn"), pLS, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(Vector2D(0, 0), pLS->realPosition, g_pConfigManager->getAnimationPropertyConfig("layersIn"), pLS, AVARDAMAGE_ENTIRE);
pLS->realSize.create(g_pConfigManager->getAnimationPropertyConfig("layersIn"), pLS, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(Vector2D(0, 0), pLS->realSize, g_pConfigManager->getAnimationPropertyConfig("layersIn"), pLS, AVARDAMAGE_ENTIRE);
pLS->alpha.registerVar();
pLS->realPosition.registerVar();
pLS->realSize.registerVar();
pLS->registerCallbacks(); pLS->registerCallbacks();
pLS->alpha.setValueAndWarp(0.f); pLS->alpha->setValueAndWarp(0.f);
Debug::log(LOG, "LayerSurface {:x} (namespace {} layer {}) created on monitor {}", (uintptr_t)resource.get(), resource->layerNamespace, (int)pLS->layer, pMonitor->szName); Debug::log(LOG, "LayerSurface {:x} (namespace {} layer {}) created on monitor {}", (uintptr_t)resource.get(), resource->layerNamespace, (int)pLS->layer, pMonitor->szName);
@ -48,7 +46,7 @@ PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) {
} }
void CLayerSurface::registerCallbacks() { void CLayerSurface::registerCallbacks() {
alpha.setUpdateCallback([this](void*) { alpha->setUpdateCallback([this](auto) {
if (dimAround) if (dimAround)
g_pHyprRenderer->damageMonitor(monitor.lock()); g_pHyprRenderer->damageMonitor(monitor.lock());
}); });
@ -93,7 +91,7 @@ void CLayerSurface::onDestroy() {
onUnmap(); onUnmap();
} else { } else {
Debug::log(LOG, "Removing LayerSurface that wasn't mapped."); Debug::log(LOG, "Removing LayerSurface that wasn't mapped.");
alpha.setValueAndWarp(0.f); alpha->setValueAndWarp(0.f);
fadingOut = true; fadingOut = true;
g_pCompositor->addToFadingOutSafe(self.lock()); g_pCompositor->addToFadingOutSafe(self.lock());
} }
@ -307,17 +305,17 @@ void CLayerSurface::onCommit() {
} }
} }
if (realPosition.goal() != geometry.pos()) { if (realPosition->goal() != geometry.pos()) {
if (realPosition.isBeingAnimated()) if (realPosition->isBeingAnimated())
realPosition = geometry.pos(); *realPosition = geometry.pos();
else else
realPosition.setValueAndWarp(geometry.pos()); realPosition->setValueAndWarp(geometry.pos());
} }
if (realSize.goal() != geometry.size()) { if (realSize->goal() != geometry.size()) {
if (realSize.isBeingAnimated()) if (realSize->isBeingAnimated())
realSize = geometry.size(); *realSize = geometry.size();
else else
realSize.setValueAndWarp(geometry.size()); realSize->setValueAndWarp(geometry.size());
} }
if (mapped && (layerSurface->current.committed & CLayerShellResource::eCommittedState::STATE_INTERACTIVITY)) { if (mapped && (layerSurface->current.committed & CLayerShellResource::eCommittedState::STATE_INTERACTIVITY)) {
@ -434,17 +432,17 @@ void CLayerSurface::applyRules() {
} }
void CLayerSurface::startAnimation(bool in, bool instant) { void CLayerSurface::startAnimation(bool in, bool instant) {
const auto ANIMSTYLE = animationStyle.value_or(realPosition.m_pConfig->pValues->internalStyle);
if (in) { if (in) {
realPosition.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("layersIn"); realPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersIn"));
realSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("layersIn"); realSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersIn"));
alpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeLayersIn"); alpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeLayersIn"));
} else { } else {
realPosition.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("layersOut"); realPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersOut"));
realSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("layersOut"); realSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersOut"));
alpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeLayersOut"); alpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeLayersOut"));
} }
const auto ANIMSTYLE = animationStyle.value_or(realPosition->getStyle());
if (ANIMSTYLE.starts_with("slide")) { if (ANIMSTYLE.starts_with("slide")) {
// get closest edge // get closest edge
const auto MIDDLE = geometry.middle(); const auto MIDDLE = geometry.middle();
@ -485,9 +483,9 @@ void CLayerSurface::startAnimation(bool in, bool instant) {
} }
} }
realSize.setValueAndWarp(geometry.size()); realSize->setValueAndWarp(geometry.size());
alpha.setValueAndWarp(in ? 0.f : 1.f); alpha->setValueAndWarp(in ? 0.f : 1.f);
alpha = in ? 1.f : 0.f; *alpha = in ? 1.f : 0.f;
Vector2D prePos; Vector2D prePos;
@ -512,11 +510,11 @@ void CLayerSurface::startAnimation(bool in, bool instant) {
} }
if (in) { if (in) {
realPosition.setValueAndWarp(prePos); realPosition->setValueAndWarp(prePos);
realPosition = geometry.pos(); *realPosition = geometry.pos();
} else { } else {
realPosition.setValueAndWarp(geometry.pos()); realPosition->setValueAndWarp(geometry.pos());
realPosition = prePos; *realPosition = prePos;
} }
} else if (ANIMSTYLE.starts_with("popin")) { } else if (ANIMSTYLE.starts_with("popin")) {
@ -535,25 +533,25 @@ void CLayerSurface::startAnimation(bool in, bool instant) {
const auto GOALSIZE = (geometry.size() * minPerc).clamp({5, 5}); const auto GOALSIZE = (geometry.size() * minPerc).clamp({5, 5});
const auto GOALPOS = geometry.pos() + (geometry.size() - GOALSIZE) / 2.f; const auto GOALPOS = geometry.pos() + (geometry.size() - GOALSIZE) / 2.f;
alpha.setValueAndWarp(in ? 0.f : 1.f); alpha->setValueAndWarp(in ? 0.f : 1.f);
alpha = in ? 1.f : 0.f; *alpha = in ? 1.f : 0.f;
if (in) { if (in) {
realSize.setValueAndWarp(GOALSIZE); realSize->setValueAndWarp(GOALSIZE);
realPosition.setValueAndWarp(GOALPOS); realPosition->setValueAndWarp(GOALPOS);
realSize = geometry.size(); *realSize = geometry.size();
realPosition = geometry.pos(); *realPosition = geometry.pos();
} else { } else {
realSize.setValueAndWarp(geometry.size()); realSize->setValueAndWarp(geometry.size());
realPosition.setValueAndWarp(geometry.pos()); realPosition->setValueAndWarp(geometry.pos());
realSize = GOALSIZE; *realSize = GOALSIZE;
realPosition = GOALPOS; *realPosition = GOALPOS;
} }
} else { } else {
// fade // fade
realPosition.setValueAndWarp(geometry.pos()); realPosition->setValueAndWarp(geometry.pos());
realSize.setValueAndWarp(geometry.size()); realSize->setValueAndWarp(geometry.size());
alpha = in ? 1.f : 0.f; *alpha = in ? 1.f : 0.f;
} }
if (!in) if (!in)
@ -564,7 +562,7 @@ bool CLayerSurface::isFadedOut() {
if (!fadingOut) if (!fadingOut)
return false; return false;
return !realPosition.isBeingAnimated() && !realSize.isBeingAnimated() && !alpha.isBeingAnimated(); return !realPosition->isBeingAnimated() && !realSize->isBeingAnimated() && !alpha->isBeingAnimated();
} }
int CLayerSurface::popupsCount() { int CLayerSurface::popupsCount() {

View file

@ -23,9 +23,9 @@ class CLayerSurface {
bool isFadedOut(); bool isFadedOut();
int popupsCount(); int popupsCount();
CAnimatedVariable<Vector2D> realPosition; PHLANIMVAR<Vector2D> realPosition;
CAnimatedVariable<Vector2D> realSize; PHLANIMVAR<Vector2D> realSize;
CAnimatedVariable<float> alpha; PHLANIMVAR<float> alpha;
WP<CLayerShellResource> layerSurface; WP<CLayerShellResource> layerSurface;
wl_list link; wl_list link;

View file

@ -243,9 +243,9 @@ Vector2D CPopup::localToGlobal(const Vector2D& rel) {
Vector2D CPopup::t1ParentCoords() { Vector2D CPopup::t1ParentCoords() {
if (!m_pWindowOwner.expired()) if (!m_pWindowOwner.expired())
return m_pWindowOwner->m_vRealPosition.value(); return m_pWindowOwner->m_vRealPosition->value();
if (!m_pLayerOwner.expired()) if (!m_pLayerOwner.expired())
return m_pLayerOwner->realPosition.value(); return m_pLayerOwner->realPosition->value();
ASSERT(false); ASSERT(false);
return {}; return {};

View file

@ -169,7 +169,7 @@ Vector2D CSubsurface::coordsGlobal() {
Vector2D coords = coordsRelativeToParent(); Vector2D coords = coordsRelativeToParent();
if (!m_pWindowParent.expired()) if (!m_pWindowParent.expired())
coords += m_pWindowParent->m_vRealPosition.value(); coords += m_pWindowParent->m_vRealPosition->value();
else if (m_pPopupParent) else if (m_pPopupParent)
coords += m_pPopupParent->coordsGlobal(); coords += m_pPopupParent->coordsGlobal();

View file

@ -72,7 +72,7 @@ Vector2D CWLSurface::correctSmallVec() const {
const auto SIZE = getViewporterCorrectedSize(); const auto SIZE = getViewporterCorrectedSize();
const auto O = m_pWindowOwner.lock(); const auto O = m_pWindowOwner.lock();
return Vector2D{(O->m_vReportedSize.x - SIZE.x) / 2, (O->m_vReportedSize.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) * (O->m_vRealSize.value() / O->m_vReportedSize); return Vector2D{(O->m_vReportedSize.x - SIZE.x) / 2, (O->m_vReportedSize.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) * (O->m_vRealSize->value() / O->m_vReportedSize);
} }
Vector2D CWLSurface::correctSmallVecBuf() const { Vector2D CWLSurface::correctSmallVecBuf() const {

View file

@ -119,4 +119,5 @@ class CWLSurface {
} listeners; } listeners;
friend class CPointerConstraint; friend class CPointerConstraint;
friend class CXxColorManagerV4;
}; };

View file

@ -1,3 +1,4 @@
#include <hyprutils/animation/AnimatedVariable.hpp>
#include <re2/re2.h> #include <re2/re2.h>
#include <any> #include <any>
@ -11,12 +12,16 @@
#include "../render/decorations/CHyprBorderDecoration.hpp" #include "../render/decorations/CHyprBorderDecoration.hpp"
#include "../config/ConfigValue.hpp" #include "../config/ConfigValue.hpp"
#include "../managers/TokenManager.hpp" #include "../managers/TokenManager.hpp"
#include "../managers/AnimationManager.hpp"
#include "../protocols/XDGShell.hpp" #include "../protocols/XDGShell.hpp"
#include "../protocols/core/Compositor.hpp" #include "../protocols/core/Compositor.hpp"
#include "../xwayland/XWayland.hpp" #include "../xwayland/XWayland.hpp"
#include "../helpers/Color.hpp"
#include <hyprutils/string/String.hpp> #include <hyprutils/string/String.hpp>
using namespace Hyprutils::String; using namespace Hyprutils::String;
using namespace Hyprutils::Animation;
PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) { PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
PHLWINDOW pWindow = SP<CWindow>(new CWindow(surface)); PHLWINDOW pWindow = SP<CWindow>(new CWindow(surface));
@ -24,16 +29,16 @@ PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
pWindow->m_pSelf = pWindow; pWindow->m_pSelf = pWindow;
pWindow->m_bIsX11 = true; pWindow->m_bIsX11 = true;
pWindow->m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_vRealPosition, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->m_vRealSize.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_vRealSize, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->m_fBorderFadeAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_BORDER); g_pAnimationManager->createAnimation(0.f, pWindow->m_fBorderFadeAnimationProgress, g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_BORDER);
pWindow->m_fBorderAngleAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("borderangle"), pWindow, AVARDAMAGE_BORDER); g_pAnimationManager->createAnimation(0.f, pWindow->m_fBorderAngleAnimationProgress, g_pConfigManager->getAnimationPropertyConfig("borderangle"), pWindow, AVARDAMAGE_BORDER);
pWindow->m_fAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(1.f, pWindow->m_fAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(1.f, pWindow->m_fActiveInactiveAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW); g_pAnimationManager->createAnimation(CHyprColor(), pWindow->m_cRealShadowColor, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW);
pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(0.f, pWindow->m_fDimPercent, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->m_fMovingToWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingToWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->m_fMovingFromWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingFromWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow)); pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow));
pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(pWindow)); pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(pWindow));
@ -47,16 +52,16 @@ PHLWINDOW CWindow::create(SP<CXDGSurfaceResource> resource) {
pWindow->m_pSelf = pWindow; pWindow->m_pSelf = pWindow;
resource->toplevel->window = pWindow; resource->toplevel->window = pWindow;
pWindow->m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_vRealPosition, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->m_vRealSize.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_vRealSize, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->m_fBorderFadeAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_BORDER); g_pAnimationManager->createAnimation(0.f, pWindow->m_fBorderFadeAnimationProgress, g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_BORDER);
pWindow->m_fBorderAngleAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("borderangle"), pWindow, AVARDAMAGE_BORDER); g_pAnimationManager->createAnimation(0.f, pWindow->m_fBorderAngleAnimationProgress, g_pConfigManager->getAnimationPropertyConfig("borderangle"), pWindow, AVARDAMAGE_BORDER);
pWindow->m_fAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(1.f, pWindow->m_fAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(1.f, pWindow->m_fActiveInactiveAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW); g_pAnimationManager->createAnimation(CHyprColor(), pWindow->m_cRealShadowColor, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW);
pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(0.f, pWindow->m_fDimPercent, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->m_fMovingToWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingToWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->m_fMovingFromWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingFromWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow)); pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow));
pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(pWindow)); pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(pWindow));
@ -118,8 +123,8 @@ SBoxExtents CWindow::getFullWindowExtents() {
if (m_sWindowData.dimAround.valueOrDefault()) { if (m_sWindowData.dimAround.valueOrDefault()) {
if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR)
return {{m_vRealPosition.value().x - PMONITOR->vecPosition.x, m_vRealPosition.value().y - PMONITOR->vecPosition.y}, return {{m_vRealPosition->value().x - PMONITOR->vecPosition.x, m_vRealPosition->value().y - PMONITOR->vecPosition.y},
{PMONITOR->vecSize.x - (m_vRealPosition.value().x - PMONITOR->vecPosition.x), PMONITOR->vecSize.y - (m_vRealPosition.value().y - PMONITOR->vecPosition.y)}}; {PMONITOR->vecSize.x - (m_vRealPosition->value().x - PMONITOR->vecPosition.x), PMONITOR->vecSize.y - (m_vRealPosition->value().y - PMONITOR->vecPosition.y)}};
} }
SBoxExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}}; SBoxExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}};
@ -183,8 +188,8 @@ CBox CWindow::getFullWindowBoundingBox() {
auto maxExtents = getFullWindowExtents(); auto maxExtents = getFullWindowExtents();
CBox finalBox = {m_vRealPosition.value().x - maxExtents.topLeft.x, m_vRealPosition.value().y - maxExtents.topLeft.y, CBox finalBox = {m_vRealPosition->value().x - maxExtents.topLeft.x, m_vRealPosition->value().y - maxExtents.topLeft.y,
m_vRealSize.value().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.value().y + maxExtents.topLeft.y + maxExtents.bottomRight.y}; m_vRealSize->value().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize->value().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
return finalBox; return finalBox;
} }
@ -238,7 +243,7 @@ CBox CWindow::getWindowBoxUnified(uint64_t properties) {
if (properties & FULL_EXTENTS) if (properties & FULL_EXTENTS)
EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(m_pSelf.lock(), false)); EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(m_pSelf.lock(), false));
CBox box = {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y}; CBox box = {m_vRealPosition->value().x, m_vRealPosition->value().y, m_vRealSize->value().x, m_vRealSize->value().y};
box.addExtents(EXTENTS); box.addExtents(EXTENTS);
return box; return box;
@ -408,10 +413,10 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
const auto OLDWORKSPACE = m_pWorkspace; const auto OLDWORKSPACE = m_pWorkspace;
m_fMovingToWorkspaceAlpha->setValueAndWarp(1.F);
*m_fMovingToWorkspaceAlpha = 0.F;
m_fMovingToWorkspaceAlpha->setCallbackOnEnd([this](auto) { m_iMonitorMovedFrom = -1; });
m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->monitorID() : -1; m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->monitorID() : -1;
m_fMovingToWorkspaceAlpha.setValueAndWarp(1.F);
m_fMovingToWorkspaceAlpha = 0.F;
m_fMovingToWorkspaceAlpha.setCallbackOnEnd([this](void* thisptr) { m_iMonitorMovedFrom = -1; });
m_pWorkspace = pWorkspace; m_pWorkspace = pWorkspace;
@ -439,7 +444,7 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
} }
// update xwayland coords // update xwayland coords
g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.value()); g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize->value());
if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && OLDWORKSPACE->getWindows() == 0 && *PCLOSEONLASTSPECIAL) { if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && OLDWORKSPACE->getWindows() == 0 && *PCLOSEONLASTSPECIAL) {
if (const auto PMONITOR = OLDWORKSPACE->m_pMonitor.lock(); PMONITOR) if (const auto PMONITOR = OLDWORKSPACE->m_pMonitor.lock(); PMONITOR)
@ -475,10 +480,6 @@ PHLWINDOW CWindow::x11TransientFor() {
return nullptr; return nullptr;
} }
static void unregisterVar(void* ptr) {
((CBaseAnimatedVariable*)ptr)->unregister();
}
void CWindow::onUnmap() { void CWindow::onUnmap() {
static auto PCLOSEONLASTSPECIAL = CConfigValue<Hyprlang::INT>("misc:close_special_on_empty"); static auto PCLOSEONLASTSPECIAL = CConfigValue<Hyprlang::INT>("misc:close_special_on_empty");
static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking"); static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking");
@ -497,19 +498,6 @@ void CWindow::onUnmap() {
m_iLastWorkspace = m_pWorkspace->m_iID; m_iLastWorkspace = m_pWorkspace->m_iID;
m_vRealPosition.setCallbackOnEnd(unregisterVar);
m_vRealSize.setCallbackOnEnd(unregisterVar);
m_fBorderFadeAnimationProgress.setCallbackOnEnd(unregisterVar);
m_fBorderAngleAnimationProgress.setCallbackOnEnd(unregisterVar);
m_fActiveInactiveAlpha.setCallbackOnEnd(unregisterVar);
m_fAlpha.setCallbackOnEnd(unregisterVar);
m_cRealShadowColor.setCallbackOnEnd(unregisterVar);
m_fDimPercent.setCallbackOnEnd(unregisterVar);
m_fMovingToWorkspaceAlpha.setCallbackOnEnd(unregisterVar);
m_fMovingFromWorkspaceAlpha.setCallbackOnEnd(unregisterVar);
m_vRealSize.setCallbackOnBegin(nullptr);
std::erase_if(g_pCompositor->m_vWindowFocusHistory, [&](const auto& other) { return other.expired() || other.lock().get() == this; }); std::erase_if(g_pCompositor->m_vWindowFocusHistory, [&](const auto& other) { return other.expired() || other.lock().get() == this; });
if (*PCLOSEONLASTSPECIAL && m_pWorkspace && m_pWorkspace->getWindows() == 0 && onSpecialWorkspace()) { if (*PCLOSEONLASTSPECIAL && m_pWorkspace && m_pWorkspace->getWindows() == 0 && onSpecialWorkspace()) {
@ -541,34 +529,24 @@ void CWindow::onUnmap() {
void CWindow::onMap() { void CWindow::onMap() {
// JIC, reset the callbacks. If any are set, we'll make sure they are cleared so we don't accidentally unset them. (In case a window got remapped) // JIC, reset the callbacks. If any are set, we'll make sure they are cleared so we don't accidentally unset them. (In case a window got remapped)
m_vRealPosition.resetAllCallbacks(); m_vRealPosition->resetAllCallbacks();
m_vRealSize.resetAllCallbacks(); m_vRealSize->resetAllCallbacks();
m_fBorderFadeAnimationProgress.resetAllCallbacks(); m_fBorderFadeAnimationProgress->resetAllCallbacks();
m_fBorderAngleAnimationProgress.resetAllCallbacks(); m_fBorderAngleAnimationProgress->resetAllCallbacks();
m_fActiveInactiveAlpha.resetAllCallbacks(); m_fActiveInactiveAlpha->resetAllCallbacks();
m_fAlpha.resetAllCallbacks(); m_fAlpha->resetAllCallbacks();
m_cRealShadowColor.resetAllCallbacks(); m_cRealShadowColor->resetAllCallbacks();
m_fDimPercent.resetAllCallbacks(); m_fDimPercent->resetAllCallbacks();
m_fMovingToWorkspaceAlpha.resetAllCallbacks(); m_fMovingToWorkspaceAlpha->resetAllCallbacks();
m_fMovingFromWorkspaceAlpha.resetAllCallbacks(); m_fMovingFromWorkspaceAlpha->resetAllCallbacks();
m_vRealPosition.registerVar(); m_fMovingFromWorkspaceAlpha->setValueAndWarp(1.F);
m_vRealSize.registerVar();
m_fBorderFadeAnimationProgress.registerVar();
m_fBorderAngleAnimationProgress.registerVar();
m_fActiveInactiveAlpha.registerVar();
m_fAlpha.registerVar();
m_cRealShadowColor.registerVar();
m_fDimPercent.registerVar();
m_fMovingToWorkspaceAlpha.registerVar();
m_fMovingFromWorkspaceAlpha.registerVar();
m_fBorderAngleAnimationProgress.setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false); m_fBorderAngleAnimationProgress->setValueAndWarp(0.f);
m_fBorderAngleAnimationProgress->setCallbackOnEnd([&](WP<CBaseAnimatedVariable> p) { onBorderAngleAnimEnd(p); }, false);
*m_fBorderAngleAnimationProgress = 1.f;
m_fBorderAngleAnimationProgress.setValueAndWarp(0.f); m_fMovingFromWorkspaceAlpha->setValueAndWarp(1.F);
m_fBorderAngleAnimationProgress = 1.f;
m_fMovingFromWorkspaceAlpha.setValueAndWarp(1.F);
g_pCompositor->m_vWindowFocusHistory.push_back(m_pSelf); g_pCompositor->m_vWindowFocusHistory.push_back(m_pSelf);
@ -584,20 +562,22 @@ void CWindow::onMap() {
m_pPopupHead = std::make_unique<CPopup>(m_pSelf.lock()); m_pPopupHead = std::make_unique<CPopup>(m_pSelf.lock());
} }
void CWindow::onBorderAngleAnimEnd(void* ptr) { void CWindow::onBorderAngleAnimEnd(WP<CBaseAnimatedVariable> pav) {
const auto PANIMVAR = (CAnimatedVariable<float>*)ptr; const auto PAV = pav.lock();
if (!PAV)
const std::string STYLE = PANIMVAR->getConfig()->pValues->internalStyle;
if (STYLE != "loop" || !PANIMVAR->getConfig()->pValues->internalEnabled)
return; return;
if (PAV->getStyle() != "loop" || !PAV->enabled())
return;
const auto PANIMVAR = dynamic_cast<CAnimatedVariable<float>*>(PAV.get());
PANIMVAR->setCallbackOnEnd(nullptr); // we remove the callback here because otherwise setvalueandwarp will recurse this PANIMVAR->setCallbackOnEnd(nullptr); // we remove the callback here because otherwise setvalueandwarp will recurse this
PANIMVAR->setValueAndWarp(0); PANIMVAR->setValueAndWarp(0);
*PANIMVAR = 1.f; *PANIMVAR = 1.f;
PANIMVAR->setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false); PANIMVAR->setCallbackOnEnd([&](WP<CBaseAnimatedVariable> pav) { onBorderAngleAnimEnd(pav); }, false);
} }
void CWindow::setHidden(bool hidden) { void CWindow::setHidden(bool hidden) {
@ -825,26 +805,27 @@ void CWindow::updateDynamicRules() {
// otherwise behaviour is undefined // otherwise behaviour is undefined
bool CWindow::isInCurvedCorner(double x, double y) { bool CWindow::isInCurvedCorner(double x, double y) {
const int ROUNDING = rounding(); const int ROUNDING = rounding();
const int ROUNDINGPOWER = roundingPower();
if (getRealBorderSize() >= ROUNDING) if (getRealBorderSize() >= ROUNDING)
return false; return false;
// (x0, y0), (x0, y1), ... are the center point of rounding at each corner // (x0, y0), (x0, y1), ... are the center point of rounding at each corner
double x0 = m_vRealPosition.value().x + ROUNDING; double x0 = m_vRealPosition->value().x + ROUNDING;
double y0 = m_vRealPosition.value().y + ROUNDING; double y0 = m_vRealPosition->value().y + ROUNDING;
double x1 = m_vRealPosition.value().x + m_vRealSize.value().x - ROUNDING; double x1 = m_vRealPosition->value().x + m_vRealSize->value().x - ROUNDING;
double y1 = m_vRealPosition.value().y + m_vRealSize.value().y - ROUNDING; double y1 = m_vRealPosition->value().y + m_vRealSize->value().y - ROUNDING;
if (x < x0 && y < y0) { if (x < x0 && y < y0) {
return Vector2D{x0, y0}.distance(Vector2D{x, y}) > (double)ROUNDING; return std::pow(x0 - x, ROUNDINGPOWER) + std::pow(y0 - y, ROUNDINGPOWER) > std::pow((double)ROUNDING, ROUNDINGPOWER);
} }
if (x > x1 && y < y0) { if (x > x1 && y < y0) {
return Vector2D{x1, y0}.distance(Vector2D{x, y}) > (double)ROUNDING; return std::pow(x - x1, ROUNDINGPOWER) + std::pow(y0 - y, ROUNDINGPOWER) > std::pow((double)ROUNDING, ROUNDINGPOWER);
} }
if (x < x0 && y > y1) { if (x < x0 && y > y1) {
return Vector2D{x0, y1}.distance(Vector2D{x, y}) > (double)ROUNDING; return std::pow(x0 - x, ROUNDINGPOWER) + std::pow(y - y1, ROUNDINGPOWER) > std::pow((double)ROUNDING, ROUNDINGPOWER);
} }
if (x > x1 && y > y1) { if (x > x1 && y > y1) {
return Vector2D{x1, y1}.distance(Vector2D{x, y}) > (double)ROUNDING; return std::pow(x - x1, ROUNDINGPOWER) + std::pow(y - y1, ROUNDINGPOWER) > std::pow((double)ROUNDING, ROUNDINGPOWER);
} }
return false; return false;
@ -1031,8 +1012,8 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) {
if (FULLSCREEN) if (FULLSCREEN)
g_pCompositor->setWindowFullscreenInternal(PCURRENT, FSMODE_NONE); g_pCompositor->setWindowFullscreenInternal(PCURRENT, FSMODE_NONE);
const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goal(); const auto PWINDOWSIZE = PCURRENT->m_vRealSize->goal();
const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goal(); const auto PWINDOWPOS = PCURRENT->m_vRealPosition->goal();
PCURRENT->setHidden(true); PCURRENT->setHidden(true);
pWindow->setHidden(false); // can remove m_pLastWindow pWindow->setHidden(false); // can remove m_pLastWindow
@ -1040,8 +1021,8 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) {
g_pLayoutManager->getCurrentLayout()->replaceWindowDataWith(PCURRENT, pWindow); g_pLayoutManager->getCurrentLayout()->replaceWindowDataWith(PCURRENT, pWindow);
if (PCURRENT->m_bIsFloating) { if (PCURRENT->m_bIsFloating) {
pWindow->m_vRealPosition.setValueAndWarp(PWINDOWPOS); pWindow->m_vRealPosition->setValueAndWarp(PWINDOWPOS);
pWindow->m_vRealSize.setValueAndWarp(PWINDOWSIZE); pWindow->m_vRealSize->setValueAndWarp(PWINDOWSIZE);
} }
g_pCompositor->updateAllWindowsAnimatedDecorationValues(); g_pCompositor->updateAllWindowsAnimatedDecorationValues();
@ -1123,22 +1104,22 @@ void CWindow::updateGroupOutputs() {
curr->m_pMonitor = m_pMonitor; curr->m_pMonitor = m_pMonitor;
curr->moveToWorkspace(WS); curr->moveToWorkspace(WS);
curr->m_vRealPosition = m_vRealPosition.goal(); *curr->m_vRealPosition = m_vRealPosition->goal();
curr->m_vRealSize = m_vRealSize.goal(); *curr->m_vRealSize = m_vRealSize->goal();
curr = curr->m_sGroupData.pNextWindow.lock(); curr = curr->m_sGroupData.pNextWindow.lock();
} }
} }
Vector2D CWindow::middle() { Vector2D CWindow::middle() {
return m_vRealPosition.goal() + m_vRealSize.goal() / 2.f; return m_vRealPosition->goal() + m_vRealSize->goal() / 2.f;
} }
bool CWindow::opaque() { bool CWindow::opaque() {
if (m_fAlpha.value() != 1.f || m_fActiveInactiveAlpha.value() != 1.f) if (m_fAlpha->value() != 1.f || m_fActiveInactiveAlpha->value() != 1.f)
return false; return false;
if (m_vRealSize.goal().floor() != m_vReportedSize) if (m_vRealSize->goal().floor() != m_vReportedSize)
return false; return false;
const auto PWORKSPACE = m_pWorkspace; const auto PWORKSPACE = m_pWorkspace;
@ -1146,7 +1127,7 @@ bool CWindow::opaque() {
if (m_pWLSurface->small() && !m_pWLSurface->m_bFillIgnoreSmall) if (m_pWLSurface->small() && !m_pWLSurface->m_bFillIgnoreSmall)
return false; return false;
if (PWORKSPACE->m_fAlpha.value() != 1.f) if (PWORKSPACE->m_fAlpha->value() != 1.f)
return false; return false;
if (m_bIsX11 && m_pXWaylandSurface && m_pXWaylandSurface->surface && m_pXWaylandSurface->surface->current.texture) if (m_bIsX11 && m_pXWaylandSurface && m_pXWaylandSurface->surface && m_pXWaylandSurface->surface->current.texture)
@ -1165,12 +1146,20 @@ bool CWindow::opaque() {
float CWindow::rounding() { float CWindow::rounding() {
static auto PROUNDING = CConfigValue<Hyprlang::INT>("decoration:rounding"); static auto PROUNDING = CConfigValue<Hyprlang::INT>("decoration:rounding");
static auto PROUNDINGPOWER = CConfigValue<Hyprlang::FLOAT>("decoration:rounding_power");
float rounding = m_sWindowData.rounding.valueOr(*PROUNDING); float roundingPower = m_sWindowData.roundingPower.valueOr(*PROUNDINGPOWER);
float rounding = m_sWindowData.rounding.valueOr(*PROUNDING) * (roundingPower / 2.0); /* Make perceived roundness consistent. */
return m_sWindowData.noRounding.valueOrDefault() ? 0 : rounding; return m_sWindowData.noRounding.valueOrDefault() ? 0 : rounding;
} }
float CWindow::roundingPower() {
static auto PROUNDINGPOWER = CConfigValue<Hyprlang::FLOAT>("decoration:rounding_power");
return m_sWindowData.roundingPower.valueOr(*PROUNDINGPOWER);
}
void CWindow::updateWindowData() { void CWindow::updateWindowData() {
const auto PWORKSPACE = m_pWorkspace; const auto PWORKSPACE = m_pWorkspace;
const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{}; const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{};
@ -1228,15 +1217,13 @@ void CWindow::setSuspended(bool suspend) {
} }
bool CWindow::visibleOnMonitor(PHLMONITOR pMonitor) { bool CWindow::visibleOnMonitor(PHLMONITOR pMonitor) {
CBox wbox = {m_vRealPosition.value(), m_vRealSize.value()}; CBox wbox = {m_vRealPosition->value(), m_vRealSize->value()};
return !wbox.intersection({pMonitor->vecPosition, pMonitor->vecSize}).empty(); return !wbox.intersection({pMonitor->vecPosition, pMonitor->vecSize}).empty();
} }
void CWindow::setAnimationsToMove() { void CWindow::setAnimationsToMove() {
auto* const PANIMCFG = g_pConfigManager->getAnimationPropertyConfig("windowsMove"); m_vRealPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsMove"));
m_vRealPosition.setConfig(PANIMCFG);
m_vRealSize.setConfig(PANIMCFG);
m_bAnimatingIn = false; m_bAnimatingIn = false;
} }
@ -1257,16 +1244,16 @@ void CWindow::onWorkspaceAnimUpdate() {
return; return;
const auto WINBB = getFullWindowBoundingBox(); const auto WINBB = getFullWindowBoundingBox();
if (PWORKSPACE->m_vRenderOffset.value().x != 0) { if (PWORKSPACE->m_vRenderOffset->value().x != 0) {
const auto PROGRESS = PWORKSPACE->m_vRenderOffset.value().x / PWSMON->vecSize.x; const auto PROGRESS = PWORKSPACE->m_vRenderOffset->value().x / PWSMON->vecSize.x;
if (WINBB.x < PWSMON->vecPosition.x) if (WINBB.x < PWSMON->vecPosition.x)
offset.x += (PWSMON->vecPosition.x - WINBB.x) * PROGRESS; offset.x += (PWSMON->vecPosition.x - WINBB.x) * PROGRESS;
if (WINBB.x + WINBB.width > PWSMON->vecPosition.x + PWSMON->vecSize.x) if (WINBB.x + WINBB.width > PWSMON->vecPosition.x + PWSMON->vecSize.x)
offset.x += (WINBB.x + WINBB.width - PWSMON->vecPosition.x - PWSMON->vecSize.x) * PROGRESS; offset.x += (WINBB.x + WINBB.width - PWSMON->vecPosition.x - PWSMON->vecSize.x) * PROGRESS;
} else if (PWORKSPACE->m_vRenderOffset.value().y != 0) { } else if (PWORKSPACE->m_vRenderOffset->value().y != 0) {
const auto PROGRESS = PWORKSPACE->m_vRenderOffset.value().y / PWSMON->vecSize.y; const auto PROGRESS = PWORKSPACE->m_vRenderOffset->value().y / PWSMON->vecSize.y;
if (WINBB.y < PWSMON->vecPosition.y) if (WINBB.y < PWSMON->vecPosition.y)
offset.y += (PWSMON->vecPosition.y - WINBB.y) * PROGRESS; offset.y += (PWSMON->vecPosition.y - WINBB.y) * PROGRESS;
@ -1297,12 +1284,12 @@ int CWindow::surfacesCount() {
} }
void CWindow::clampWindowSize(const std::optional<Vector2D> minSize, const std::optional<Vector2D> maxSize) { void CWindow::clampWindowSize(const std::optional<Vector2D> minSize, const std::optional<Vector2D> maxSize) {
const Vector2D REALSIZE = m_vRealSize.goal(); const Vector2D REALSIZE = m_vRealSize->goal();
const Vector2D NEWSIZE = REALSIZE.clamp(minSize.value_or(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), maxSize.value_or(Vector2D{INFINITY, INFINITY})); const Vector2D NEWSIZE = REALSIZE.clamp(minSize.value_or(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), maxSize.value_or(Vector2D{INFINITY, INFINITY}));
const Vector2D DELTA = REALSIZE - NEWSIZE; const Vector2D DELTA = REALSIZE - NEWSIZE;
m_vRealPosition = m_vRealPosition.goal() + DELTA / 2.0; *m_vRealPosition = m_vRealPosition->goal() + DELTA / 2.0;
m_vRealSize = NEWSIZE; *m_vRealSize = NEWSIZE;
g_pXWaylandManager->setWindowSize(m_pSelf.lock(), NEWSIZE); g_pXWaylandManager->setWindowSize(m_pSelf.lock(), NEWSIZE);
} }
@ -1516,7 +1503,7 @@ void CWindow::onX11Configure(CBox box) {
g_pHyprRenderer->damageWindow(m_pSelf.lock()); g_pHyprRenderer->damageWindow(m_pSelf.lock());
if (!m_bIsFloating || isFullscreen() || g_pInputManager->currentlyDraggedWindow == m_pSelf) { if (!m_bIsFloating || isFullscreen() || g_pInputManager->currentlyDraggedWindow == m_pSelf) {
g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal(), true); g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize->goal(), true);
g_pInputManager->refocus(); g_pInputManager->refocus();
g_pHyprRenderer->damageWindow(m_pSelf.lock()); g_pHyprRenderer->damageWindow(m_pSelf.lock());
return; return;
@ -1529,19 +1516,19 @@ void CWindow::onX11Configure(CBox box) {
const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords(box.pos()); const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords(box.pos());
m_vRealPosition.setValueAndWarp(LOGICALPOS); m_vRealPosition->setValueAndWarp(LOGICALPOS);
m_vRealSize.setValueAndWarp(box.size()); m_vRealSize->setValueAndWarp(box.size());
static auto PXWLFORCESCALEZERO = CConfigValue<Hyprlang::INT>("xwayland:force_zero_scaling"); static auto PXWLFORCESCALEZERO = CConfigValue<Hyprlang::INT>("xwayland:force_zero_scaling");
if (*PXWLFORCESCALEZERO) { if (*PXWLFORCESCALEZERO) {
if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) { if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) {
m_vRealSize.setValueAndWarp(m_vRealSize.goal() / PMONITOR->scale); m_vRealSize->setValueAndWarp(m_vRealSize->goal() / PMONITOR->scale);
m_fX11SurfaceScaledBy = PMONITOR->scale; m_fX11SurfaceScaledBy = PMONITOR->scale;
} }
} }
m_vPosition = m_vRealPosition.value(); m_vPosition = m_vRealPosition->value();
m_vSize = m_vRealSize.value(); m_vSize = m_vRealSize->value();
m_pXWaylandSurface->configure(box); m_pXWaylandSurface->configure(box);
@ -1553,7 +1540,7 @@ void CWindow::onX11Configure(CBox box) {
if (!m_pWorkspace || !m_pWorkspace->isVisible()) if (!m_pWorkspace || !m_pWorkspace->isVisible())
return; // further things are only for visible windows return; // further things are only for visible windows
m_pWorkspace = g_pCompositor->getMonitorFromVector(m_vRealPosition.value() + m_vRealSize.value() / 2.f)->activeWorkspace; m_pWorkspace = g_pCompositor->getMonitorFromVector(m_vRealPosition->value() + m_vRealSize->value() / 2.f)->activeWorkspace;
g_pCompositor->changeWindowZOrder(m_pSelf.lock(), true); g_pCompositor->changeWindowZOrder(m_pSelf.lock(), true);

View file

@ -183,6 +183,7 @@ struct SWindowData {
CWindowOverridableVar<bool> renderUnfocused = false; CWindowOverridableVar<bool> renderUnfocused = false;
CWindowOverridableVar<int> rounding; CWindowOverridableVar<int> rounding;
CWindowOverridableVar<float> roundingPower;
CWindowOverridableVar<int> borderSize; CWindowOverridableVar<int> borderSize;
CWindowOverridableVar<float> scrollMouse; CWindowOverridableVar<float> scrollMouse;
@ -232,8 +233,8 @@ class CWindow {
Vector2D m_vSize = Vector2D(0, 0); Vector2D m_vSize = Vector2D(0, 0);
// this is the real position and size used to draw the thing // this is the real position and size used to draw the thing
CAnimatedVariable<Vector2D> m_vRealPosition; PHLANIMVAR<Vector2D> m_vRealPosition;
CAnimatedVariable<Vector2D> m_vRealSize; PHLANIMVAR<Vector2D> m_vRealSize;
// for not spamming the protocols // for not spamming the protocols
Vector2D m_vReportedPosition; Vector2D m_vReportedPosition;
@ -299,11 +300,11 @@ class CWindow {
// Animated border // Animated border
CGradientValueData m_cRealBorderColor = {0}; CGradientValueData m_cRealBorderColor = {0};
CGradientValueData m_cRealBorderColorPrevious = {0}; CGradientValueData m_cRealBorderColorPrevious = {0};
CAnimatedVariable<float> m_fBorderFadeAnimationProgress; PHLANIMVAR<float> m_fBorderFadeAnimationProgress;
CAnimatedVariable<float> m_fBorderAngleAnimationProgress; PHLANIMVAR<float> m_fBorderAngleAnimationProgress;
// Fade in-out // Fade in-out
CAnimatedVariable<float> m_fAlpha; PHLANIMVAR<float> m_fAlpha;
bool m_bFadingOut = false; bool m_bFadingOut = false;
bool m_bReadyToDelete = false; bool m_bReadyToDelete = false;
Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in
@ -335,18 +336,18 @@ class CWindow {
std::vector<std::unique_ptr<IWindowTransformer>> m_vTransformers; std::vector<std::unique_ptr<IWindowTransformer>> m_vTransformers;
// for alpha // for alpha
CAnimatedVariable<float> m_fActiveInactiveAlpha; PHLANIMVAR<float> m_fActiveInactiveAlpha;
CAnimatedVariable<float> m_fMovingFromWorkspaceAlpha; PHLANIMVAR<float> m_fMovingFromWorkspaceAlpha;
// animated shadow color // animated shadow color
CAnimatedVariable<CHyprColor> m_cRealShadowColor; PHLANIMVAR<CHyprColor> m_cRealShadowColor;
// animated tint // animated tint
CAnimatedVariable<float> m_fDimPercent; PHLANIMVAR<float> m_fDimPercent;
// animate moving to an invisible workspace // animate moving to an invisible workspace
int m_iMonitorMovedFrom = -1; // -1 means not moving int m_iMonitorMovedFrom = -1; // -1 means not moving
CAnimatedVariable<float> m_fMovingToWorkspaceAlpha; PHLANIMVAR<float> m_fMovingToWorkspaceAlpha;
// swallowing // swallowing
PHLWINDOWREF m_pSwallowed; PHLWINDOWREF m_pSwallowed;
@ -414,6 +415,7 @@ class CWindow {
Vector2D middle(); Vector2D middle();
bool opaque(); bool opaque();
float rounding(); float rounding();
float roundingPower();
bool canBeTorn(); bool canBeTorn();
void setSuspended(bool suspend); void setSuspended(bool suspend);
bool visibleOnMonitor(PHLMONITOR pMonitor); bool visibleOnMonitor(PHLMONITOR pMonitor);
@ -430,7 +432,7 @@ class CWindow {
float getScrollTouchpad(); float getScrollTouchpad();
void updateWindowData(); void updateWindowData();
void updateWindowData(const struct SWorkspaceRule&); void updateWindowData(const struct SWorkspaceRule&);
void onBorderAngleAnimEnd(void* ptr); void onBorderAngleAnimEnd(WP<Hyprutils::Animation::CBaseAnimatedVariable> pav);
bool isInCurvedCorner(double x, double y); bool isInCurvedCorner(double x, double y);
bool hasPopupAt(const Vector2D& pos); bool hasPopupAt(const Vector2D& pos);
int popupsCount(); int popupsCount();
@ -465,7 +467,7 @@ class CWindow {
Vector2D requestedMaxSize(); Vector2D requestedMaxSize();
CBox getWindowMainSurfaceBox() const { CBox getWindowMainSurfaceBox() const {
return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y}; return {m_vRealPosition->value().x, m_vRealPosition->value().y, m_vRealSize->value().x, m_vRealSize->value().y};
} }
// listeners // listeners

View file

@ -9,7 +9,7 @@ static const auto RULES = std::unordered_set<std::string>{
}; };
static const auto RULES_PREFIX = std::unordered_set<std::string>{ static const auto RULES_PREFIX = std::unordered_set<std::string>{
"animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", "move", "opacity", "animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", "move", "opacity",
"plugin:", "prop", "pseudo", "rounding", "scrollmouse", "scrolltouchpad", "size", "suppressevent", "tag", "workspace", "xray", "plugin:", "prop", "pseudo", "rounding", "roundingpower", "scrollmouse", "scrolltouchpad", "size", "suppressevent", "tag", "workspace", "xray",
}; };
CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool isV2, bool isExecRule) : szValue(value), szRule(rule), v2(isV2), execRule(isExecRule) { CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool isV2, bool isExecRule) : szValue(value), szRule(rule), v2(isV2), execRule(isExecRule) {

View file

@ -1,7 +1,10 @@
#include "Workspace.hpp" #include "Workspace.hpp"
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "../config/ConfigValue.hpp" #include "../config/ConfigValue.hpp"
#include "config/ConfigManager.hpp"
#include "managers/AnimationManager.hpp"
#include <hyprutils/animation/AnimatedVariable.hpp>
#include <hyprutils/string/String.hpp> #include <hyprutils/string/String.hpp>
using namespace Hyprutils::String; using namespace Hyprutils::String;
@ -19,16 +22,10 @@ CWorkspace::CWorkspace(WORKSPACEID id, PHLMONITOR monitor, std::string name, boo
void CWorkspace::init(PHLWORKSPACE self) { void CWorkspace::init(PHLWORKSPACE self) {
m_pSelf = self; m_pSelf = self;
m_vRenderOffset.create(m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") : g_pAnimationManager->createAnimation(Vector2D(0, 0), m_vRenderOffset,
g_pConfigManager->getAnimationPropertyConfig("workspacesIn"), g_pConfigManager->getAnimationPropertyConfig(m_bIsSpecialWorkspace ? "specialWorkspaceIn" : "workspacesIn"), self, AVARDAMAGE_ENTIRE);
self, AVARDAMAGE_ENTIRE); g_pAnimationManager->createAnimation(1.f, m_fAlpha, g_pConfigManager->getAnimationPropertyConfig(m_bIsSpecialWorkspace ? "specialWorkspaceIn" : "workspacesIn"), self,
m_fAlpha.create(AVARTYPE_FLOAT,
m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") : g_pConfigManager->getAnimationPropertyConfig("workspacesIn"), self,
AVARDAMAGE_ENTIRE); AVARDAMAGE_ENTIRE);
m_fAlpha.setValueAndWarp(1.f);
m_vRenderOffset.registerVar();
m_fAlpha.registerVar();
const auto RULEFORTHIS = g_pConfigManager->getWorkspaceRuleFor(self); const auto RULEFORTHIS = g_pConfigManager->getWorkspaceRuleFor(self);
if (RULEFORTHIS.defaultName.has_value()) if (RULEFORTHIS.defaultName.has_value())
@ -63,8 +60,6 @@ SWorkspaceIDName CWorkspace::getPrevWorkspaceIDName(bool perMonitor) const {
} }
CWorkspace::~CWorkspace() { CWorkspace::~CWorkspace() {
m_vRenderOffset.unregister();
Debug::log(LOG, "Destroying workspace ID {}", m_iID); Debug::log(LOG, "Destroying workspace ID {}", m_iID);
// check if g_pHookSystem and g_pEventManager exist, they might be destroyed as in when the compositor is closing. // check if g_pHookSystem and g_pEventManager exist, they might be destroyed as in when the compositor is closing.
@ -82,15 +77,15 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
if (!instant) { if (!instant) {
const std::string ANIMNAME = std::format("{}{}", m_bIsSpecialWorkspace ? "specialWorkspace" : "workspaces", in ? "In" : "Out"); const std::string ANIMNAME = std::format("{}{}", m_bIsSpecialWorkspace ? "specialWorkspace" : "workspaces", in ? "In" : "Out");
m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME); m_fAlpha->setConfig(g_pConfigManager->getAnimationPropertyConfig(ANIMNAME));
m_vRenderOffset.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME); m_vRenderOffset->setConfig(g_pConfigManager->getAnimationPropertyConfig(ANIMNAME));
} }
const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle; const auto ANIMSTYLE = m_fAlpha->getStyle();
static auto PWORKSPACEGAP = CConfigValue<Hyprlang::INT>("general:gaps_workspaces"); static auto PWORKSPACEGAP = CConfigValue<Hyprlang::INT>("general:gaps_workspaces");
// set floating windows offset callbacks // set floating windows offset callbacks
m_vRenderOffset.setUpdateCallback([&](void*) { m_vRenderOffset->setUpdateCallback([&](auto) {
for (auto const& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (!validMapped(w) || w->workspaceID() != m_iID) if (!validMapped(w) || w->workspaceID() != m_iID)
continue; continue;
@ -110,84 +105,84 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
} catch (std::exception& e) { Debug::log(ERR, "Error in startAnim: invalid percentage"); } } catch (std::exception& e) { Debug::log(ERR, "Error in startAnim: invalid percentage"); }
} }
m_fAlpha.setValueAndWarp(1.f); m_fAlpha->setValueAndWarp(1.f);
m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); m_vRenderOffset->setValueAndWarp(Vector2D(0, 0));
if (ANIMSTYLE.starts_with("slidefadevert")) { if (ANIMSTYLE.starts_with("slidefadevert")) {
if (in) { if (in) {
m_fAlpha.setValueAndWarp(0.f); m_fAlpha->setValueAndWarp(0.f);
m_vRenderOffset.setValueAndWarp(Vector2D(0.0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f))); m_vRenderOffset->setValueAndWarp(Vector2D(0.0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f)));
m_fAlpha = 1.f; *m_fAlpha = 1.f;
m_vRenderOffset = Vector2D(0, 0); *m_vRenderOffset = Vector2D(0, 0);
} else { } else {
m_fAlpha.setValueAndWarp(1.f); m_fAlpha->setValueAndWarp(1.f);
m_fAlpha = 0.f; *m_fAlpha = 0.f;
m_vRenderOffset = Vector2D(0.0, (left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y) * (movePerc / 100.f)); *m_vRenderOffset = Vector2D(0.0, (left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y) * (movePerc / 100.f));
} }
} else { } else {
if (in) { if (in) {
m_fAlpha.setValueAndWarp(0.f); m_fAlpha->setValueAndWarp(0.f);
m_vRenderOffset.setValueAndWarp(Vector2D((left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0)); m_vRenderOffset->setValueAndWarp(Vector2D((left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0));
m_fAlpha = 1.f; *m_fAlpha = 1.f;
m_vRenderOffset = Vector2D(0, 0); *m_vRenderOffset = Vector2D(0, 0);
} else { } else {
m_fAlpha.setValueAndWarp(1.f); m_fAlpha->setValueAndWarp(1.f);
m_fAlpha = 0.f; *m_fAlpha = 0.f;
m_vRenderOffset = Vector2D((left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0); *m_vRenderOffset = Vector2D((left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0);
} }
} }
} else if (ANIMSTYLE == "fade") { } else if (ANIMSTYLE == "fade") {
m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); // fix a bug, if switching from slide -> fade. m_vRenderOffset->setValueAndWarp(Vector2D(0, 0)); // fix a bug, if switching from slide -> fade.
if (in) { if (in) {
m_fAlpha.setValueAndWarp(0.f); m_fAlpha->setValueAndWarp(0.f);
m_fAlpha = 1.f; *m_fAlpha = 1.f;
} else { } else {
m_fAlpha.setValueAndWarp(1.f); m_fAlpha->setValueAndWarp(1.f);
m_fAlpha = 0.f; *m_fAlpha = 0.f;
} }
} else if (ANIMSTYLE == "slidevert") { } else if (ANIMSTYLE == "slidevert") {
// fallback is slide // fallback is slide
const auto PMONITOR = m_pMonitor.lock(); const auto PMONITOR = m_pMonitor.lock();
const auto YDISTANCE = PMONITOR->vecSize.y + *PWORKSPACEGAP; const auto YDISTANCE = PMONITOR->vecSize.y + *PWORKSPACEGAP;
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. m_fAlpha->setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
if (in) { if (in) {
m_vRenderOffset.setValueAndWarp(Vector2D(0.0, left ? YDISTANCE : -YDISTANCE)); m_vRenderOffset->setValueAndWarp(Vector2D(0.0, left ? YDISTANCE : -YDISTANCE));
m_vRenderOffset = Vector2D(0, 0); *m_vRenderOffset = Vector2D(0, 0);
} else { } else {
m_vRenderOffset = Vector2D(0.0, left ? -YDISTANCE : YDISTANCE); *m_vRenderOffset = Vector2D(0.0, left ? -YDISTANCE : YDISTANCE);
} }
} else { } else {
// fallback is slide // fallback is slide
const auto PMONITOR = m_pMonitor.lock(); const auto PMONITOR = m_pMonitor.lock();
const auto XDISTANCE = PMONITOR->vecSize.x + *PWORKSPACEGAP; const auto XDISTANCE = PMONITOR->vecSize.x + *PWORKSPACEGAP;
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. m_fAlpha->setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
if (in) { if (in) {
m_vRenderOffset.setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0.0)); m_vRenderOffset->setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0.0));
m_vRenderOffset = Vector2D(0, 0); *m_vRenderOffset = Vector2D(0, 0);
} else { } else {
m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0.0); *m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0.0);
} }
} }
if (m_bIsSpecialWorkspace) { if (m_bIsSpecialWorkspace) {
// required for open/close animations // required for open/close animations
if (in) { if (in) {
m_fAlpha.setValueAndWarp(0.f); m_fAlpha->setValueAndWarp(0.f);
m_fAlpha = 1.f; *m_fAlpha = 1.f;
} else { } else {
m_fAlpha.setValueAndWarp(1.f); m_fAlpha->setValueAndWarp(1.f);
m_fAlpha = 0.f; *m_fAlpha = 0.f;
} }
} }
if (instant) { if (instant) {
m_vRenderOffset.warp(); m_vRenderOffset->warp();
m_fAlpha.warp(); m_fAlpha->warp();
} }
} }
@ -633,7 +628,7 @@ void CWorkspace::forceReportSizesToWindows() {
if (w->m_pWorkspace != m_pSelf || !w->m_bIsMapped || w->isHidden()) if (w->m_pWorkspace != m_pSelf || !w->m_bIsMapped || w->isHidden())
continue; continue;
g_pXWaylandManager->setWindowSize(w, w->m_vRealSize.value(), true); g_pXWaylandManager->setWindowSize(w, w->m_vRealSize->goal(), true);
} }
} }

View file

@ -37,8 +37,8 @@ class CWorkspace {
wl_array m_wlrCoordinateArr; wl_array m_wlrCoordinateArr;
// for animations // for animations
CAnimatedVariable<Vector2D> m_vRenderOffset; PHLANIMVAR<Vector2D> m_vRenderOffset;
CAnimatedVariable<float> m_fAlpha; PHLANIMVAR<float> m_fAlpha;
bool m_bForceRendering = false; bool m_bForceRendering = false;
// allows damage to propagate. // allows damage to propagate.

View file

@ -12,10 +12,12 @@
#include "../protocols/core/Compositor.hpp" #include "../protocols/core/Compositor.hpp"
#include "../protocols/ToplevelExport.hpp" #include "../protocols/ToplevelExport.hpp"
#include "../xwayland/XSurface.hpp" #include "../xwayland/XSurface.hpp"
#include "managers/AnimationManager.hpp"
#include "managers/PointerManager.hpp" #include "managers/PointerManager.hpp"
#include <hyprutils/string/String.hpp> #include <hyprutils/string/String.hpp>
using namespace Hyprutils::String; using namespace Hyprutils::String;
using namespace Hyprutils::Animation;
// ------------------------------------------------------------ // // ------------------------------------------------------------ //
// __ _______ _ _ _____ ______ _______ // // __ _______ _ _ _____ ______ _______ //
@ -27,15 +29,17 @@ using namespace Hyprutils::String;
// // // //
// ------------------------------------------------------------ // // ------------------------------------------------------------ //
static void setAnimToMove(void* data) { static void setVector2DAnimToMove(WP<CBaseAnimatedVariable> pav) {
auto* const PANIMCFG = g_pConfigManager->getAnimationPropertyConfig("windowsMove"); const auto PAV = pav.lock();
if (!PAV)
return;
CBaseAnimatedVariable* animvar = (CBaseAnimatedVariable*)data; CAnimatedVariable<Vector2D>* animvar = dynamic_cast<CAnimatedVariable<Vector2D>*>(PAV.get());
animvar->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsMove"));
animvar->setConfig(PANIMCFG); const auto PHLWINDOW = animvar->m_Context.pWindow.lock();
if (PHLWINDOW && PHLWINDOW->m_vRealPosition->isBeingAnimated() && PHLWINDOW->m_vRealSize->isBeingAnimated())
if (animvar->getWindow() && !animvar->getWindow()->m_vRealPosition.isBeingAnimated() && !animvar->getWindow()->m_vRealSize.isBeingAnimated()) PHLWINDOW->m_bAnimatingIn = false;
animvar->getWindow()->m_bAnimatingIn = false;
} }
void Events::listener_mapWindow(void* owner, void* data) { void Events::listener_mapWindow(void* owner, void* data) {
@ -378,10 +382,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
const auto MAXSIZE = PWINDOW->requestedMaxSize(); const auto MAXSIZE = PWINDOW->requestedMaxSize();
const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->vecSize.x) : const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->vecSize.x) :
stringToFloatClamp(SIZEXSTR, PWINDOW->m_vRealSize.goal().x, PMONITOR->vecSize.x); stringToFloatClamp(SIZEXSTR, PWINDOW->m_vRealSize->goal().x, PMONITOR->vecSize.x);
const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, PMONITOR->vecSize.y) : const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, PMONITOR->vecSize.y) :
stringToFloatClamp(SIZEYSTR, PWINDOW->m_vRealSize.goal().y, PMONITOR->vecSize.y); stringToFloatClamp(SIZEYSTR, PWINDOW->m_vRealSize->goal().y, PMONITOR->vecSize.y);
Debug::log(LOG, "Rule size, applying to {}", PWINDOW); Debug::log(LOG, "Rule size, applying to {}", PWINDOW);
@ -418,7 +422,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
(!POSXRAW.contains('%') ? std::stoi(POSXRAW) : std::stof(POSXRAW.substr(0, POSXRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.x); (!POSXRAW.contains('%') ? std::stoi(POSXRAW) : std::stof(POSXRAW.substr(0, POSXRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
if (subtractWindow) if (subtractWindow)
posX -= PWINDOW->m_vRealSize.goal().x; posX -= PWINDOW->m_vRealSize->goal().x;
if (CURSOR) if (CURSOR)
Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!"); Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!");
@ -430,7 +434,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x; posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x;
} else { } else {
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x + posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x +
(!POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goal().x); (!POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize->goal().x);
} }
} }
@ -441,7 +445,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
(!POSYRAW.contains('%') ? std::stoi(POSYRAW) : std::stof(POSYRAW.substr(0, POSYRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.y); (!POSYRAW.contains('%') ? std::stoi(POSYRAW) : std::stof(POSYRAW.substr(0, POSYRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
if (subtractWindow) if (subtractWindow)
posY -= PWINDOW->m_vRealSize.goal().y; posY -= PWINDOW->m_vRealSize->goal().y;
if (CURSOR) if (CURSOR)
Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!"); Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!");
@ -453,7 +457,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y; posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y;
} else { } else {
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y + posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y +
(!POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goal().y); (!POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize->goal().y);
} }
} }
@ -461,15 +465,15 @@ void Events::listener_mapWindow(void* owner, void* data) {
int borderSize = PWINDOW->getRealBorderSize(); int borderSize = PWINDOW->getRealBorderSize();
posX = std::clamp(posX, (int)(PMONITOR->vecReservedTopLeft.x + borderSize), posX = std::clamp(posX, (int)(PMONITOR->vecReservedTopLeft.x + borderSize),
(int)(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PWINDOW->m_vRealSize.goal().x - borderSize)); (int)(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PWINDOW->m_vRealSize->goal().x - borderSize));
posY = std::clamp(posY, (int)(PMONITOR->vecReservedTopLeft.y + borderSize), posY = std::clamp(posY, (int)(PMONITOR->vecReservedTopLeft.y + borderSize),
(int)(PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PWINDOW->m_vRealSize.goal().y - borderSize)); (int)(PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PWINDOW->m_vRealSize->goal().y - borderSize));
} }
Debug::log(LOG, "Rule move, applying to {}", PWINDOW); Debug::log(LOG, "Rule move, applying to {}", PWINDOW);
PWINDOW->m_vRealPosition = Vector2D(posX, posY) + PMONITOR->vecPosition; *PWINDOW->m_vRealPosition = Vector2D(posX, posY) + PMONITOR->vecPosition;
PWINDOW->setHidden(false); PWINDOW->setHidden(false);
} catch (...) { Debug::log(LOG, "Rule move failed, rule: {} -> {}", r->szRule, r->szValue); } } catch (...) { Debug::log(LOG, "Rule move failed, rule: {} -> {}", r->szRule, r->szValue); }
@ -481,7 +485,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (ARGS[1] == "1") if (ARGS[1] == "1")
RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f; RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f;
PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize.goal() / 2.f + RESERVEDOFFSET; *PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize->goal() / 2.f + RESERVEDOFFSET;
break; break;
} }
@ -491,7 +495,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
// set the pseudo size to the GOAL of our current size // set the pseudo size to the GOAL of our current size
// because the windows are animated on RealSize // because the windows are animated on RealSize
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal(); PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize->goal();
g_pCompositor->changeWindowZOrder(PWINDOW, true); g_pCompositor->changeWindowZOrder(PWINDOW, true);
} else { } else {
@ -524,7 +528,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
} }
if (!setPseudo) if (!setPseudo)
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal() - Vector2D(10, 10); PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize->goal() - Vector2D(10, 10);
} }
const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_pLastWindow.lock(); const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_pLastWindow.lock();
@ -554,11 +558,11 @@ void Events::listener_mapWindow(void* owner, void* data) {
(!PWINDOW->isX11OverrideRedirect() || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->wantsFocus())) && !workspaceSilent && (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW) && (!PWINDOW->isX11OverrideRedirect() || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->wantsFocus())) && !workspaceSilent && (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW) &&
!g_pInputManager->isConstrained()) { !g_pInputManager->isConstrained()) {
g_pCompositor->focusWindow(PWINDOW); g_pCompositor->focusWindow(PWINDOW);
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA); PWINDOW->m_fActiveInactiveAlpha->setValueAndWarp(*PACTIVEALPHA);
PWINDOW->m_fDimPercent.setValueAndWarp(PWINDOW->m_sWindowData.noDim.valueOrDefault() ? 0.f : *PDIMSTRENGTH); PWINDOW->m_fDimPercent->setValueAndWarp(PWINDOW->m_sWindowData.noDim.valueOrDefault() ? 0.f : *PDIMSTRENGTH);
} else { } else {
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PINACTIVEALPHA); PWINDOW->m_fActiveInactiveAlpha->setValueAndWarp(*PINACTIVEALPHA);
PWINDOW->m_fDimPercent.setValueAndWarp(0); PWINDOW->m_fDimPercent->setValueAndWarp(0);
} }
if (requestedClientFSMode.has_value() && (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN)) if (requestedClientFSMode.has_value() && (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN))
@ -571,8 +575,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (PWINDOW->m_pWorkspace->m_bHasFullscreenWindow) if (PWINDOW->m_pWorkspace->m_bHasFullscreenWindow)
g_pCompositor->setWindowFullscreenInternal(PWINDOW->m_pWorkspace->getFullscreenWindow(), FSMODE_NONE); g_pCompositor->setWindowFullscreenInternal(PWINDOW->m_pWorkspace->getFullscreenWindow(), FSMODE_NONE);
PWINDOW->m_vRealPosition.warp(); PWINDOW->m_vRealPosition->warp();
PWINDOW->m_vRealSize.warp(); PWINDOW->m_vRealSize->warp();
if (requestedFSState.has_value()) { if (requestedFSState.has_value()) {
PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_WINDOW_RULE); PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_WINDOW_RULE);
g_pCompositor->setWindowFullscreenState(PWINDOW, requestedFSState.value()); g_pCompositor->setWindowFullscreenState(PWINDOW, requestedFSState.value());
@ -607,7 +611,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_bFirstMap = false; PWINDOW->m_bFirstMap = false;
Debug::log(LOG, "Map request dispatched, monitor {}, window pos: {:5j}, window size: {:5j}", PMONITOR->szName, PWINDOW->m_vRealPosition.goal(), PWINDOW->m_vRealSize.goal()); Debug::log(LOG, "Map request dispatched, monitor {}, window pos: {:5j}, window size: {:5j}", PMONITOR->szName, PWINDOW->m_vRealPosition->goal(), PWINDOW->m_vRealSize->goal());
auto workspaceID = requestedWorkspace != "" ? requestedWorkspace : PWORKSPACE->m_szName; auto workspaceID = requestedWorkspace != "" ? requestedWorkspace : PWORKSPACE->m_szName;
g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", std::format("{:x},{},{},{}", PWINDOW, workspaceID, PWINDOW->m_szClass, PWINDOW->m_szTitle)}); g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", std::format("{:x},{},{},{}", PWINDOW, workspaceID, PWINDOW->m_szClass, PWINDOW->m_szTitle)});
@ -620,17 +624,17 @@ void Events::listener_mapWindow(void* owner, void* data) {
// do animations // do animations
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, false); g_pAnimationManager->onWindowPostCreateClose(PWINDOW, false);
PWINDOW->m_fAlpha.setValueAndWarp(0.f); PWINDOW->m_fAlpha->setValueAndWarp(0.f);
PWINDOW->m_fAlpha = 1.f; *PWINDOW->m_fAlpha = 1.f;
PWINDOW->m_vRealPosition.setCallbackOnEnd(setAnimToMove); PWINDOW->m_vRealPosition->setCallbackOnEnd(setVector2DAnimToMove);
PWINDOW->m_vRealSize.setCallbackOnEnd(setAnimToMove); PWINDOW->m_vRealSize->setCallbackOnEnd(setVector2DAnimToMove);
// recalc the values for this window // recalc the values for this window
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW); g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
// avoid this window being visible // avoid this window being visible
if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->isFullscreen() && !PWINDOW->m_bIsFloating) if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->isFullscreen() && !PWINDOW->m_bIsFloating)
PWINDOW->m_fAlpha.setValueAndWarp(0.f); PWINDOW->m_fAlpha->setValueAndWarp(0.f);
g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface->resource(), PMONITOR->scale); g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface->resource(), PMONITOR->scale);
g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface->resource(), PMONITOR->transform); g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface->resource(), PMONITOR->transform);
@ -666,8 +670,8 @@ void Events::listener_unmapWindow(void* owner, void* data) {
const auto PMONITOR = PWINDOW->m_pMonitor.lock(); const auto PMONITOR = PWINDOW->m_pMonitor.lock();
if (PMONITOR) { if (PMONITOR) {
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.value() - PMONITOR->vecPosition; PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition->value() - PMONITOR->vecPosition;
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.value(); PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize->value();
PWINDOW->m_eOriginalClosedExtents = PWINDOW->getFullWindowExtents(); PWINDOW->m_eOriginalClosedExtents = PWINDOW->getFullWindowExtents();
} }
@ -758,11 +762,11 @@ void Events::listener_unmapWindow(void* owner, void* data) {
g_pCompositor->addToFadingOutSafe(PWINDOW); g_pCompositor->addToFadingOutSafe(PWINDOW);
if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in. if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in.
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.value() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it *PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition->value() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it
// anims // anims
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, true); g_pAnimationManager->onWindowPostCreateClose(PWINDOW, true);
PWINDOW->m_fAlpha = 0.f; *PWINDOW->m_fAlpha = 0.f;
// recheck idle inhibitors // recheck idle inhibitors
g_pInputManager->recheckIdleInhibitorStatus(); g_pInputManager->recheckIdleInhibitorStatus();
@ -812,7 +816,7 @@ void Events::listener_commitWindow(void* owner, void* data) {
g_pSeatManager->isPointerFrameSkipped = false; g_pSeatManager->isPointerFrameSkipped = false;
g_pSeatManager->isPointerFrameCommit = false; g_pSeatManager->isPointerFrameCommit = false;
} else } else
g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface->resource(), PWINDOW->m_vRealPosition.goal().x, PWINDOW->m_vRealPosition.goal().y, g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface->resource(), PWINDOW->m_vRealPosition->goal().x, PWINDOW->m_vRealPosition->goal().y,
PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0); PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0);
if (g_pSeatManager->isPointerFrameSkipped) { if (g_pSeatManager->isPointerFrameSkipped) {
@ -903,8 +907,8 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
if (!PWINDOW->m_bIsMapped || !PWINDOW->m_pXWaylandSurface || !PWINDOW->m_pXWaylandSurface->overrideRedirect) if (!PWINDOW->m_bIsMapped || !PWINDOW->m_pXWaylandSurface || !PWINDOW->m_pXWaylandSurface->overrideRedirect)
return; return;
const auto POS = PWINDOW->m_vRealPosition.goal(); const auto POS = PWINDOW->m_vRealPosition->goal();
const auto SIZ = PWINDOW->m_vRealSize.goal(); const auto SIZ = PWINDOW->m_vRealSize->goal();
if (PWINDOW->m_pXWaylandSurface->geometry.size() > Vector2D{1, 1}) if (PWINDOW->m_pXWaylandSurface->geometry.size() > Vector2D{1, 1})
PWINDOW->setHidden(false); PWINDOW->setHidden(false);
@ -912,7 +916,7 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
PWINDOW->setHidden(true); PWINDOW->setHidden(true);
if (PWINDOW->isFullscreen() || !PWINDOW->m_bIsFloating) { if (PWINDOW->isFullscreen() || !PWINDOW->m_bIsFloating) {
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal(), true); g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize->goal(), true);
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
return; return;
} }
@ -926,27 +930,27 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
Debug::log(LOG, "Unmanaged window {} requests geometry update to {:j} {:j}", PWINDOW, LOGICALPOS, PWINDOW->m_pXWaylandSurface->geometry.size()); Debug::log(LOG, "Unmanaged window {} requests geometry update to {:j} {:j}", PWINDOW, LOGICALPOS, PWINDOW->m_pXWaylandSurface->geometry.size());
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
PWINDOW->m_vRealPosition.setValueAndWarp(Vector2D(LOGICALPOS.x, LOGICALPOS.y)); PWINDOW->m_vRealPosition->setValueAndWarp(Vector2D(LOGICALPOS.x, LOGICALPOS.y));
if (abs(std::floor(SIZ.x) - PWINDOW->m_pXWaylandSurface->geometry.w) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_pXWaylandSurface->geometry.h) > 2) if (abs(std::floor(SIZ.x) - PWINDOW->m_pXWaylandSurface->geometry.w) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_pXWaylandSurface->geometry.h) > 2)
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_pXWaylandSurface->geometry.size()); PWINDOW->m_vRealSize->setValueAndWarp(PWINDOW->m_pXWaylandSurface->geometry.size());
if (*PXWLFORCESCALEZERO) { if (*PXWLFORCESCALEZERO) {
if (const auto PMONITOR = PWINDOW->m_pMonitor.lock(); PMONITOR) { if (const auto PMONITOR = PWINDOW->m_pMonitor.lock(); PMONITOR) {
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goal() / PMONITOR->scale); PWINDOW->m_vRealSize->setValueAndWarp(PWINDOW->m_vRealSize->goal() / PMONITOR->scale);
} }
} }
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goal(); PWINDOW->m_vPosition = PWINDOW->m_vRealPosition->goal();
PWINDOW->m_vSize = PWINDOW->m_vRealSize.goal(); PWINDOW->m_vSize = PWINDOW->m_vRealSize->goal();
PWINDOW->m_pWorkspace = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.value() + PWINDOW->m_vRealSize.value() / 2.f)->activeWorkspace; PWINDOW->m_pWorkspace = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition->value() + PWINDOW->m_vRealSize->value() / 2.f)->activeWorkspace;
g_pCompositor->changeWindowZOrder(PWINDOW, true); g_pCompositor->changeWindowZOrder(PWINDOW, true);
PWINDOW->updateWindowDecos(); PWINDOW->updateWindowDecos();
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
PWINDOW->m_vReportedPosition = PWINDOW->m_vRealPosition.goal(); PWINDOW->m_vReportedPosition = PWINDOW->m_vRealPosition->goal();
PWINDOW->m_vPendingReportedSize = PWINDOW->m_vRealSize.goal(); PWINDOW->m_vPendingReportedSize = PWINDOW->m_vRealSize->goal();
} }
} }

View file

@ -1,87 +0,0 @@
#include "AnimatedVariable.hpp"
#include "../managers/AnimationManager.hpp"
#include "../config/ConfigManager.hpp"
CBaseAnimatedVariable::CBaseAnimatedVariable(eAnimatedVarType type) : m_Type(type) {
; // dummy var
}
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLWINDOW pWindow, eAVarDamagePolicy policy) {
m_eDamagePolicy = policy;
m_pConfig = pAnimConfig;
m_pWindow = pWindow;
m_bDummy = false;
}
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLLS pLayer, eAVarDamagePolicy policy) {
m_eDamagePolicy = policy;
m_pConfig = pAnimConfig;
m_pLayer = pLayer;
m_bDummy = false;
}
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLWORKSPACE pWorkspace, eAVarDamagePolicy policy) {
m_eDamagePolicy = policy;
m_pConfig = pAnimConfig;
m_pWorkspace = pWorkspace;
m_bDummy = false;
}
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, eAVarDamagePolicy policy) {
m_eDamagePolicy = policy;
m_pConfig = pAnimConfig;
m_bDummy = false;
}
CBaseAnimatedVariable::~CBaseAnimatedVariable() {
unregister();
}
void CBaseAnimatedVariable::unregister() {
if (!g_pAnimationManager)
return;
std::erase_if(g_pAnimationManager->m_vAnimatedVariables, [&](const auto& other) { return other == this; });
m_bIsRegistered = false;
disconnectFromActive();
}
void CBaseAnimatedVariable::registerVar() {
if (!m_bIsRegistered)
g_pAnimationManager->m_vAnimatedVariables.push_back(this);
m_bIsRegistered = true;
}
float CBaseAnimatedVariable::getPercent() {
const auto DURATIONPASSED = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - animationBegin).count();
return std::clamp((DURATIONPASSED / 100.f) / m_pConfig->pValues->internalSpeed, 0.f, 1.f);
}
float CBaseAnimatedVariable::getCurveValue() {
if (!m_bIsBeingAnimated)
return 1.f;
const auto SPENT = getPercent();
if (SPENT >= 1.f)
return 1.f;
return g_pAnimationManager->getBezier(m_pConfig->pValues->internalBezier)->getYForPoint(SPENT);
}
void CBaseAnimatedVariable::connectToActive() {
g_pAnimationManager->scheduleTick(); // otherwise the animation manager will never pick this up
if (!m_bIsConnectedToActive)
g_pAnimationManager->m_vActiveAnimatedVariables.push_back(this);
m_bIsConnectedToActive = true;
}
void CBaseAnimatedVariable::disconnectFromActive() {
std::erase_if(g_pAnimationManager->m_vActiveAnimatedVariables, [&](const auto& other) { return other == this; });
m_bIsConnectedToActive = false;
}

View file

@ -1,15 +1,18 @@
#pragma once #pragma once
#include <functional> #include <hyprutils/animation/AnimatedVariable.hpp>
#include <any>
#include <chrono>
#include <type_traits>
#include "math/Math.hpp"
#include "Color.hpp" #include "Color.hpp"
#include "../defines.hpp" #include "../defines.hpp"
#include "../debug/Log.hpp"
#include "../desktop/DesktopTypes.hpp" #include "../desktop/DesktopTypes.hpp"
enum eAVarDamagePolicy : int8_t {
AVARDAMAGE_NONE = -1,
AVARDAMAGE_ENTIRE = 0,
AVARDAMAGE_BORDER,
AVARDAMAGE_SHADOW
};
enum eAnimatedVarType : int8_t { enum eAnimatedVarType : int8_t {
AVARTYPE_INVALID = -1, AVARTYPE_INVALID = -1,
AVARTYPE_FLOAT, AVARTYPE_FLOAT,
@ -42,20 +45,6 @@ struct STypeToAnimatedVarType_t<CHyprColor> {
template <class T> template <class T>
inline constexpr eAnimatedVarType typeToeAnimatedVarType = STypeToAnimatedVarType_t<T>::value; inline constexpr eAnimatedVarType typeToeAnimatedVarType = STypeToAnimatedVarType_t<T>::value;
enum eAVarDamagePolicy : int8_t {
AVARDAMAGE_NONE = -1,
AVARDAMAGE_ENTIRE = 0,
AVARDAMAGE_BORDER,
AVARDAMAGE_SHADOW
};
class CAnimationManager;
struct SAnimationPropertyConfig;
class CHyprRenderer;
class CWindow;
class CWorkspace;
class CLayerSurface;
// Utility to define a concept as a list of possible type // Utility to define a concept as a list of possible type
template <class T, class... U> template <class T, class... U>
concept OneOf = (... or std::same_as<T, U>); concept OneOf = (... or std::same_as<T, U>);
@ -66,245 +55,19 @@ concept OneOf = (... or std::same_as<T, U>);
template <class T> template <class T>
concept Animable = OneOf<T, Vector2D, float, CHyprColor>; concept Animable = OneOf<T, Vector2D, float, CHyprColor>;
class CBaseAnimatedVariable { struct SAnimationContext {
public: PHLWINDOWREF pWindow;
CBaseAnimatedVariable(eAnimatedVarType type); PHLWORKSPACEREF pWorkspace;
void create(SAnimationPropertyConfig* pAnimConfig, PHLWINDOW pWindow, eAVarDamagePolicy policy); PHLLSREF pLayer;
void create(SAnimationPropertyConfig* pAnimConfig, PHLLS pLayer, eAVarDamagePolicy policy);
void create(SAnimationPropertyConfig* pAnimConfig, PHLWORKSPACE pWorkspace, eAVarDamagePolicy policy);
void create(SAnimationPropertyConfig* pAnimConfig, eAVarDamagePolicy policy);
CBaseAnimatedVariable(const CBaseAnimatedVariable&) = delete; eAVarDamagePolicy eDamagePolicy = AVARDAMAGE_NONE;
CBaseAnimatedVariable(CBaseAnimatedVariable&&) = delete;
CBaseAnimatedVariable& operator=(const CBaseAnimatedVariable&) = delete;
CBaseAnimatedVariable& operator=(CBaseAnimatedVariable&&) = delete;
virtual ~CBaseAnimatedVariable();
void unregister();
void registerVar();
virtual void warp(bool endCallback = true) = 0;
//
void setConfig(SAnimationPropertyConfig* pConfig) {
m_pConfig = pConfig;
}
SAnimationPropertyConfig* getConfig() {
return m_pConfig;
}
/* returns the spent (completion) % */
float getPercent();
/* returns the current curve value */
float getCurveValue();
// checks if an animation is in progress
bool isBeingAnimated() const {
return m_bIsBeingAnimated;
}
/* sets a function to be ran when the animation finishes.
if an animation is not running, runs instantly.
if "remove" is set to true, will remove the callback when ran. */
void setCallbackOnEnd(std::function<void(void* thisptr)> func, bool remove = true) {
m_fEndCallback = std::move(func);
m_bRemoveEndAfterRan = remove;
if (!isBeingAnimated())
onAnimationEnd();
}
/* sets a function to be ran when an animation is started.
if "remove" is set to true, will remove the callback when ran. */
void setCallbackOnBegin(std::function<void(void* thisptr)> func, bool remove = true) {
m_fBeginCallback = std::move(func);
m_bRemoveBeginAfterRan = remove;
}
/* Sets the update callback, called every time the value is animated and a step is done
Warning: calling unregisterVar/registerVar in this handler will cause UB */
void setUpdateCallback(std::function<void(void* thisptr)> func) {
m_fUpdateCallback = std::move(func);
}
/* resets all callbacks. Does not call any. */
void resetAllCallbacks() {
m_fBeginCallback = nullptr;
m_fEndCallback = nullptr;
m_fUpdateCallback = nullptr;
m_bRemoveBeginAfterRan = false;
m_bRemoveEndAfterRan = false;
}
PHLWINDOW getWindow() {
return m_pWindow.lock();
}
protected:
PHLWINDOWREF m_pWindow;
PHLWORKSPACEREF m_pWorkspace;
PHLLSREF m_pLayer;
SAnimationPropertyConfig* m_pConfig = nullptr;
bool m_bDummy = true;
bool m_bIsRegistered = false;
bool m_bIsBeingAnimated = false;
std::chrono::steady_clock::time_point animationBegin;
eAVarDamagePolicy m_eDamagePolicy = AVARDAMAGE_NONE;
eAnimatedVarType m_Type;
bool m_bRemoveEndAfterRan = true;
bool m_bRemoveBeginAfterRan = true;
std::function<void(void* thisptr)> m_fEndCallback;
std::function<void(void* thisptr)> m_fBeginCallback;
std::function<void(void* thisptr)> m_fUpdateCallback;
bool m_bIsConnectedToActive = false;
void connectToActive();
void disconnectFromActive();
// methods
void onAnimationEnd() {
m_bIsBeingAnimated = false;
disconnectFromActive();
if (m_fEndCallback) {
// loading m_bRemoveEndAfterRan before calling the callback allows the callback to delete this animation safely if it is false.
auto removeEndCallback = m_bRemoveEndAfterRan;
m_fEndCallback(this);
if (removeEndCallback)
m_fEndCallback = nullptr; // reset
}
}
void onAnimationBegin() {
m_bIsBeingAnimated = true;
connectToActive();
if (m_fBeginCallback) {
m_fBeginCallback(this);
if (m_bRemoveBeginAfterRan)
m_fBeginCallback = nullptr; // reset
}
}
friend class CAnimationManager;
friend class CWorkspace;
friend class CLayerSurface;
friend class CHyprRenderer;
}; };
template <Animable VarType> template <Animable VarType>
class CAnimatedVariable : public CBaseAnimatedVariable { using CAnimatedVariable = Hyprutils::Animation::CGenericAnimatedVariable<VarType, SAnimationContext>;
public:
CAnimatedVariable() : CBaseAnimatedVariable(typeToeAnimatedVarType<VarType>) {
;
} // dummy var
void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, PHLWINDOW pWindow, eAVarDamagePolicy policy) { template <Animable VarType>
create(pAnimConfig, pWindow, policy); using PHLANIMVAR = SP<CAnimatedVariable<VarType>>;
m_Value = value;
m_Goal = value;
}
void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, PHLLS pLayer, eAVarDamagePolicy policy) {
create(pAnimConfig, pLayer, policy);
m_Value = value;
m_Goal = value;
}
void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, PHLWORKSPACE pWorkspace, eAVarDamagePolicy policy) {
create(pAnimConfig, pWorkspace, policy);
m_Value = value;
m_Goal = value;
}
void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, eAVarDamagePolicy policy) {
create(pAnimConfig, policy);
m_Value = value;
m_Goal = value;
}
using CBaseAnimatedVariable::create; template <Animable VarType>
using PHLANIMVARREF = WP<CAnimatedVariable<VarType>>;
CAnimatedVariable(const CAnimatedVariable&) = delete;
CAnimatedVariable(CAnimatedVariable&&) = delete;
CAnimatedVariable& operator=(const CAnimatedVariable&) = delete;
CAnimatedVariable& operator=(CAnimatedVariable&&) = delete;
~CAnimatedVariable() = default;
// gets the current vector value (real time)
const VarType& value() const {
return m_Value;
}
// gets the goal vector value
const VarType& goal() const {
return m_Goal;
}
CAnimatedVariable& operator=(const VarType& v) {
if (v == m_Goal)
return *this;
m_Goal = v;
animationBegin = std::chrono::steady_clock::now();
m_Begun = m_Value;
onAnimationBegin();
return *this;
}
// Sets the actual stored value, without affecting the goal, but resets the timer
void setValue(const VarType& v) {
if (v == m_Value)
return;
m_Value = v;
animationBegin = std::chrono::steady_clock::now();
m_Begun = m_Value;
onAnimationBegin();
}
// Sets the actual value and goal
void setValueAndWarp(const VarType& v) {
m_Goal = v;
m_bIsBeingAnimated = true;
warp();
}
void warp(bool endCallback = true) override {
if (!m_bIsBeingAnimated)
return;
m_Value = m_Goal;
m_bIsBeingAnimated = false;
if (m_fUpdateCallback)
m_fUpdateCallback(this);
if (endCallback)
onAnimationEnd();
}
private:
VarType m_Value{};
VarType m_Goal{};
VarType m_Begun{};
// owners
friend class CAnimationManager;
friend class CWorkspace;
friend class CLayerSurface;
friend class CHyprRenderer;
};

View file

@ -1,90 +0,0 @@
#include "BezierCurve.hpp"
#include "../debug/Log.hpp"
#include "../macros.hpp"
#include <chrono>
#include <algorithm>
void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
const auto BEGIN = std::chrono::high_resolution_clock::now();
// Avoid reallocations by reserving enough memory upfront
m_vPoints.resize(pVec->size() + 2);
m_vPoints[0] = Vector2D(0, 0); // Start point
size_t index = 1; // Start after the first element
for (const auto& vec : *pVec) {
if (index < m_vPoints.size() - 1) { // Bounds check to ensure safety
m_vPoints[index] = vec;
++index;
}
}
m_vPoints.back() = Vector2D(1, 1); // End point
RASSERT(m_vPoints.size() == 4, "CBezierCurve only supports cubic beziers! (points num: {})", m_vPoints.size());
// bake BAKEDPOINTS points for faster lookups
// T -> X ( / BAKEDPOINTS )
for (int i = 0; i < BAKEDPOINTS; ++i) {
float const t = (i + 1) / (float)BAKEDPOINTS;
m_aPointsBaked[i] = Vector2D(getXForT(t), getYForT(t));
}
const auto ELAPSEDUS = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - BEGIN).count() / 1000.f;
const auto POINTSSIZE = m_aPointsBaked.size() * sizeof(m_aPointsBaked[0]) / 1000.f;
const auto BEGINCALC = std::chrono::high_resolution_clock::now();
for (int j = 1; j < 10; ++j) {
float i = j / 10.0f;
getYForPoint(i);
}
const auto ELAPSEDCALCAVG = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - BEGINCALC).count() / 1000.f / 10.f;
Debug::log(LOG, "Created a bezier curve, baked {} points, mem usage: {:.2f}kB, time to bake: {:.2f}µs. Estimated average calc time: {:.2f}µs.", BAKEDPOINTS, POINTSSIZE,
ELAPSEDUS, ELAPSEDCALCAVG);
}
float CBezierCurve::getXForT(float const& t) const {
float t2 = t * t;
float t3 = t2 * t;
return 3 * t * (1 - t) * (1 - t) * m_vPoints[1].x + 3 * t2 * (1 - t) * m_vPoints[2].x + t3 * m_vPoints[3].x;
}
float CBezierCurve::getYForT(float const& t) const {
float t2 = t * t;
float t3 = t2 * t;
return 3 * t * (1 - t) * (1 - t) * m_vPoints[1].y + 3 * t2 * (1 - t) * m_vPoints[2].y + t3 * m_vPoints[3].y;
}
// Todo: this probably can be done better and faster
float CBezierCurve::getYForPoint(float const& x) const {
if (x >= 1.f)
return 1.f;
if (x <= 0.f)
return 0.f;
int index = 0;
bool below = true;
for (int step = (BAKEDPOINTS + 1) / 2; step > 0; step /= 2) {
if (below)
index += step;
else
index -= step;
below = m_aPointsBaked[index].x < x;
}
int lowerIndex = index - (!below || index == BAKEDPOINTS - 1);
// in the name of performance i shall make a hack
const auto LOWERPOINT = &m_aPointsBaked[lowerIndex];
const auto UPPERPOINT = &m_aPointsBaked[lowerIndex + 1];
const auto PERCINDELTA = (x - LOWERPOINT->x) / (UPPERPOINT->x - LOWERPOINT->x);
if (std::isnan(PERCINDELTA) || std::isinf(PERCINDELTA)) // can sometimes happen for VERY small x
return 0.f;
return LOWERPOINT->y + (UPPERPOINT->y - LOWERPOINT->y) * PERCINDELTA;
}

View file

@ -1,28 +0,0 @@
#pragma once
#include <vector>
#include <array>
#include <vector>
#include "math/Math.hpp"
constexpr int BAKEDPOINTS = 255;
constexpr float INVBAKEDPOINTS = 1.f / BAKEDPOINTS;
// an implementation of a cubic bezier curve
// might do better later
class CBezierCurve {
public:
// sets up the bezier curve.
// this EXCLUDES the 0,0 and 1,1 points,
void setup(std::vector<Vector2D>* points);
float getYForT(float const& t) const;
float getXForT(float const& t) const;
float getYForPoint(float const& x) const;
private:
// this INCLUDES the 0,0 and 1,1 points.
std::vector<Vector2D> m_vPoints;
std::array<Vector2D, BAKEDPOINTS> m_aPointsBaked;
};

View file

@ -1127,15 +1127,15 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) {
if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && !w->isX11OverrideRedirect()) { if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && !w->isX11OverrideRedirect()) {
// if it's floating and the middle isnt on the current mon, move it to the center // if it's floating and the middle isnt on the current mon, move it to the center
const auto PMONFROMMIDDLE = g_pCompositor->getMonitorFromVector(MIDDLE); const auto PMONFROMMIDDLE = g_pCompositor->getMonitorFromVector(MIDDLE);
Vector2D pos = w->m_vRealPosition.goal(); Vector2D pos = w->m_vRealPosition->goal();
if (!VECINRECT(MIDDLE, PMONFROMMIDDLE->vecPosition.x, PMONFROMMIDDLE->vecPosition.y, PMONFROMMIDDLE->vecPosition.x + PMONFROMMIDDLE->vecSize.x, if (!VECINRECT(MIDDLE, PMONFROMMIDDLE->vecPosition.x, PMONFROMMIDDLE->vecPosition.y, PMONFROMMIDDLE->vecPosition.x + PMONFROMMIDDLE->vecSize.x,
PMONFROMMIDDLE->vecPosition.y + PMONFROMMIDDLE->vecSize.y)) { PMONFROMMIDDLE->vecPosition.y + PMONFROMMIDDLE->vecSize.y)) {
// not on any monitor, center // not on any monitor, center
pos = middle() / 2.f - w->m_vRealSize.goal() / 2.f; pos = middle() / 2.f - w->m_vRealSize->goal() / 2.f;
} else } else
pos = pos - PMONFROMMIDDLE->vecPosition + vecPosition; pos = pos - PMONFROMMIDDLE->vecPosition + vecPosition;
w->m_vRealPosition = pos; *w->m_vRealPosition = pos;
w->m_vPosition = pos; w->m_vPosition = pos;
} }
} }

View file

@ -5,7 +5,6 @@
#include "../desktop/Window.hpp" #include "../desktop/Window.hpp"
#include "../desktop/Subsurface.hpp" #include "../desktop/Subsurface.hpp"
#include "../desktop/Popup.hpp" #include "../desktop/Popup.hpp"
#include "AnimatedVariable.hpp"
#include "../desktop/WLSurface.hpp" #include "../desktop/WLSurface.hpp"
#include "signal/Signal.hpp" #include "signal/Signal.hpp"
#include "math/Math.hpp" #include "math/Math.hpp"

View file

@ -3,13 +3,13 @@
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "../config/ConfigValue.hpp" #include "../config/ConfigValue.hpp"
#include "../render/pass/TexPassElement.hpp" #include "../render/pass/TexPassElement.hpp"
#include "../managers/AnimationManager.hpp"
#include <hyprutils/utils/ScopeGuard.hpp> #include <hyprutils/utils/ScopeGuard.hpp>
using namespace Hyprutils::Utils; using namespace Hyprutils::Animation;
CHyprError::CHyprError() { CHyprError::CHyprError() {
m_fFadeOpacity.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), AVARDAMAGE_NONE); g_pAnimationManager->createAnimation(0.f, m_fFadeOpacity, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), AVARDAMAGE_NONE);
m_fFadeOpacity.registerVar();
static auto P = g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) { static auto P = g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) {
if (!m_bIsCreated) if (!m_bIsCreated)
@ -23,16 +23,14 @@ CHyprError::CHyprError() {
if (!m_bIsCreated) if (!m_bIsCreated)
return; return;
if (m_fFadeOpacity.isBeingAnimated() || m_bMonitorChanged) if (m_fFadeOpacity->isBeingAnimated() || m_bMonitorChanged)
g_pHyprRenderer->damageBox(&m_bDamageBox); g_pHyprRenderer->damageBox(&m_bDamageBox);
}); });
m_pTexture = makeShared<CTexture>(); m_pTexture = makeShared<CTexture>();
} }
CHyprError::~CHyprError() { CHyprError::~CHyprError() = default;
m_fFadeOpacity.unregister();
}
void CHyprError::queueCreate(std::string message, const CHyprColor& color) { void CHyprError::queueCreate(std::string message, const CHyprColor& color) {
m_szQueued = message; m_szQueued = message;
@ -43,10 +41,10 @@ void CHyprError::createQueued() {
if (m_bIsCreated) if (m_bIsCreated)
m_pTexture->destroyTexture(); m_pTexture->destroyTexture();
m_fFadeOpacity.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn")); m_fFadeOpacity->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn"));
m_fFadeOpacity.setValueAndWarp(0.f); m_fFadeOpacity->setValueAndWarp(0.f);
m_fFadeOpacity = 1.f; *m_fFadeOpacity = 1.f;
const auto PMONITOR = g_pCompositor->m_vMonitors.front(); const auto PMONITOR = g_pCompositor->m_vMonitors.front();
@ -176,8 +174,8 @@ void CHyprError::draw() {
} }
if (m_bQueuedDestroy) { if (m_bQueuedDestroy) {
if (!m_fFadeOpacity.isBeingAnimated()) { if (!m_fFadeOpacity->isBeingAnimated()) {
if (m_fFadeOpacity.value() == 0.f) { if (m_fFadeOpacity->value() == 0.f) {
m_bQueuedDestroy = false; m_bQueuedDestroy = false;
m_pTexture->destroyTexture(); m_pTexture->destroyTexture();
m_bIsCreated = false; m_bIsCreated = false;
@ -189,8 +187,8 @@ void CHyprError::draw() {
return; return;
} else { } else {
m_fFadeOpacity.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut")); m_fFadeOpacity->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut"));
m_fFadeOpacity = 0.f; *m_fFadeOpacity = 0.f;
} }
} }
} }
@ -202,7 +200,7 @@ void CHyprError::draw() {
m_bDamageBox.x = (int)PMONITOR->vecPosition.x; m_bDamageBox.x = (int)PMONITOR->vecPosition.x;
m_bDamageBox.y = (int)PMONITOR->vecPosition.y; m_bDamageBox.y = (int)PMONITOR->vecPosition.y;
if (m_fFadeOpacity.isBeingAnimated() || m_bMonitorChanged) if (m_fFadeOpacity->isBeingAnimated() || m_bMonitorChanged)
g_pHyprRenderer->damageBox(&m_bDamageBox); g_pHyprRenderer->damageBox(&m_bDamageBox);
m_bMonitorChanged = false; m_bMonitorChanged = false;
@ -210,7 +208,7 @@ void CHyprError::draw() {
CTexPassElement::SRenderData data; CTexPassElement::SRenderData data;
data.tex = m_pTexture; data.tex = m_pTexture;
data.box = monbox; data.box = monbox;
data.a = m_fFadeOpacity.value(); data.a = m_fFadeOpacity->value();
g_pHyprRenderer->m_sRenderPass.add(makeShared<CTexPassElement>(data)); g_pHyprRenderer->m_sRenderPass.add(makeShared<CTexPassElement>(data));
} }

View file

@ -25,7 +25,7 @@ class CHyprError {
bool m_bQueuedDestroy = false; bool m_bQueuedDestroy = false;
bool m_bIsCreated = false; bool m_bIsCreated = false;
SP<CTexture> m_pTexture; SP<CTexture> m_pTexture;
CAnimatedVariable<float> m_fFadeOpacity; PHLANIMVAR<float> m_fFadeOpacity;
CBox m_bDamageBox = {0, 0, 0, 0}; CBox m_bDamageBox = {0, 0, 0, 0};
float m_fLastHeight = 0.F; float m_fLastHeight = 0.F;

View file

@ -192,16 +192,16 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR}; CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR};
wb.round(); // avoid rounding mess wb.round(); // avoid rounding mess
PWINDOW->m_vRealPosition = wb.pos(); *PWINDOW->m_vRealPosition = wb.pos();
PWINDOW->m_vRealSize = wb.size(); *PWINDOW->m_vRealSize = wb.size();
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size()); g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
} else { } else {
CBox wb = {calcPos, calcSize}; CBox wb = {calcPos, calcSize};
wb.round(); // avoid rounding mess wb.round(); // avoid rounding mess
PWINDOW->m_vRealSize = wb.size(); *PWINDOW->m_vRealSize = wb.size();
PWINDOW->m_vRealPosition = wb.pos(); *PWINDOW->m_vRealPosition = wb.pos();
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size()); g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
} }
@ -209,8 +209,8 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
if (force) { if (force) {
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
PWINDOW->m_vRealPosition.warp(); PWINDOW->m_vRealPosition->warp();
PWINDOW->m_vRealSize.warp(); PWINDOW->m_vRealSize->warp();
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
} }
@ -508,8 +508,8 @@ void CHyprDwindleLayout::calculateWorkspace(const PHLWORKSPACE& pWorkspace) {
const auto PFULLWINDOW = pWorkspace->getFullscreenWindow(); const auto PFULLWINDOW = pWorkspace->getFullscreenWindow();
if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) { if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) {
PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition; *PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition;
PFULLWINDOW->m_vRealSize = PMONITOR->vecSize; *PFULLWINDOW->m_vRealSize = PMONITOR->vecSize;
} else if (pWorkspace->m_efFullscreenMode == FSMODE_MAXIMIZED) { } else if (pWorkspace->m_efFullscreenMode == FSMODE_MAXIMIZED) {
SDwindleNodeData fakeNode; SDwindleNodeData fakeNode;
fakeNode.pWindow = PFULLWINDOW; fakeNode.pWindow = PFULLWINDOW;
@ -554,8 +554,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
const auto PNODE = getNodeFromWindow(PWINDOW); const auto PNODE = getNodeFromWindow(PWINDOW);
if (!PNODE) { if (!PNODE) {
PWINDOW->m_vRealSize = *PWINDOW->m_vRealSize =
(PWINDOW->m_vRealSize.goal() + pixResize) (PWINDOW->m_vRealSize->goal() + pixResize)
.clamp(PWINDOW->m_sWindowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_sWindowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY})); .clamp(PWINDOW->m_sWindowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_sWindowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY}));
PWINDOW->updateWindowDecos(); PWINDOW->updateWindowDecos();
return; return;
@ -575,7 +575,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
if (!m_PseudoDragFlags.started) { if (!m_PseudoDragFlags.started) {
m_PseudoDragFlags.started = true; m_PseudoDragFlags.started = true;
const auto pseudoSize = PWINDOW->m_vRealSize.goal(); const auto pseudoSize = PWINDOW->m_vRealSize->goal();
const auto mouseOffset = g_pInputManager->getMouseCoordsInternal() - (PNODE->box.pos() + ((PNODE->box.size() / 2) - (pseudoSize / 2))); const auto mouseOffset = g_pInputManager->getMouseCoordsInternal() - (PNODE->box.pos() + ((PNODE->box.size() / 2) - (pseudoSize / 2)));
if (mouseOffset.x > 0 && mouseOffset.x < pseudoSize.x && mouseOffset.y > 0 && mouseOffset.y < pseudoSize.y) { if (mouseOffset.x > 0 && mouseOffset.x < pseudoSize.x && mouseOffset.y > 0 && mouseOffset.y < pseudoSize.y) {
@ -743,10 +743,10 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFu
// save position and size if floating // save position and size if floating
if (pWindow->m_bIsFloating && CURRENT_EFFECTIVE_MODE == FSMODE_NONE) { if (pWindow->m_bIsFloating && CURRENT_EFFECTIVE_MODE == FSMODE_NONE) {
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goal(); pWindow->m_vLastFloatingSize = pWindow->m_vRealSize->goal();
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goal(); pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition->goal();
pWindow->m_vPosition = pWindow->m_vRealPosition.goal(); pWindow->m_vPosition = pWindow->m_vRealPosition->goal();
pWindow->m_vSize = pWindow->m_vRealSize.goal(); pWindow->m_vSize = pWindow->m_vRealSize->goal();
} }
if (EFFECTIVE_MODE == FSMODE_NONE) { if (EFFECTIVE_MODE == FSMODE_NONE) {
@ -756,8 +756,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFu
applyNodeDataToWindow(PNODE); applyNodeDataToWindow(PNODE);
else { else {
// get back its' dimensions from position and size // get back its' dimensions from position and size
pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition; *pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition;
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; *pWindow->m_vRealSize = pWindow->m_vLastFloatingSize;
pWindow->unsetWindowData(PRIORITY_LAYOUT); pWindow->unsetWindowData(PRIORITY_LAYOUT);
pWindow->updateWindowData(); pWindow->updateWindowData();
@ -765,8 +765,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFu
} else { } else {
// apply new pos and size being monitors' box // apply new pos and size being monitors' box
if (EFFECTIVE_MODE == FSMODE_FULLSCREEN) { if (EFFECTIVE_MODE == FSMODE_FULLSCREEN) {
pWindow->m_vRealPosition = PMONITOR->vecPosition; *pWindow->m_vRealPosition = PMONITOR->vecPosition;
pWindow->m_vRealSize = PMONITOR->vecSize; *pWindow->m_vRealSize = PMONITOR->vecSize;
} else { } else {
// This is a massive hack. // This is a massive hack.
// We make a fake "only" node and apply // We make a fake "only" node and apply

View file

@ -106,7 +106,7 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) {
if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) { if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
const auto PWINDOWSURFACE = pWindow->m_pWLSurface->resource(); const auto PWINDOWSURFACE = pWindow->m_pWLSurface->resource();
pWindow->m_vRealSize = PWINDOWSURFACE->current.size; *pWindow->m_vRealSize = PWINDOWSURFACE->current.size;
if ((desiredGeometry.width <= 1 || desiredGeometry.height <= 1) && pWindow->m_bIsX11 && if ((desiredGeometry.width <= 1 || desiredGeometry.height <= 1) && pWindow->m_bIsX11 &&
pWindow->isX11OverrideRedirect()) { // XDG windows should be fine. TODO: check for weird atoms? pWindow->isX11OverrideRedirect()) { // XDG windows should be fine. TODO: check for weird atoms?
@ -115,23 +115,23 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) {
} }
// reject any windows with size <= 5x5 // reject any windows with size <= 5x5
if (pWindow->m_vRealSize.goal().x <= 5 || pWindow->m_vRealSize.goal().y <= 5) if (pWindow->m_vRealSize->goal().x <= 5 || pWindow->m_vRealSize->goal().y <= 5)
pWindow->m_vRealSize = PMONITOR->vecSize / 2.f; *pWindow->m_vRealSize = PMONITOR->vecSize / 2.f;
if (pWindow->m_bIsX11 && pWindow->isX11OverrideRedirect()) { if (pWindow->m_bIsX11 && pWindow->isX11OverrideRedirect()) {
if (pWindow->m_pXWaylandSurface->geometry.x != 0 && pWindow->m_pXWaylandSurface->geometry.y != 0) if (pWindow->m_pXWaylandSurface->geometry.x != 0 && pWindow->m_pXWaylandSurface->geometry.y != 0)
pWindow->m_vRealPosition = g_pXWaylandManager->xwaylandToWaylandCoords(pWindow->m_pXWaylandSurface->geometry.pos()); *pWindow->m_vRealPosition = g_pXWaylandManager->xwaylandToWaylandCoords(pWindow->m_pXWaylandSurface->geometry.pos());
else else
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goal().x) / 2.f, *pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize->goal().x) / 2.f,
PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goal().y) / 2.f); PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize->goal().y) / 2.f);
} else { } else {
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goal().x) / 2.f, *pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize->goal().x) / 2.f,
PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goal().y) / 2.f); PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize->goal().y) / 2.f);
} }
} else { } else {
// we respect the size. // we respect the size.
pWindow->m_vRealSize = Vector2D(desiredGeometry.width, desiredGeometry.height); *pWindow->m_vRealSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
// check if it's on the correct monitor! // check if it's on the correct monitor!
Vector2D middlePoint = Vector2D(desiredGeometry.x, desiredGeometry.y) + Vector2D(desiredGeometry.width, desiredGeometry.height) / 2.f; Vector2D middlePoint = Vector2D(desiredGeometry.x, desiredGeometry.y) + Vector2D(desiredGeometry.width, desiredGeometry.height) / 2.f;
@ -150,35 +150,35 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) {
if ((desiredGeometry.x == 0 && desiredGeometry.y == 0) || !visible || !pWindow->m_bIsX11) { if ((desiredGeometry.x == 0 && desiredGeometry.y == 0) || !visible || !pWindow->m_bIsX11) {
// if the pos isn't set, fall back to the center placement if it's not a child, otherwise middle of parent if available // if the pos isn't set, fall back to the center placement if it's not a child, otherwise middle of parent if available
if (!pWindow->m_bIsX11 && pWindow->m_pXDGSurface->toplevel->parent && validMapped(pWindow->m_pXDGSurface->toplevel->parent->window)) if (!pWindow->m_bIsX11 && pWindow->m_pXDGSurface->toplevel->parent && validMapped(pWindow->m_pXDGSurface->toplevel->parent->window))
pWindow->m_vRealPosition = pWindow->m_pXDGSurface->toplevel->parent->window->m_vRealPosition.goal() + *pWindow->m_vRealPosition = pWindow->m_pXDGSurface->toplevel->parent->window->m_vRealPosition->goal() +
pWindow->m_pXDGSurface->toplevel->parent->window->m_vRealSize.goal() / 2.F - desiredGeometry.size() / 2.F; pWindow->m_pXDGSurface->toplevel->parent->window->m_vRealSize->goal() / 2.F - desiredGeometry.size() / 2.F;
else else
pWindow->m_vRealPosition = PMONITOR->vecPosition + PMONITOR->vecSize / 2.F - desiredGeometry.size() / 2.F; *pWindow->m_vRealPosition = PMONITOR->vecPosition + PMONITOR->vecSize / 2.F - desiredGeometry.size() / 2.F;
} else { } else {
// if it is, we respect where it wants to put itself, but apply monitor offset if outside // if it is, we respect where it wants to put itself, but apply monitor offset if outside
// most of these are popups // most of these are popups
if (const auto POPENMON = g_pCompositor->getMonitorFromVector(middlePoint); POPENMON->ID != PMONITOR->ID) if (const auto POPENMON = g_pCompositor->getMonitorFromVector(middlePoint); POPENMON->ID != PMONITOR->ID)
pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y) - POPENMON->vecPosition + PMONITOR->vecPosition; *pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y) - POPENMON->vecPosition + PMONITOR->vecPosition;
else else
pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y); *pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y);
} }
} }
if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11) if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11)
pWindow->m_vRealSize = pWindow->m_vRealSize.goal() / PMONITOR->scale; *pWindow->m_vRealSize = pWindow->m_vRealSize->goal() / PMONITOR->scale;
if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->isX11OverrideRedirect())) { if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->isX11OverrideRedirect())) {
pWindow->m_vRealPosition.warp(); pWindow->m_vRealPosition->warp();
pWindow->m_vRealSize.warp(); pWindow->m_vRealSize->warp();
} }
if (!pWindow->isX11OverrideRedirect()) { if (!pWindow->isX11OverrideRedirect()) {
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal()); g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize->goal());
g_pCompositor->changeWindowZOrder(pWindow, true); g_pCompositor->changeWindowZOrder(pWindow, true);
} else { } else {
pWindow->m_vPendingReportedSize = pWindow->m_vRealSize.goal(); pWindow->m_vPendingReportedSize = pWindow->m_vRealSize->goal();
pWindow->m_vReportedSize = pWindow->m_vPendingReportedSize; pWindow->m_vReportedSize = pWindow->m_vPendingReportedSize;
} }
} }
@ -250,18 +250,18 @@ void IHyprLayout::onBeginDragWindow() {
if (!DRAGGINGWINDOW->m_bIsFloating) { if (!DRAGGINGWINDOW->m_bIsFloating) {
if (g_pInputManager->dragMode == MBIND_MOVE) { if (g_pInputManager->dragMode == MBIND_MOVE) {
DRAGGINGWINDOW->m_vLastFloatingSize = (DRAGGINGWINDOW->m_vRealSize.goal() * 0.8489).clamp(Vector2D{5, 5}, Vector2D{}).floor(); DRAGGINGWINDOW->m_vLastFloatingSize = (DRAGGINGWINDOW->m_vRealSize->goal() * 0.8489).clamp(Vector2D{5, 5}, Vector2D{}).floor();
changeWindowFloatingMode(DRAGGINGWINDOW); changeWindowFloatingMode(DRAGGINGWINDOW);
DRAGGINGWINDOW->m_bIsFloating = true; DRAGGINGWINDOW->m_bIsFloating = true;
DRAGGINGWINDOW->m_bDraggingTiled = true; DRAGGINGWINDOW->m_bDraggingTiled = true;
DRAGGINGWINDOW->m_vRealPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_vRealSize.goal() / 2.f; *DRAGGINGWINDOW->m_vRealPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_vRealSize->goal() / 2.f;
} }
} }
m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal(); m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal();
m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.goal(); m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition->goal();
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.goal(); m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize->goal();
m_vLastDragXY = m_vBeginDragXY; m_vLastDragXY = m_vBeginDragXY;
// get the grab corner // get the grab corner
@ -349,8 +349,8 @@ void IHyprLayout::onEndDragWindow() {
PHLWINDOW next = DRAGGINGWINDOW->m_sGroupData.pNextWindow.lock(); PHLWINDOW next = DRAGGINGWINDOW->m_sGroupData.pNextWindow.lock();
while (next != DRAGGINGWINDOW) { while (next != DRAGGINGWINDOW) {
next->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of group members next->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of group members
next->m_vRealSize = pWindow->m_vRealSize.goal(); // match the size of group members *next->m_vRealSize = pWindow->m_vRealSize->goal(); // match the size of group members
next->m_vRealPosition = pWindow->m_vRealPosition.goal(); // match the position of group members *next->m_vRealPosition = pWindow->m_vRealPosition->goal(); // match the position of group members
next = next->m_sGroupData.pNextWindow.lock(); next = next->m_sGroupData.pNextWindow.lock();
} }
} }
@ -360,7 +360,7 @@ void IHyprLayout::onEndDragWindow() {
DRAGGINGWINDOW->m_bDraggingTiled = false; DRAGGINGWINDOW->m_bDraggingTiled = false;
if (pWindow->m_bIsFloating) if (pWindow->m_bIsFloating)
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, pWindow->m_vRealSize.goal()); // match the size of the window g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, pWindow->m_vRealSize->goal()); // match the size of the window
static auto USECURRPOS = CConfigValue<Hyprlang::INT>("group:insert_after_current"); static auto USECURRPOS = CConfigValue<Hyprlang::INT>("group:insert_after_current");
(*USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW); (*USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW);
@ -423,9 +423,11 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA
if (*SNAPWINDOWGAP) { if (*SNAPWINDOWGAP) {
const double GAPSIZE = *SNAPWINDOWGAP; const double GAPSIZE = *SNAPWINDOWGAP;
const auto WSID = DRAGGINGWINDOW->workspaceID(); const auto WSID = DRAGGINGWINDOW->workspaceID();
const bool HASFULLSCREEN = DRAGGINGWINDOW->m_pWorkspace && DRAGGINGWINDOW->m_pWorkspace->m_bHasFullscreenWindow;
for (auto& other : g_pCompositor->m_vWindows) { for (auto& other : g_pCompositor->m_vWindows) {
if (other == DRAGGINGWINDOW || other->workspaceID() != WSID || !other->m_bIsMapped || other->m_bFadingOut || other->isX11OverrideRedirect()) if ((HASFULLSCREEN && !other->m_bCreatedOverFullscreen) || other == DRAGGINGWINDOW || other->workspaceID() != WSID || !other->m_bIsMapped || other->m_bFadingOut ||
other->isX11OverrideRedirect())
continue; continue;
const int OTHERBORDERSIZE = other->getRealBorderSize(); const int OTHERBORDERSIZE = other->getRealBorderSize();
@ -591,7 +593,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
if (g_pInputManager->dragMode == MBIND_MOVE) { if (g_pInputManager->dragMode == MBIND_MOVE) {
Vector2D newPos = m_vBeginDragPositionXY + DELTA; Vector2D newPos = m_vBeginDragPositionXY + DELTA;
Vector2D newSize = DRAGGINGWINDOW->m_vRealSize.goal(); Vector2D newSize = DRAGGINGWINDOW->m_vRealSize->goal();
if (*SNAPENABLED && !DRAGGINGWINDOW->m_bDraggingTiled) if (*SNAPENABLED && !DRAGGINGWINDOW->m_bDraggingTiled)
performSnap(newPos, newSize, DRAGGINGWINDOW, MBIND_MOVE, -1, m_vBeginDragSizeXY); performSnap(newPos, newSize, DRAGGINGWINDOW, MBIND_MOVE, -1, m_vBeginDragSizeXY);
@ -600,11 +602,11 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
wb.round(); wb.round();
if (*PANIMATEMOUSE) if (*PANIMATEMOUSE)
DRAGGINGWINDOW->m_vRealPosition = wb.pos(); *DRAGGINGWINDOW->m_vRealPosition = wb.pos();
else else
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos()); DRAGGINGWINDOW->m_vRealPosition->setValueAndWarp(wb.pos());
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goal()); g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize->goal());
} else if (g_pInputManager->dragMode == MBIND_RESIZE || g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) { } else if (g_pInputManager->dragMode == MBIND_RESIZE || g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) {
if (DRAGGINGWINDOW->m_bIsFloating) { if (DRAGGINGWINDOW->m_bIsFloating) {
@ -669,21 +671,21 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
wb.round(); wb.round();
if (*PANIMATE) { if (*PANIMATE) {
DRAGGINGWINDOW->m_vRealSize = wb.size(); *DRAGGINGWINDOW->m_vRealSize = wb.size();
DRAGGINGWINDOW->m_vRealPosition = wb.pos(); *DRAGGINGWINDOW->m_vRealPosition = wb.pos();
} else { } else {
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(wb.size()); DRAGGINGWINDOW->m_vRealSize->setValueAndWarp(wb.size());
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos()); DRAGGINGWINDOW->m_vRealPosition->setValueAndWarp(wb.pos());
} }
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goal()); g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize->goal());
} else { } else {
resizeActiveWindow(TICKDELTA, m_eGrabbedCorner, DRAGGINGWINDOW); resizeActiveWindow(TICKDELTA, m_eGrabbedCorner, DRAGGINGWINDOW);
} }
} }
// get middle point // get middle point
Vector2D middle = DRAGGINGWINDOW->m_vRealPosition.value() + DRAGGINGWINDOW->m_vRealSize.value() / 2.f; Vector2D middle = DRAGGINGWINDOW->m_vRealPosition->value() + DRAGGINGWINDOW->m_vRealSize->value() / 2.f;
// and check its monitor // and check its monitor
const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle); const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle);
@ -717,7 +719,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) {
EMIT_HOOK_EVENT("changeFloatingMode", pWindow); EMIT_HOOK_EVENT("changeFloatingMode", pWindow);
if (!TILED) { if (!TILED) {
const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.value() + pWindow->m_vRealSize.value() / 2.f); const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition->value() + pWindow->m_vRealSize->value() / 2.f);
pWindow->m_pMonitor = PNEWMON; pWindow->m_pMonitor = PNEWMON;
pWindow->moveToWorkspace(PNEWMON->activeSpecialWorkspace ? PNEWMON->activeSpecialWorkspace : PNEWMON->activeWorkspace); pWindow->moveToWorkspace(PNEWMON->activeSpecialWorkspace ? PNEWMON->activeSpecialWorkspace : PNEWMON->activeWorkspace);
pWindow->updateGroupOutputs(); pWindow->updateGroupOutputs();
@ -728,12 +730,12 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) {
g_pCompositor->setWindowFullscreenInternal(PWORKSPACE->getFullscreenWindow(), FSMODE_NONE); g_pCompositor->setWindowFullscreenInternal(PWORKSPACE->getFullscreenWindow(), FSMODE_NONE);
// save real pos cuz the func applies the default 5,5 mid // save real pos cuz the func applies the default 5,5 mid
const auto PSAVEDPOS = pWindow->m_vRealPosition.goal(); const auto PSAVEDPOS = pWindow->m_vRealPosition->goal();
const auto PSAVEDSIZE = pWindow->m_vRealSize.goal(); const auto PSAVEDSIZE = pWindow->m_vRealSize->goal();
// if the window is pseudo, update its size // if the window is pseudo, update its size
if (!pWindow->m_bDraggingTiled) if (!pWindow->m_bDraggingTiled)
pWindow->m_vPseudoSize = pWindow->m_vRealSize.goal(); pWindow->m_vPseudoSize = pWindow->m_vRealSize->goal();
pWindow->m_vLastFloatingSize = PSAVEDSIZE; pWindow->m_vLastFloatingSize = PSAVEDSIZE;
@ -742,8 +744,8 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) {
onWindowCreatedTiling(pWindow); onWindowCreatedTiling(pWindow);
pWindow->m_vRealPosition.setValue(PSAVEDPOS); pWindow->m_vRealPosition->setValue(PSAVEDPOS);
pWindow->m_vRealSize.setValue(PSAVEDSIZE); pWindow->m_vRealSize->setValue(PSAVEDSIZE);
// fix pseudo leaving artifacts // fix pseudo leaving artifacts
g_pHyprRenderer->damageMonitor(pWindow->m_pMonitor.lock()); g_pHyprRenderer->damageMonitor(pWindow->m_pMonitor.lock());
@ -755,16 +757,16 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) {
g_pCompositor->changeWindowZOrder(pWindow, true); g_pCompositor->changeWindowZOrder(pWindow, true);
CBox wb = {pWindow->m_vRealPosition.goal() + (pWindow->m_vRealSize.goal() - pWindow->m_vLastFloatingSize) / 2.f, pWindow->m_vLastFloatingSize}; CBox wb = {pWindow->m_vRealPosition->goal() + (pWindow->m_vRealSize->goal() - pWindow->m_vLastFloatingSize) / 2.f, pWindow->m_vLastFloatingSize};
wb.round(); wb.round();
if (!(pWindow->m_bIsFloating && pWindow->m_bIsPseudotiled) && DELTALESSTHAN(pWindow->m_vRealSize.value().x, pWindow->m_vLastFloatingSize.x, 10) && if (!(pWindow->m_bIsFloating && pWindow->m_bIsPseudotiled) && DELTALESSTHAN(pWindow->m_vRealSize->value().x, pWindow->m_vLastFloatingSize.x, 10) &&
DELTALESSTHAN(pWindow->m_vRealSize.value().y, pWindow->m_vLastFloatingSize.y, 10)) { DELTALESSTHAN(pWindow->m_vRealSize->value().y, pWindow->m_vLastFloatingSize.y, 10)) {
wb = {wb.pos() + Vector2D{10, 10}, wb.size() - Vector2D{20, 20}}; wb = {wb.pos() + Vector2D{10, 10}, wb.size() - Vector2D{20, 20}};
} }
pWindow->m_vRealPosition = wb.pos(); *pWindow->m_vRealPosition = wb.pos();
pWindow->m_vRealSize = wb.size(); *pWindow->m_vRealSize = wb.size();
pWindow->m_vSize = wb.pos(); pWindow->m_vSize = wb.pos();
pWindow->m_vPosition = wb.size(); pWindow->m_vPosition = wb.size();
@ -796,7 +798,7 @@ void IHyprLayout::moveActiveWindow(const Vector2D& delta, PHLWINDOW pWindow) {
PWINDOW->setAnimationsToMove(); PWINDOW->setAnimationsToMove();
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goal() + delta; *PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition->goal() + delta;
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
} }

View file

@ -301,8 +301,8 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
const auto PFULLWINDOW = pWorkspace->getFullscreenWindow(); const auto PFULLWINDOW = pWorkspace->getFullscreenWindow();
if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) { if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) {
PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition; *PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition;
PFULLWINDOW->m_vRealSize = PMONITOR->vecSize; *PFULLWINDOW->m_vRealSize = PMONITOR->vecSize;
} else if (pWorkspace->m_efFullscreenMode == FSMODE_MAXIMIZED) { } else if (pWorkspace->m_efFullscreenMode == FSMODE_MAXIMIZED) {
SMasterNodeData fakeNode; SMasterNodeData fakeNode;
fakeNode.pWindow = PFULLWINDOW; fakeNode.pWindow = PFULLWINDOW;
@ -328,6 +328,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
eOrientation orientation = getDynamicOrientation(pWorkspace); eOrientation orientation = getDynamicOrientation(pWorkspace);
bool centerMasterWindow = false; bool centerMasterWindow = false;
static auto SLAVECOUNTFORCENTER = CConfigValue<Hyprlang::INT>("master:slave_count_for_center_master"); static auto SLAVECOUNTFORCENTER = CConfigValue<Hyprlang::INT>("master:slave_count_for_center_master");
static auto CMSLAVESONRIGHT = CConfigValue<Hyprlang::INT>("master:center_master_slaves_on_right");
static auto PIGNORERESERVED = CConfigValue<Hyprlang::INT>("master:center_ignores_reserved"); static auto PIGNORERESERVED = CConfigValue<Hyprlang::INT>("master:center_ignores_reserved");
static auto PSMARTRESIZING = CConfigValue<Hyprlang::INT>("master:smart_resizing"); static auto PSMARTRESIZING = CConfigValue<Hyprlang::INT>("master:smart_resizing");
@ -341,7 +342,10 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
if (STACKWINDOWS >= *SLAVECOUNTFORCENTER) { if (STACKWINDOWS >= *SLAVECOUNTFORCENTER) {
centerMasterWindow = true; centerMasterWindow = true;
} else { } else {
if (*CMSLAVESONRIGHT)
orientation = ORIENTATION_LEFT; orientation = ORIENTATION_LEFT;
else
orientation = ORIENTATION_RIGHT;
} }
} }
@ -515,15 +519,20 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
float nextY = 0; float nextY = 0;
float nextYL = 0; float nextYL = 0;
float nextYR = 0; float nextYR = 0;
bool onRight = true; bool onRight = *CMSLAVESONRIGHT;
int slavesLeftL = 1 + (slavesLeft - 1) / 2;
int slavesLeftR = slavesLeft - slavesLeftL;
int slavesLeftR = 1 + (slavesLeft - 1) / 2; if (*CMSLAVESONRIGHT) {
int slavesLeftL = slavesLeft - slavesLeftR; slavesLeftR = 1 + (slavesLeft - 1) / 2;
slavesLeftL = slavesLeft - slavesLeftR;
}
const float slaveAverageHeightL = WSSIZE.y / slavesLeftL; const float slaveAverageHeightL = WSSIZE.y / slavesLeftL;
const float slaveAverageHeightR = WSSIZE.y / slavesLeftR; const float slaveAverageHeightR = WSSIZE.y / slavesLeftR;
float slaveAccumulatedHeightL = 0; float slaveAccumulatedHeightL = 0;
float slaveAccumulatedHeightR = 0; float slaveAccumulatedHeightR = 0;
if (*PSMARTRESIZING) { if (*PSMARTRESIZING) {
for (auto const& nd : m_lMasterNodesData) { for (auto const& nd : m_lMasterNodesData) {
if (nd.workspaceID != pWorkspace->m_iID || nd.isMaster) if (nd.workspaceID != pWorkspace->m_iID || nd.isMaster)
@ -536,7 +545,8 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
} }
onRight = !onRight; onRight = !onRight;
} }
onRight = true;
onRight = *CMSLAVESONRIGHT;
} }
for (auto& nd : m_lMasterNodesData) { for (auto& nd : m_lMasterNodesData) {
@ -662,16 +672,16 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR}; CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR};
wb.round(); // avoid rounding mess wb.round(); // avoid rounding mess
PWINDOW->m_vRealPosition = wb.pos(); *PWINDOW->m_vRealPosition = wb.pos();
PWINDOW->m_vRealSize = wb.size(); *PWINDOW->m_vRealSize = wb.size();
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size()); g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
} else { } else {
CBox wb = {calcPos, calcSize}; CBox wb = {calcPos, calcSize};
wb.round(); // avoid rounding mess wb.round(); // avoid rounding mess
PWINDOW->m_vRealPosition = wb.pos(); *PWINDOW->m_vRealPosition = wb.pos();
PWINDOW->m_vRealSize = wb.size(); *PWINDOW->m_vRealSize = wb.size();
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size()); g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
} }
@ -679,8 +689,8 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
if (m_bForceWarps && !*PANIMATE) { if (m_bForceWarps && !*PANIMATE) {
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
PWINDOW->m_vRealPosition.warp(); PWINDOW->m_vRealPosition->warp();
PWINDOW->m_vRealSize.warp(); PWINDOW->m_vRealSize->warp();
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
} }
@ -701,8 +711,8 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne
const auto PNODE = getNodeFromWindow(PWINDOW); const auto PNODE = getNodeFromWindow(PWINDOW);
if (!PNODE) { if (!PNODE) {
PWINDOW->m_vRealSize = *PWINDOW->m_vRealSize =
(PWINDOW->m_vRealSize.goal() + pixResize) (PWINDOW->m_vRealSize->goal() + pixResize)
.clamp(PWINDOW->m_sWindowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_sWindowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY})); .clamp(PWINDOW->m_sWindowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_sWindowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY}));
PWINDOW->updateWindowDecos(); PWINDOW->updateWindowDecos();
return; return;
@ -842,10 +852,10 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFul
// save position and size if floating // save position and size if floating
if (pWindow->m_bIsFloating && CURRENT_EFFECTIVE_MODE == FSMODE_NONE) { if (pWindow->m_bIsFloating && CURRENT_EFFECTIVE_MODE == FSMODE_NONE) {
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goal(); pWindow->m_vLastFloatingSize = pWindow->m_vRealSize->goal();
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goal(); pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition->goal();
pWindow->m_vPosition = pWindow->m_vRealPosition.goal(); pWindow->m_vPosition = pWindow->m_vRealPosition->goal();
pWindow->m_vSize = pWindow->m_vRealSize.goal(); pWindow->m_vSize = pWindow->m_vRealSize->goal();
} }
if (EFFECTIVE_MODE == FSMODE_NONE) { if (EFFECTIVE_MODE == FSMODE_NONE) {
@ -855,8 +865,8 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFul
applyNodeDataToWindow(PNODE); applyNodeDataToWindow(PNODE);
else { else {
// get back its' dimensions from position and size // get back its' dimensions from position and size
pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition; *pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition;
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; *pWindow->m_vRealSize = pWindow->m_vLastFloatingSize;
pWindow->unsetWindowData(PRIORITY_LAYOUT); pWindow->unsetWindowData(PRIORITY_LAYOUT);
pWindow->updateWindowData(); pWindow->updateWindowData();
@ -864,8 +874,8 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFul
} else { } else {
// apply new pos and size being monitors' box // apply new pos and size being monitors' box
if (EFFECTIVE_MODE == FSMODE_FULLSCREEN) { if (EFFECTIVE_MODE == FSMODE_FULLSCREEN) {
pWindow->m_vRealPosition = PMONITOR->vecPosition; *pWindow->m_vRealPosition = PMONITOR->vecPosition;
pWindow->m_vRealSize = PMONITOR->vecSize; *pWindow->m_vRealSize = PMONITOR->vecSize;
} else { } else {
// This is a massive hack. // This is a massive hack.
// We make a fake "only" node and apply // We make a fake "only" node and apply

View file

@ -1,6 +1,9 @@
#include "AnimationManager.hpp" #include "AnimationManager.hpp"
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "HookSystemManager.hpp" #include "HookSystemManager.hpp"
#include "config/ConfigManager.hpp"
#include "desktop/DesktopTypes.hpp"
#include "helpers/AnimatedVariable.hpp"
#include "macros.hpp" #include "macros.hpp"
#include "../config/ConfigValue.hpp" #include "../config/ConfigValue.hpp"
#include "../desktop/Window.hpp" #include "../desktop/Window.hpp"
@ -9,6 +12,8 @@
#include "../helpers/varlist/VarList.hpp" #include "../helpers/varlist/VarList.hpp"
#include <hyprgraphics/color/Color.hpp> #include <hyprgraphics/color/Color.hpp>
#include <hyprutils/animation/AnimatedVariable.hpp>
#include <hyprutils/animation/AnimationManager.hpp>
static int wlTick(SP<CEventLoopTimer> self, void* data) { static int wlTick(SP<CEventLoopTimer> self, void* data) {
if (g_pAnimationManager) if (g_pAnimationManager)
@ -26,95 +31,76 @@ static int wlTick(SP<CEventLoopTimer> self, void* data) {
return 0; return 0;
} }
CAnimationManager::CAnimationManager() { CHyprAnimationManager::CHyprAnimationManager() {
std::vector<Vector2D> points = {Vector2D(0.0, 0.75), Vector2D(0.15, 1.0)};
m_mBezierCurves["default"].setup(&points);
points = {Vector2D(0.0, 0.0), Vector2D(1.0, 1.0)};
m_mBezierCurves["linear"].setup(&points);
m_pAnimationTimer = SP<CEventLoopTimer>(new CEventLoopTimer(std::chrono::microseconds(500), wlTick, nullptr)); m_pAnimationTimer = SP<CEventLoopTimer>(new CEventLoopTimer(std::chrono::microseconds(500), wlTick, nullptr));
g_pEventLoopManager->addTimer(m_pAnimationTimer); g_pEventLoopManager->addTimer(m_pAnimationTimer);
addBezierWithName("linear", Vector2D(0.0, 0.0), Vector2D(1.0, 1.0));
} }
void CAnimationManager::removeAllBeziers() { template <Animable VarType>
m_mBezierCurves.clear(); void updateVariable(CAnimatedVariable<VarType>& av, const float POINTY, bool warp = false) {
if (warp || av.value() == av.goal()) {
// add the default one av.warp();
std::vector<Vector2D> points = {Vector2D(0.0, 0.75), Vector2D(0.15, 1.0)};
m_mBezierCurves["default"].setup(&points);
points = {Vector2D(0.0, 0.0), Vector2D(1.0, 1.0)};
m_mBezierCurves["linear"].setup(&points);
}
void CAnimationManager::addBezierWithName(std::string name, const Vector2D& p1, const Vector2D& p2) {
std::vector points = {p1, p2};
m_mBezierCurves[name].setup(&points);
}
void CAnimationManager::onTicked() {
m_bTickScheduled = false;
}
void CAnimationManager::tick() {
static std::chrono::time_point lastTick = std::chrono::high_resolution_clock::now();
m_fLastTickTime = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - lastTick).count() / 1000.0;
lastTick = std::chrono::high_resolution_clock::now();
if (m_vActiveAnimatedVariables.empty())
return; return;
bool animGlobalDisabled = false;
static auto PANIMENABLED = CConfigValue<Hyprlang::INT>("animations:enabled");
if (!*PANIMENABLED)
animGlobalDisabled = true;
static auto* const PSHADOWSENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:shadow:enabled");
const auto DEFAULTBEZIER = m_mBezierCurves.find("default");
std::vector<CBaseAnimatedVariable*> animationEndedVars;
for (auto const& av : m_vActiveAnimatedVariables) {
if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW && !*PSHADOWSENABLED) {
av->warp(false);
animationEndedVars.push_back(av);
continue;
} }
// get the spent % (0 - 1) const auto DELTA = av.goal() - av.begun();
const float SPENT = av->getPercent(); av.value() = av.begun() + DELTA * POINTY;
}
// window stuff void updateColorVariable(CAnimatedVariable<CHyprColor>& av, const float POINTY, bool warp) {
PHLWINDOW PWINDOW = av->m_pWindow.lock(); if (warp || av.value() == av.goal()) {
PHLWORKSPACE PWORKSPACE = av->m_pWorkspace.lock(); av.warp();
PHLLS PLAYER = av->m_pLayer.lock(); return;
}
// convert both to OkLab, then lerp that, and convert back.
// This is not as fast as just lerping rgb, but it's WAY more precise...
// Use the CHyprColor cache for OkLab
const auto& L1 = av.begun().asOkLab();
const auto& L2 = av.goal().asOkLab();
static const auto lerp = [](const float one, const float two, const float progress) -> float { return one + (two - one) * progress; };
const Hyprgraphics::CColor lerped = Hyprgraphics::CColor::SOkLab{
.l = lerp(L1.l, L2.l, POINTY),
.a = lerp(L1.a, L2.a, POINTY),
.b = lerp(L1.b, L2.b, POINTY),
};
av.value() = {lerped, lerp(av.begun().a, av.goal().a, POINTY)};
}
template <Animable VarType>
static void handleUpdate(CAnimatedVariable<VarType>& av, bool warp) {
PHLWINDOW PWINDOW = av.m_Context.pWindow.lock();
PHLWORKSPACE PWORKSPACE = av.m_Context.pWorkspace.lock();
PHLLS PLAYER = av.m_Context.pLayer.lock();
PHLMONITOR PMONITOR = nullptr; PHLMONITOR PMONITOR = nullptr;
bool animationsDisabled = animGlobalDisabled; bool animationsDisabled = warp;
if (PWINDOW) { if (PWINDOW) {
if (av->m_eDamagePolicy == AVARDAMAGE_ENTIRE) { if (av.m_Context.eDamagePolicy == AVARDAMAGE_ENTIRE)
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
} else if (av->m_eDamagePolicy == AVARDAMAGE_BORDER) { else if (av.m_Context.eDamagePolicy == AVARDAMAGE_BORDER) {
const auto PDECO = PWINDOW->getDecorationByType(DECORATION_BORDER); const auto PDECO = PWINDOW->getDecorationByType(DECORATION_BORDER);
PDECO->damageEntire(); PDECO->damageEntire();
} else if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW) { } else if (av.m_Context.eDamagePolicy == AVARDAMAGE_SHADOW) {
const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW); const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW);
PDECO->damageEntire(); PDECO->damageEntire();
} }
PMONITOR = PWINDOW->m_pMonitor.lock(); PMONITOR = PWINDOW->m_pMonitor.lock();
if (!PMONITOR) if (!PMONITOR)
continue; return;
animationsDisabled = PWINDOW->m_sWindowData.noAnim.valueOr(animationsDisabled); animationsDisabled = PWINDOW->m_sWindowData.noAnim.valueOr(animationsDisabled);
} else if (PWORKSPACE) { } else if (PWORKSPACE) {
PMONITOR = PWORKSPACE->m_pMonitor.lock(); PMONITOR = PWORKSPACE->m_pMonitor.lock();
if (!PMONITOR) if (!PMONITOR)
continue; return;
// dont damage the whole monitor on workspace change, unless it's a special workspace, because dim/blur etc // dont damage the whole monitor on workspace change, unless it's a special workspace, because dim/blur etc
if (PWORKSPACE->m_bIsSpecialWorkspace) if (PWORKSPACE->m_bIsSpecialWorkspace)
@ -147,113 +133,29 @@ void CAnimationManager::tick() {
} }
} else if (PLAYER) { } else if (PLAYER) {
// "some fucking layers miss 1 pixel???" -- vaxry // "some fucking layers miss 1 pixel???" -- vaxry
CBox expandBox = CBox{PLAYER->realPosition.value(), PLAYER->realSize.value()}; CBox expandBox = CBox{PLAYER->realPosition->value(), PLAYER->realSize->value()};
expandBox.expand(5); expandBox.expand(5);
g_pHyprRenderer->damageBox(&expandBox); g_pHyprRenderer->damageBox(&expandBox);
PMONITOR = g_pCompositor->getMonitorFromVector(PLAYER->realPosition.goal() + PLAYER->realSize.goal() / 2.F); PMONITOR = g_pCompositor->getMonitorFromVector(PLAYER->realPosition->goal() + PLAYER->realSize->goal() / 2.F);
if (!PMONITOR) if (!PMONITOR)
continue; return;
animationsDisabled = animationsDisabled || PLAYER->noAnimations; animationsDisabled = animationsDisabled || PLAYER->noAnimations;
} }
const bool VISIBLE = PWINDOW && PWINDOW->m_pWorkspace ? PWINDOW->m_pWorkspace->isVisible() : true; const auto SPENT = av.getPercent();
const auto PBEZIER = g_pAnimationManager->getBezier(av.getBezierName());
const auto POINTY = PBEZIER->getYForPoint(SPENT);
const bool WARP = animationsDisabled || SPENT >= 1.f;
// beziers are with a switch unforto if constexpr (std::same_as<VarType, CHyprColor>)
// TODO: maybe do something cleaner updateColorVariable(av, POINTY, WARP);
static const auto updateVariable = [this]<Animable T>(CAnimatedVariable<T>& av, const float SPENT, const CBezierCurve& DEFAULTBEZIER, const bool DISABLED) {
// for disabled anims just warp
if (av.m_pConfig->pValues->internalEnabled == 0 || DISABLED) {
av.warp(false);
return;
}
if (SPENT >= 1.f || av.m_Begun == av.m_Goal) {
av.warp(false);
return;
}
const auto BEZIER = m_mBezierCurves.find(av.m_pConfig->pValues->internalBezier);
const auto POINTY = BEZIER != m_mBezierCurves.end() ? BEZIER->second.getYForPoint(SPENT) : DEFAULTBEZIER.getYForPoint(SPENT);
const auto DELTA = av.m_Goal - av.m_Begun;
if (BEZIER != m_mBezierCurves.end())
av.m_Value = av.m_Begun + DELTA * POINTY;
else else
av.m_Value = av.m_Begun + DELTA * POINTY; updateVariable<VarType>(av, POINTY, WARP);
};
static const auto updateColorVariable = [this](CAnimatedVariable<CHyprColor>& av, const float SPENT, const CBezierCurve& DEFAULTBEZIER, const bool DISABLED) { av.onUpdate();
// for disabled anims just warp
if (av.m_pConfig->pValues->internalEnabled == 0 || DISABLED) {
av.warp(false);
return;
}
if (SPENT >= 1.f || av.m_Begun == av.m_Goal) { switch (av.m_Context.eDamagePolicy) {
av.warp(false);
return;
}
const auto BEZIER = m_mBezierCurves.find(av.m_pConfig->pValues->internalBezier);
const auto POINTY = BEZIER != m_mBezierCurves.end() ? BEZIER->second.getYForPoint(SPENT) : DEFAULTBEZIER.getYForPoint(SPENT);
// convert both to OkLab, then lerp that, and convert back.
// This is not as fast as just lerping rgb, but it's WAY more precise...
// Use the CHyprColor cache for OkLab
const auto& L1 = av.m_Begun.asOkLab();
const auto& L2 = av.m_Goal.asOkLab();
static const auto lerp = [](const float one, const float two, const float progress) -> float { return one + (two - one) * progress; };
const Hyprgraphics::CColor lerped = Hyprgraphics::CColor::SOkLab{
.l = lerp(L1.l, L2.l, POINTY),
.a = lerp(L1.a, L2.a, POINTY),
.b = lerp(L1.b, L2.b, POINTY),
};
av.m_Value = {lerped, lerp(av.m_Begun.a, av.m_Goal.a, POINTY)};
return;
};
switch (av->m_Type) {
case AVARTYPE_FLOAT: {
auto typedAv = dynamic_cast<CAnimatedVariable<float>*>(av);
updateVariable(*typedAv, SPENT, DEFAULTBEZIER->second, animationsDisabled);
break;
}
case AVARTYPE_VECTOR: {
auto typedAv = dynamic_cast<CAnimatedVariable<Vector2D>*>(av);
updateVariable(*typedAv, SPENT, DEFAULTBEZIER->second, animationsDisabled);
break;
}
case AVARTYPE_COLOR: {
auto typedAv = dynamic_cast<CAnimatedVariable<CHyprColor>*>(av);
updateColorVariable(*typedAv, SPENT, DEFAULTBEZIER->second, animationsDisabled);
break;
}
default: UNREACHABLE();
}
// set size and pos if valid, but only if damage policy entire (dont if border for example)
if (validMapped(PWINDOW) && av->m_eDamagePolicy == AVARDAMAGE_ENTIRE && !PWINDOW->isX11OverrideRedirect())
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal());
// check if we did not finish animating. If so, trigger onAnimationEnd.
if (!av->isBeingAnimated())
animationEndedVars.push_back(av);
// lastly, handle damage, but only if whatever we are animating is visible.
if (!VISIBLE)
continue;
if (av->m_fUpdateCallback)
av->m_fUpdateCallback(av);
switch (av->m_eDamagePolicy) {
case AVARDAMAGE_ENTIRE: { case AVARDAMAGE_ENTIRE: {
if (PWINDOW) { if (PWINDOW) {
PWINDOW->updateWindowDecos(); PWINDOW->updateWindowDecos();
@ -274,7 +176,7 @@ void CAnimationManager::tick() {
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR);
// some fucking layers miss 1 pixel??? // some fucking layers miss 1 pixel???
CBox expandBox = CBox{PLAYER->realPosition.value(), PLAYER->realSize.value()}; CBox expandBox = CBox{PLAYER->realPosition->value(), PLAYER->realSize->value()};
expandBox.expand(5); expandBox.expand(5);
g_pHyprRenderer->damageBox(&expandBox); g_pHyprRenderer->damageBox(&expandBox);
} }
@ -305,45 +207,69 @@ void CAnimationManager::tick() {
// manually schedule a frame // manually schedule a frame
if (PMONITOR) if (PMONITOR)
g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_ANIMATION); g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_ANIMATION);
}
void CHyprAnimationManager::tick() {
static std::chrono::time_point lastTick = std::chrono::high_resolution_clock::now();
m_fLastTickTime = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - lastTick).count() / 1000.0;
lastTick = std::chrono::high_resolution_clock::now();
static auto PANIMENABLED = CConfigValue<Hyprlang::INT>("animations:enabled");
for (auto const& pav : m_vActiveAnimatedVariables) {
const auto PAV = pav.lock();
if (!PAV)
continue;
// for disabled anims just warp
bool warp = !*PANIMENABLED || !PAV->enabled();
switch (PAV->m_Type) {
case AVARTYPE_FLOAT: {
auto pTypedAV = dynamic_cast<CAnimatedVariable<float>*>(PAV.get());
RASSERT(pTypedAV, "Failed to upcast animated float");
handleUpdate(*pTypedAV, warp);
} break;
case AVARTYPE_VECTOR: {
auto pTypedAV = dynamic_cast<CAnimatedVariable<Vector2D>*>(PAV.get());
RASSERT(pTypedAV, "Failed to upcast animated Vector2D");
handleUpdate(*pTypedAV, warp);
} break;
case AVARTYPE_COLOR: {
auto pTypedAV = dynamic_cast<CAnimatedVariable<CHyprColor>*>(PAV.get());
RASSERT(pTypedAV, "Failed to upcast animated CHyprColor");
handleUpdate(*pTypedAV, warp);
} break;
default: UNREACHABLE();
}
} }
// do it here, because if this alters the animation vars vec we would be in trouble above. tickDone();
for (auto const& ave : animationEndedVars) {
ave->onAnimationEnd();
}
} }
bool CAnimationManager::deltaSmallToFlip(const Vector2D& a, const Vector2D& b) { void CHyprAnimationManager::scheduleTick() {
return std::abs(a.x - b.x) < 0.5f && std::abs(a.y - b.y) < 0.5f; if (m_bTickScheduled)
} return;
bool CAnimationManager::deltaSmallToFlip(const CHyprColor& a, const CHyprColor& b) { m_bTickScheduled = true;
return std::abs(a.r - b.r) < 0.5f && std::abs(a.g - b.g) < 0.5f && std::abs(a.b - b.b) < 0.5f && std::abs(a.a - b.a) < 0.5f;
}
bool CAnimationManager::deltaSmallToFlip(const float& a, const float& b) { const auto PMOSTHZ = g_pHyprRenderer->m_pMostHzMonitor;
return std::abs(a - b) < 0.5f;
}
bool CAnimationManager::deltazero(const Vector2D& a, const Vector2D& b) { if (!PMOSTHZ) {
return a.x == b.x && a.y == b.y; m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(16));
} return;
bool CAnimationManager::deltazero(const float& a, const float& b) {
return a == b;
}
bool CAnimationManager::deltazero(const CHyprColor& a, const CHyprColor& b) {
return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
}
bool CAnimationManager::bezierExists(const std::string& bezier) {
for (auto const& [bc, bz] : m_mBezierCurves) {
if (bc == bezier)
return true;
} }
return false; float refreshDelayMs = std::floor(1000.f / PMOSTHZ->refreshRate);
const float SINCEPRES = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - PMOSTHZ->lastPresentationTimer.chrono()).count() / 1000.f;
const auto TOPRES = std::clamp(refreshDelayMs - SINCEPRES, 1.1f, 1000.f); // we can't send 0, that will disarm it
m_pAnimationTimer->updateTimeout(std::chrono::milliseconds((int)std::floor(TOPRES)));
}
void CHyprAnimationManager::onTicked() {
m_bTickScheduled = false;
} }
// //
@ -351,24 +277,24 @@ bool CAnimationManager::bezierExists(const std::string& bezier) {
// //
// //
void CAnimationManager::animationPopin(PHLWINDOW pWindow, bool close, float minPerc) { void CHyprAnimationManager::animationPopin(PHLWINDOW pWindow, bool close, float minPerc) {
const auto GOALPOS = pWindow->m_vRealPosition.goal(); const auto GOALPOS = pWindow->m_vRealPosition->goal();
const auto GOALSIZE = pWindow->m_vRealSize.goal(); const auto GOALSIZE = pWindow->m_vRealSize->goal();
if (!close) { if (!close) {
pWindow->m_vRealSize.setValue((GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y})); pWindow->m_vRealSize->setValue((GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y}));
pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize.m_Value / 2.f); pWindow->m_vRealPosition->setValue(GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize->value() / 2.f);
} else { } else {
pWindow->m_vRealSize = (GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y}); *pWindow->m_vRealSize = (GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y});
pWindow->m_vRealPosition = GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize.m_Goal / 2.f; *pWindow->m_vRealPosition = GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize->goal() / 2.f;
} }
} }
void CAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, bool close) { void CHyprAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, bool close) {
pWindow->m_vRealSize.warp(false); // size we preserve in slide pWindow->m_vRealSize->warp(false); // size we preserve in slide
const auto GOALPOS = pWindow->m_vRealPosition.goal(); const auto GOALPOS = pWindow->m_vRealPosition->goal();
const auto GOALSIZE = pWindow->m_vRealSize.goal(); const auto GOALSIZE = pWindow->m_vRealSize->goal();
const auto PMONITOR = pWindow->m_pMonitor.lock(); const auto PMONITOR = pWindow->m_pMonitor.lock();
@ -388,9 +314,9 @@ void CAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, boo
posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y); posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y);
if (!close) if (!close)
pWindow->m_vRealPosition.setValue(posOffset); pWindow->m_vRealPosition->setValue(posOffset);
else else
pWindow->m_vRealPosition = posOffset; *pWindow->m_vRealPosition = posOffset;
return; return;
} }
@ -423,33 +349,33 @@ void CAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, boo
} }
if (!close) if (!close)
pWindow->m_vRealPosition.setValue(posOffset); pWindow->m_vRealPosition->setValue(posOffset);
else else
pWindow->m_vRealPosition = posOffset; *pWindow->m_vRealPosition = posOffset;
} }
void CAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) { void CHyprAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) {
if (!close) { if (!close) {
pWindow->m_vRealPosition.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsIn"); pWindow->m_vRealPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsIn"));
pWindow->m_vRealSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsIn"); pWindow->m_vRealSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsIn"));
pWindow->m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeIn"); pWindow->m_fAlpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn"));
} else { } else {
pWindow->m_vRealPosition.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsOut"); pWindow->m_vRealPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsOut"));
pWindow->m_vRealSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsOut"); pWindow->m_vRealSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsOut"));
pWindow->m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeOut"); pWindow->m_fAlpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut"));
} }
auto ANIMSTYLE = pWindow->m_vRealPosition.m_pConfig->pValues->internalStyle; std::string ANIMSTYLE = pWindow->m_vRealPosition->getStyle();
transform(ANIMSTYLE.begin(), ANIMSTYLE.end(), ANIMSTYLE.begin(), ::tolower); transform(ANIMSTYLE.begin(), ANIMSTYLE.end(), ANIMSTYLE.begin(), ::tolower);
CVarList animList(ANIMSTYLE, 0, 's'); CVarList animList(ANIMSTYLE, 0, 's');
// if the window is not being animated, that means the layout set a fixed size for it, don't animate. // if the window is not being animated, that means the layout set a fixed size for it, don't animate.
if (!pWindow->m_vRealPosition.isBeingAnimated() && !pWindow->m_vRealSize.isBeingAnimated()) if (!pWindow->m_vRealPosition->isBeingAnimated() && !pWindow->m_vRealSize->isBeingAnimated())
return; return;
// if the animation is disabled and we are leaving, ignore the anim to prevent the snapshot being fucked // if the animation is disabled and we are leaving, ignore the anim to prevent the snapshot being fucked
if (!pWindow->m_vRealPosition.m_pConfig->pValues->internalEnabled) if (!pWindow->m_vRealPosition->enabled())
return; return;
if (pWindow->m_sWindowData.animationStyle.hasValue()) { if (pWindow->m_sWindowData.animationStyle.hasValue()) {
@ -494,7 +420,7 @@ void CAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) {
} }
} }
std::string CAnimationManager::styleValidInConfigVar(const std::string& config, const std::string& style) { std::string CHyprAnimationManager::styleValidInConfigVar(const std::string& config, const std::string& style) {
if (config.starts_with("window")) { if (config.starts_with("window")) {
if (style.starts_with("slide")) if (style.starts_with("slide"))
return ""; return "";
@ -568,39 +494,3 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config,
return ""; return "";
} }
CBezierCurve* CAnimationManager::getBezier(const std::string& name) {
const auto BEZIER = std::find_if(m_mBezierCurves.begin(), m_mBezierCurves.end(), [&](const auto& other) { return other.first == name; });
return BEZIER == m_mBezierCurves.end() ? &m_mBezierCurves["default"] : &BEZIER->second;
}
std::unordered_map<std::string, CBezierCurve> CAnimationManager::getAllBeziers() {
return m_mBezierCurves;
}
bool CAnimationManager::shouldTickForNext() {
return !m_vActiveAnimatedVariables.empty();
}
void CAnimationManager::scheduleTick() {
if (m_bTickScheduled)
return;
m_bTickScheduled = true;
const auto PMOSTHZ = g_pHyprRenderer->m_pMostHzMonitor;
if (!PMOSTHZ) {
m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(16));
return;
}
float refreshDelayMs = std::floor(1000.f / PMOSTHZ->refreshRate);
const float SINCEPRES = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - PMOSTHZ->lastPresentationTimer.chrono()).count() / 1000.f;
const auto TOPRES = std::clamp(refreshDelayMs - SINCEPRES, 1.1f, 1000.f); // we can't send 0, that will disarm it
m_pAnimationTimer->updateTimeout(std::chrono::milliseconds((int)std::floor(TOPRES)));
}

View file

@ -1,52 +1,59 @@
#pragma once #pragma once
#include <hyprutils/animation/AnimationManager.hpp>
#include <hyprutils/animation/AnimatedVariable.hpp>
#include "../defines.hpp" #include "../defines.hpp"
#include <list>
#include <unordered_map>
#include "../helpers/AnimatedVariable.hpp" #include "../helpers/AnimatedVariable.hpp"
#include "../helpers/BezierCurve.hpp" #include "../desktop/DesktopTypes.hpp"
#include "../helpers/Timer.hpp"
#include "eventLoop/EventLoopTimer.hpp" #include "eventLoop/EventLoopTimer.hpp"
class CWindow; class CHyprAnimationManager : public Hyprutils::Animation::CAnimationManager {
class CAnimationManager {
public: public:
CAnimationManager(); CHyprAnimationManager();
void tick(); void tick();
bool shouldTickForNext(); virtual void scheduleTick();
void onTicked(); virtual void onTicked();
void scheduleTick();
void addBezierWithName(std::string, const Vector2D&, const Vector2D&); using SAnimationPropertyConfig = Hyprutils::Animation::SAnimationPropertyConfig;
void removeAllBeziers(); template <Animable VarType>
void createAnimation(const VarType& v, PHLANIMVAR<VarType>& pav, SP<SAnimationPropertyConfig> pConfig, eAVarDamagePolicy policy) {
constexpr const eAnimatedVarType EAVTYPE = typeToeAnimatedVarType<VarType>;
const auto PAV = makeShared<CAnimatedVariable<VarType>>();
PAV->create(EAVTYPE, static_cast<Hyprutils::Animation::CAnimationManager*>(this), PAV, v);
PAV->setConfig(pConfig);
PAV->m_Context.eDamagePolicy = policy;
pav = std::move(PAV);
}
template <Animable VarType>
void createAnimation(const VarType& v, PHLANIMVAR<VarType>& pav, SP<SAnimationPropertyConfig> pConfig, PHLWINDOW pWindow, eAVarDamagePolicy policy) {
createAnimation(v, pav, pConfig, policy);
pav->m_Context.pWindow = pWindow;
}
template <Animable VarType>
void createAnimation(const VarType& v, PHLANIMVAR<VarType>& pav, SP<SAnimationPropertyConfig> pConfig, PHLWORKSPACE pWorkspace, eAVarDamagePolicy policy) {
createAnimation(v, pav, pConfig, policy);
pav->m_Context.pWorkspace = pWorkspace;
}
template <Animable VarType>
void createAnimation(const VarType& v, PHLANIMVAR<VarType>& pav, SP<SAnimationPropertyConfig> pConfig, PHLLS pLayer, eAVarDamagePolicy policy) {
createAnimation(v, pav, pConfig, policy);
pav->m_Context.pLayer = pLayer;
}
void onWindowPostCreateClose(PHLWINDOW, bool close = false); void onWindowPostCreateClose(PHLWINDOW, bool close = false);
bool bezierExists(const std::string&);
CBezierCurve* getBezier(const std::string&);
std::string styleValidInConfigVar(const std::string&, const std::string&); std::string styleValidInConfigVar(const std::string&, const std::string&);
std::unordered_map<std::string, CBezierCurve> getAllBeziers();
std::vector<CBaseAnimatedVariable*> m_vAnimatedVariables;
std::vector<CBaseAnimatedVariable*> m_vActiveAnimatedVariables;
SP<CEventLoopTimer> m_pAnimationTimer; SP<CEventLoopTimer> m_pAnimationTimer;
float m_fLastTickTime; // in ms float m_fLastTickTime; // in ms
private: private:
bool deltaSmallToFlip(const Vector2D& a, const Vector2D& b);
bool deltaSmallToFlip(const CHyprColor& a, const CHyprColor& b);
bool deltaSmallToFlip(const float& a, const float& b);
bool deltazero(const Vector2D& a, const Vector2D& b);
bool deltazero(const CHyprColor& a, const CHyprColor& b);
bool deltazero(const float& a, const float& b);
std::unordered_map<std::string, CBezierCurve> m_mBezierCurves;
bool m_bTickScheduled = false; bool m_bTickScheduled = false;
// Anim stuff // Anim stuff
@ -54,4 +61,4 @@ class CAnimationManager {
void animationSlide(PHLWINDOW, std::string force = "", bool close = false); void animationSlide(PHLWINDOW, std::string force = "", bool close = false);
}; };
inline std::unique_ptr<CAnimationManager> g_pAnimationManager; inline std::unique_ptr<CHyprAnimationManager> g_pAnimationManager;

View file

@ -12,6 +12,7 @@
#include "eventLoop/EventLoopManager.hpp" #include "eventLoop/EventLoopManager.hpp"
#include "debug/Log.hpp" #include "debug/Log.hpp"
#include "helpers/varlist/VarList.hpp" #include "helpers/varlist/VarList.hpp"
#include "../helpers/signal/Signal.hpp"
#include <optional> #include <optional>
#include <iterator> #include <iterator>
@ -63,8 +64,12 @@ CKeybindManager::CKeybindManager() {
m_mDispatchers["exec"] = spawn; m_mDispatchers["exec"] = spawn;
m_mDispatchers["execr"] = spawnRaw; m_mDispatchers["execr"] = spawnRaw;
m_mDispatchers["killactive"] = killActive; m_mDispatchers["killactive"] = closeActive;
m_mDispatchers["closewindow"] = kill; m_mDispatchers["forcekillactive"] = killActive;
m_mDispatchers["closewindow"] = closeWindow;
m_mDispatchers["killwindow"] = killWindow;
m_mDispatchers["signal"] = signalActive;
m_mDispatchers["signalwindow"] = signalWindow;
m_mDispatchers["togglefloating"] = toggleActiveFloating; m_mDispatchers["togglefloating"] = toggleActiveFloating;
m_mDispatchers["setfloating"] = setActiveFloating; m_mDispatchers["setfloating"] = setActiveFloating;
m_mDispatchers["settiled"] = setActiveTiled; m_mDispatchers["settiled"] = setActiveTiled;
@ -377,8 +382,8 @@ void CKeybindManager::switchToWindow(PHLWINDOW PWINDOWTOCHANGETO) {
g_pCompositor->setWindowFullscreenInternal(PWINDOWTOCHANGETO, MODE); g_pCompositor->setWindowFullscreenInternal(PWINDOWTOCHANGETO, MODE);
// warp the position + size animation, otherwise it looks weird. // warp the position + size animation, otherwise it looks weird.
PWINDOWTOCHANGETO->m_vRealPosition.warp(); PWINDOWTOCHANGETO->m_vRealPosition->warp();
PWINDOWTOCHANGETO->m_vRealSize.warp(); PWINDOWTOCHANGETO->m_vRealSize->warp();
} else { } else {
updateRelativeCursorCoords(); updateRelativeCursorCoords();
g_pCompositor->focusWindow(PWINDOWTOCHANGETO); g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
@ -978,17 +983,23 @@ uint64_t CKeybindManager::spawnRawProc(std::string args, PHLWORKSPACE pInitialWo
} }
SDispatchResult CKeybindManager::killActive(std::string args) { SDispatchResult CKeybindManager::killActive(std::string args) {
kill(g_pCompositor->m_pLastWindow.lock()->getPID(), SIGKILL);
return {};
}
SDispatchResult CKeybindManager::closeActive(std::string args) {
g_pCompositor->closeWindow(g_pCompositor->m_pLastWindow.lock()); g_pCompositor->closeWindow(g_pCompositor->m_pLastWindow.lock());
return {}; return {};
} }
SDispatchResult CKeybindManager::kill(std::string args) { SDispatchResult CKeybindManager::closeWindow(std::string args) {
const auto PWINDOW = g_pCompositor->getWindowByRegex(args); const auto PWINDOW = g_pCompositor->getWindowByRegex(args);
if (!PWINDOW) { if (!PWINDOW) {
Debug::log(ERR, "kill: no window found"); Debug::log(ERR, "closeWindow: no window found");
return {.success = false, .error = "kill: no window found"}; return {.success = false, .error = "closeWindow: no window found"};
} }
g_pCompositor->closeWindow(PWINDOW); g_pCompositor->closeWindow(PWINDOW);
@ -996,6 +1007,69 @@ SDispatchResult CKeybindManager::kill(std::string args) {
return {}; return {};
} }
SDispatchResult CKeybindManager::killWindow(std::string args) {
const auto PWINDOW = g_pCompositor->getWindowByRegex(args);
if (!PWINDOW) {
Debug::log(ERR, "killWindow: no window found");
return {.success = false, .error = "killWindow: no window found"};
}
kill(PWINDOW->getPID(), SIGKILL);
return {};
}
SDispatchResult CKeybindManager::signalActive(std::string args) {
if (!std::all_of(args.begin(), args.end(), ::isdigit))
return {.success = false, .error = "signalActive: signal has to be int"};
try {
const auto SIGNALNUM = std::stoi(args);
if (SIGNALNUM < 1 || SIGNALNUM > 31) {
Debug::log(ERR, "signalActive: invalid signal number {}", SIGNALNUM);
return {.success = false, .error = std::format("signalActive: invalid signal number {}", SIGNALNUM)};
}
kill(g_pCompositor->m_pLastWindow.lock()->getPID(), SIGNALNUM);
} catch (const std::exception& e) {
Debug::log(ERR, "signalActive: invalid signal format \"{}\"", args);
return {.success = false, .error = std::format("signalActive: invalid signal format \"{}\"", args)};
}
kill(g_pCompositor->m_pLastWindow.lock()->getPID(), std::stoi(args));
return {};
}
SDispatchResult CKeybindManager::signalWindow(std::string args) {
const auto WINDOWREGEX = args.substr(0, args.find_first_of(','));
const auto SIGNAL = args.substr(args.find_first_of(',') + 1);
const auto PWINDOW = g_pCompositor->getWindowByRegex(WINDOWREGEX);
if (!PWINDOW) {
Debug::log(ERR, "signalWindow: no window");
return {.success = false, .error = "signalWindow: no window"};
}
if (!std::all_of(SIGNAL.begin(), SIGNAL.end(), ::isdigit))
return {.success = false, .error = "signalWindow: signal has to be int"};
try {
const auto SIGNALNUM = std::stoi(SIGNAL);
if (SIGNALNUM < 1 || SIGNALNUM > 31) {
Debug::log(ERR, "signalWindow: invalid signal number {}", SIGNALNUM);
return {.success = false, .error = std::format("signalWindow: invalid signal number {}", SIGNALNUM)};
}
kill(PWINDOW->getPID(), SIGNALNUM);
} catch (const std::exception& e) {
Debug::log(ERR, "signalWindow: invalid signal format \"{}\"", SIGNAL);
return {.success = false, .error = std::format("signalWindow: invalid signal format \"{}\"", SIGNAL)};
}
return {};
}
void CKeybindManager::clearKeybinds() { void CKeybindManager::clearKeybinds() {
m_vKeybinds.clear(); m_vKeybinds.clear();
} }
@ -1070,8 +1144,8 @@ SDispatchResult CKeybindManager::centerWindow(std::string args) {
if (args == "1") if (args == "1")
RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f; RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f;
PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize.goal() / 2.f + RESERVEDOFFSET; *PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize->goal() / 2.f + RESERVEDOFFSET;
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goal(); PWINDOW->m_vPosition = PWINDOW->m_vRealPosition->goal();
return {}; return {};
} }
@ -1557,14 +1631,14 @@ SDispatchResult CKeybindManager::moveActiveTo(std::string args) {
switch (arg) { switch (arg) {
case 'l': vPosx = PMONITOR->vecReservedTopLeft.x + BORDERSIZE + PMONITOR->vecPosition.x; break; case 'l': vPosx = PMONITOR->vecReservedTopLeft.x + BORDERSIZE + PMONITOR->vecPosition.x; break;
case 'r': vPosx = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PLASTWINDOW->m_vRealSize.goal().x - BORDERSIZE + PMONITOR->vecPosition.x; break; case 'r': vPosx = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PLASTWINDOW->m_vRealSize->goal().x - BORDERSIZE + PMONITOR->vecPosition.x; break;
case 't': case 't':
case 'u': vPosy = PMONITOR->vecReservedTopLeft.y + BORDERSIZE + PMONITOR->vecPosition.y; break; case 'u': vPosy = PMONITOR->vecReservedTopLeft.y + BORDERSIZE + PMONITOR->vecPosition.y; break;
case 'b': case 'b':
case 'd': vPosy = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PLASTWINDOW->m_vRealSize.goal().y - BORDERSIZE + PMONITOR->vecPosition.y; break; case 'd': vPosy = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PLASTWINDOW->m_vRealSize->goal().y - BORDERSIZE + PMONITOR->vecPosition.y; break;
} }
PLASTWINDOW->m_vRealPosition = Vector2D(vPosx.value_or(PLASTWINDOW->m_vRealPosition.goal().x), vPosy.value_or(PLASTWINDOW->m_vRealPosition.goal().y)); *PLASTWINDOW->m_vRealPosition = Vector2D(vPosx.value_or(PLASTWINDOW->m_vRealPosition->goal().x), vPosy.value_or(PLASTWINDOW->m_vRealPosition->goal().y));
return {}; return {};
} }
@ -1735,20 +1809,20 @@ SDispatchResult CKeybindManager::moveCursorToCorner(std::string arg) {
switch (CORNER) { switch (CORNER) {
case 0: case 0:
// bottom left // bottom left
g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y + PWINDOW->m_vRealSize.value().y}, true); g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition->value().x, PWINDOW->m_vRealPosition->value().y + PWINDOW->m_vRealSize->value().y}, true);
break; break;
case 1: case 1:
// bottom right // bottom right
g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealPosition.value().y + PWINDOW->m_vRealSize.value().y}, g_pCompositor->warpCursorTo(
true); {PWINDOW->m_vRealPosition->value().x + PWINDOW->m_vRealSize->value().x, PWINDOW->m_vRealPosition->value().y + PWINDOW->m_vRealSize->value().y}, true);
break; break;
case 2: case 2:
// top right // top right
g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition.value().x + PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealPosition.value().y}, true); g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition->value().x + PWINDOW->m_vRealSize->value().x, PWINDOW->m_vRealPosition->value().y}, true);
break; break;
case 3: case 3:
// top left // top left
g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y}, true); g_pCompositor->warpCursorTo({PWINDOW->m_vRealPosition->value().x, PWINDOW->m_vRealPosition->value().y}, true);
break; break;
} }
@ -1817,18 +1891,18 @@ SDispatchResult CKeybindManager::workspaceOpt(std::string args) {
continue; continue;
if (!w->m_bRequestsFloat && w->m_bIsFloating != PWORKSPACE->m_bDefaultFloating) { if (!w->m_bRequestsFloat && w->m_bIsFloating != PWORKSPACE->m_bDefaultFloating) {
const auto SAVEDPOS = w->m_vRealPosition.value(); const auto SAVEDPOS = w->m_vRealPosition->value();
const auto SAVEDSIZE = w->m_vRealSize.value(); const auto SAVEDSIZE = w->m_vRealSize->value();
w->m_bIsFloating = PWORKSPACE->m_bDefaultFloating; w->m_bIsFloating = PWORKSPACE->m_bDefaultFloating;
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(w); g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(w);
if (PWORKSPACE->m_bDefaultFloating) { if (PWORKSPACE->m_bDefaultFloating) {
w->m_vRealPosition.setValueAndWarp(SAVEDPOS); w->m_vRealPosition->setValueAndWarp(SAVEDPOS);
w->m_vRealSize.setValueAndWarp(SAVEDSIZE); w->m_vRealSize->setValueAndWarp(SAVEDSIZE);
g_pXWaylandManager->setWindowSize(w, SAVEDSIZE); g_pXWaylandManager->setWindowSize(w, SAVEDSIZE);
w->m_vRealSize = w->m_vRealSize.value() + Vector2D(4, 4); *w->m_vRealSize = w->m_vRealSize->value() + Vector2D(4, 4);
w->m_vRealPosition = w->m_vRealPosition.value() - Vector2D(2, 2); *w->m_vRealPosition = w->m_vRealPosition->value() - Vector2D(2, 2);
} }
} }
} }
@ -2043,14 +2117,14 @@ SDispatchResult CKeybindManager::resizeActive(std::string args) {
if (!PLASTWINDOW || PLASTWINDOW->isFullscreen()) if (!PLASTWINDOW || PLASTWINDOW->isFullscreen())
return {}; return {};
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealSize.goal()); const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealSize->goal());
if (SIZ.x < 1 || SIZ.y < 1) if (SIZ.x < 1 || SIZ.y < 1)
return {}; return {};
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PLASTWINDOW->m_vRealSize.goal()); g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PLASTWINDOW->m_vRealSize->goal());
if (PLASTWINDOW->m_vRealSize.goal().x > 1 && PLASTWINDOW->m_vRealSize.goal().y > 1) if (PLASTWINDOW->m_vRealSize->goal().x > 1 && PLASTWINDOW->m_vRealSize->goal().y > 1)
PLASTWINDOW->setHidden(false); PLASTWINDOW->setHidden(false);
return {}; return {};
@ -2062,9 +2136,9 @@ SDispatchResult CKeybindManager::moveActive(std::string args) {
if (!PLASTWINDOW || PLASTWINDOW->isFullscreen()) if (!PLASTWINDOW || PLASTWINDOW->isFullscreen())
return {}; return {};
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealPosition.goal()); const auto POS = g_pCompositor->parseWindowVectorArgsRelative(args, PLASTWINDOW->m_vRealPosition->goal());
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PLASTWINDOW->m_vRealPosition.goal()); g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PLASTWINDOW->m_vRealPosition->goal());
return {}; return {};
} }
@ -2084,9 +2158,9 @@ SDispatchResult CKeybindManager::moveWindow(std::string args) {
if (PWINDOW->isFullscreen()) if (PWINDOW->isFullscreen())
return {}; return {};
const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealPosition.goal()); const auto POS = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealPosition->goal());
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PWINDOW->m_vRealPosition.goal(), PWINDOW); g_pLayoutManager->getCurrentLayout()->moveActiveWindow(POS - PWINDOW->m_vRealPosition->goal(), PWINDOW);
return {}; return {};
} }
@ -2106,14 +2180,14 @@ SDispatchResult CKeybindManager::resizeWindow(std::string args) {
if (PWINDOW->isFullscreen()) if (PWINDOW->isFullscreen())
return {}; return {};
const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize.goal()); const auto SIZ = g_pCompositor->parseWindowVectorArgsRelative(MOVECMD, PWINDOW->m_vRealSize->goal());
if (SIZ.x < 1 || SIZ.y < 1) if (SIZ.x < 1 || SIZ.y < 1)
return {}; return {};
g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize.goal(), CORNER_NONE, PWINDOW); g_pLayoutManager->getCurrentLayout()->resizeActiveWindow(SIZ - PWINDOW->m_vRealSize->goal(), CORNER_NONE, PWINDOW);
if (PWINDOW->m_vRealSize.goal().x > 1 && PWINDOW->m_vRealSize.goal().y > 1) if (PWINDOW->m_vRealSize->goal().x > 1 && PWINDOW->m_vRealSize->goal().y > 1)
PWINDOW->setHidden(false); PWINDOW->setHidden(false);
return {}; return {};
@ -2192,8 +2266,8 @@ SDispatchResult CKeybindManager::focusWindow(std::string regexp) {
g_pCompositor->setWindowFullscreenClient(PWINDOW, FSMODE); g_pCompositor->setWindowFullscreenClient(PWINDOW, FSMODE);
// warp the position + size animation, otherwise it looks weird. // warp the position + size animation, otherwise it looks weird.
PWINDOW->m_vRealPosition.warp(); PWINDOW->m_vRealPosition->warp();
PWINDOW->m_vRealSize.warp(); PWINDOW->m_vRealSize->warp();
} }
} else } else
g_pCompositor->focusWindow(PWINDOW); g_pCompositor->focusWindow(PWINDOW);
@ -2311,7 +2385,7 @@ SDispatchResult CKeybindManager::pass(std::string regexp) {
} }
} }
const auto SL = PWINDOW->m_vRealPosition.goal() - g_pInputManager->getMouseCoordsInternal(); const auto SL = PWINDOW->m_vRealPosition->goal() - g_pInputManager->getMouseCoordsInternal();
if (g_pKeybindManager->m_uLastCode != 0) if (g_pKeybindManager->m_uLastCode != 0)
g_pSeatManager->setKeyboardFocus(LASTKBSURF); g_pSeatManager->setKeyboardFocus(LASTKBSURF);
@ -2466,7 +2540,7 @@ SDispatchResult CKeybindManager::sendshortcut(std::string args) {
} }
} }
const auto SL = PWINDOW->m_vRealPosition.goal() - g_pInputManager->getMouseCoordsInternal(); const auto SL = PWINDOW->m_vRealPosition->goal() - g_pInputManager->getMouseCoordsInternal();
if (!isMouse) if (!isMouse)
g_pSeatManager->setKeyboardFocus(LASTSURFACE); g_pSeatManager->setKeyboardFocus(LASTSURFACE);

View file

@ -152,8 +152,12 @@ class CKeybindManager {
static uint64_t spawnWithRules(std::string, PHLWORKSPACE pInitialWorkspace); static uint64_t spawnWithRules(std::string, PHLWORKSPACE pInitialWorkspace);
// -------------- Dispatchers -------------- // // -------------- Dispatchers -------------- //
static SDispatchResult closeActive(std::string);
static SDispatchResult killActive(std::string); static SDispatchResult killActive(std::string);
static SDispatchResult kill(std::string); static SDispatchResult closeWindow(std::string);
static SDispatchResult killWindow(std::string);
static SDispatchResult signalActive(std::string);
static SDispatchResult signalWindow(std::string);
static SDispatchResult spawn(std::string); static SDispatchResult spawn(std::string);
static SDispatchResult spawnRaw(std::string); static SDispatchResult spawnRaw(std::string);
static SDispatchResult toggleActiveFloating(std::string); static SDispatchResult toggleActiveFloating(std::string);

View file

@ -376,7 +376,9 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
auto maxSize = state->monitor->output->cursorPlaneSize(); auto maxSize = state->monitor->output->cursorPlaneSize();
auto const& cursorSize = currentCursorImage.size; auto const& cursorSize = currentCursorImage.size;
static auto PDUMB = CConfigValue<Hyprlang::INT>("cursor:use_cpu_buffer"); static auto PCPUBUFFER = CConfigValue<Hyprlang::INT>("cursor:use_cpu_buffer");
const bool shouldUseCpuBuffer = *PCPUBUFFER == 1 || (*PCPUBUFFER != 0 && g_pHyprRenderer->isNvidia());
if (maxSize == Vector2D{}) if (maxSize == Vector2D{})
return nullptr; return nullptr;
@ -390,12 +392,12 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
maxSize = cursorSize; maxSize = cursorSize;
if (!state->monitor->cursorSwapchain || maxSize != state->monitor->cursorSwapchain->currentOptions().size || if (!state->monitor->cursorSwapchain || maxSize != state->monitor->cursorSwapchain->currentOptions().size ||
*PDUMB != (state->monitor->cursorSwapchain->getAllocator()->type() != Aquamarine::AQ_ALLOCATOR_TYPE_GBM)) { shouldUseCpuBuffer != (state->monitor->cursorSwapchain->getAllocator()->type() != Aquamarine::AQ_ALLOCATOR_TYPE_GBM)) {
if (!state->monitor->cursorSwapchain || *PDUMB != (state->monitor->cursorSwapchain->getAllocator()->type() != Aquamarine::AQ_ALLOCATOR_TYPE_GBM)) { if (!state->monitor->cursorSwapchain || shouldUseCpuBuffer != (state->monitor->cursorSwapchain->getAllocator()->type() != Aquamarine::AQ_ALLOCATOR_TYPE_GBM)) {
auto allocator = state->monitor->output->getBackend()->preferredAllocator(); auto allocator = state->monitor->output->getBackend()->preferredAllocator();
if (*PDUMB) { if (shouldUseCpuBuffer) {
for (const auto& a : state->monitor->output->getBackend()->getAllocators()) { for (const auto& a : state->monitor->output->getBackend()->getAllocators()) {
if (a->type() == Aquamarine::AQ_ALLOCATOR_TYPE_DRM_DUMB) { if (a->type() == Aquamarine::AQ_ALLOCATOR_TYPE_DRM_DUMB) {
allocator = a; allocator = a;
@ -415,7 +417,7 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
options.multigpu = state->monitor->output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_iDRMFD; options.multigpu = state->monitor->output->getBackend()->preferredAllocator()->drmFD() != g_pCompositor->m_iDRMFD;
// We do not set the format (unless shm). If it's unset (DRM_FORMAT_INVALID) then the swapchain will pick for us, // We do not set the format (unless shm). If it's unset (DRM_FORMAT_INVALID) then the swapchain will pick for us,
// but if it's set, we don't wanna change it. // but if it's set, we don't wanna change it.
if (*PDUMB) if (shouldUseCpuBuffer)
options.format = DRM_FORMAT_ARGB8888; options.format = DRM_FORMAT_ARGB8888;
if (!state->monitor->cursorSwapchain->reconfigure(options)) { if (!state->monitor->cursorSwapchain->reconfigure(options)) {
@ -438,7 +440,7 @@ SP<Aquamarine::IBuffer> CPointerManager::renderHWCursorBuffer(SP<CPointerManager
return nullptr; return nullptr;
} }
if (*PDUMB) { if (shouldUseCpuBuffer) {
// get the texture data if available. // get the texture data if available.
auto texData = texture->dataCopy(); auto texData = texture->dataCopy();
if (texData.empty()) { if (texData.empty()) {

View file

@ -55,6 +55,8 @@
#include "../protocols/core/Subcompositor.hpp" #include "../protocols/core/Subcompositor.hpp"
#include "../protocols/core/Output.hpp" #include "../protocols/core/Output.hpp"
#include "../protocols/core/Shm.hpp" #include "../protocols/core/Shm.hpp"
#include "../protocols/ColorManagement.hpp"
#include "../protocols/FrogColorManagement.hpp"
#include "../helpers/Monitor.hpp" #include "../helpers/Monitor.hpp"
#include "../render/Renderer.hpp" #include "../render/Renderer.hpp"
@ -77,11 +79,15 @@ void CProtocolManager::onMonitorModeChange(PHLMONITOR pMonitor) {
PROTO::outputs.erase(pMonitor->szName); PROTO::outputs.erase(pMonitor->szName);
PROTO::outputs.emplace(pMonitor->szName, makeShared<CWLOutputProtocol>(&wl_output_interface, 4, std::format("WLOutput ({})", pMonitor->szName), pMonitor->self.lock())); PROTO::outputs.emplace(pMonitor->szName, makeShared<CWLOutputProtocol>(&wl_output_interface, 4, std::format("WLOutput ({})", pMonitor->szName), pMonitor->self.lock()));
} }
if (PROTO::colorManagement && g_pCompositor->shouldChangePreferredImageDescription())
PROTO::colorManagement->onImagePreferredChanged();
} }
CProtocolManager::CProtocolManager() { CProtocolManager::CProtocolManager() {
static const auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("render:explicit_sync"); static const auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("render:explicit_sync");
static const auto PENABLEXXCM = CConfigValue<Hyprlang::INT>("experimental:xx_color_management_v4");
// Outputs are a bit dumb, we have to agree. // Outputs are a bit dumb, we have to agree.
static auto P = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) { static auto P = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) {
@ -162,6 +168,11 @@ CProtocolManager::CProtocolManager() {
PROTO::ctm = std::make_unique<CHyprlandCTMControlProtocol>(&hyprland_ctm_control_manager_v1_interface, 1, "CTMControl"); PROTO::ctm = std::make_unique<CHyprlandCTMControlProtocol>(&hyprland_ctm_control_manager_v1_interface, 1, "CTMControl");
PROTO::hyprlandSurface = std::make_unique<CHyprlandSurfaceProtocol>(&hyprland_surface_manager_v1_interface, 1, "HyprlandSurface"); PROTO::hyprlandSurface = std::make_unique<CHyprlandSurfaceProtocol>(&hyprland_surface_manager_v1_interface, 1, "HyprlandSurface");
if (*PENABLEXXCM) {
PROTO::colorManagement = std::make_unique<CColorManagementProtocol>(&xx_color_manager_v4_interface, 1, "ColorManagement");
PROTO::frogColorManagement = std::make_unique<CFrogColorManagementProtocol>(&frog_color_management_factory_v1_interface, 1, "FrogColorManagement");
}
for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) { for (auto const& b : g_pCompositor->m_pAqBackend->getImplementations()) {
if (b->type() != Aquamarine::AQ_BACKEND_DRM) if (b->type() != Aquamarine::AQ_BACKEND_DRM)
continue; continue;

View file

@ -55,7 +55,7 @@ void CHyprXWaylandManager::activateWindow(PHLWINDOW pWindow, bool activate) {
if (pWindow->m_bIsX11) { if (pWindow->m_bIsX11) {
if (activate) { if (activate) {
setWindowSize(pWindow, pWindow->m_vRealSize.value()); // update xwayland output pos setWindowSize(pWindow, pWindow->m_vRealSize->value()); // update xwayland output pos
pWindow->m_pXWaylandSurface->setMinimized(false); pWindow->m_pXWaylandSurface->setMinimized(false);
if (!pWindow->isX11OverrideRedirect()) if (!pWindow->isX11OverrideRedirect())
@ -123,7 +123,7 @@ void CHyprXWaylandManager::setWindowSize(PHLWINDOW pWindow, Vector2D size, bool
// calculate pos // calculate pos
// TODO: this should be decoupled from setWindowSize IMO // TODO: this should be decoupled from setWindowSize IMO
Vector2D windowPos = pWindow->m_vRealPosition.value(); Vector2D windowPos = pWindow->m_vRealPosition->value();
if (pWindow->m_bIsX11 && PMONITOR) { if (pWindow->m_bIsX11 && PMONITOR) {
windowPos -= PMONITOR->vecPosition; // normalize to monitor windowPos -= PMONITOR->vecPosition; // normalize to monitor

View file

@ -137,7 +137,7 @@ void CInputManager::sendMotionEventsToFocused() {
timespec now; timespec now;
clock_gettime(CLOCK_MONOTONIC, &now); clock_gettime(CLOCK_MONOTONIC, &now);
const auto LOCAL = getMouseCoordsInternal() - (PWINDOW ? PWINDOW->m_vRealPosition.goal() : (PLS ? Vector2D{PLS->geometry.x, PLS->geometry.y} : Vector2D{})); const auto LOCAL = getMouseCoordsInternal() - (PWINDOW ? PWINDOW->m_vRealPosition->goal() : (PLS ? Vector2D{PLS->geometry.x, PLS->geometry.y} : Vector2D{}));
m_bEmptyFocusCursorSet = false; m_bEmptyFocusCursorSet = false;
@ -243,7 +243,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) {
if (forcedFocus) { if (forcedFocus) {
pFoundWindow = forcedFocus; pFoundWindow = forcedFocus;
surfacePos = pFoundWindow->m_vRealPosition.value(); surfacePos = pFoundWindow->m_vRealPosition->value();
foundSurface = pFoundWindow->m_pWLSurface->resource(); foundSurface = pFoundWindow->m_pWLSurface->resource();
} }
@ -320,7 +320,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) {
surfacePos = Vector2D(-1337, -1337); surfacePos = Vector2D(-1337, -1337);
} else { } else {
foundSurface = pFoundWindow->m_pWLSurface->resource(); foundSurface = pFoundWindow->m_pWLSurface->resource();
surfacePos = pFoundWindow->m_vRealPosition.value(); surfacePos = pFoundWindow->m_vRealPosition->value();
} }
} }
@ -362,11 +362,11 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) {
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords); foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
if (!foundSurface) { if (!foundSurface) {
foundSurface = pFoundWindow->m_pWLSurface->resource(); foundSurface = pFoundWindow->m_pWLSurface->resource();
surfacePos = pFoundWindow->m_vRealPosition.value(); surfacePos = pFoundWindow->m_vRealPosition->value();
} }
} else { } else {
foundSurface = pFoundWindow->m_pWLSurface->resource(); foundSurface = pFoundWindow->m_pWLSurface->resource();
surfacePos = pFoundWindow->m_vRealPosition.value(); surfacePos = pFoundWindow->m_vRealPosition->value();
} }
} }
} }
@ -689,7 +689,7 @@ void CInputManager::processMouseDownNormal(const IPointer::SButtonEvent& e) {
// TODO detect click on LS properly // TODO detect click on LS properly
if (*PRESIZEONBORDER && !m_bLastFocusOnLS && e.state == WL_POINTER_BUTTON_STATE_PRESSED && (!w || !w->isX11OverrideRedirect())) { if (*PRESIZEONBORDER && !m_bLastFocusOnLS && e.state == WL_POINTER_BUTTON_STATE_PRESSED && (!w || !w->isX11OverrideRedirect())) {
if (w && !w->isFullscreen()) { if (w && !w->isFullscreen()) {
const CBox real = {w->m_vRealPosition.value().x, w->m_vRealPosition.value().y, w->m_vRealSize.value().x, w->m_vRealSize.value().y}; const CBox real = {w->m_vRealPosition->value().x, w->m_vRealPosition->value().y, w->m_vRealSize->value().x, w->m_vRealSize->value().y};
const CBox grab = {real.x - BORDER_GRAB_AREA, real.y - BORDER_GRAB_AREA, real.width + 2 * BORDER_GRAB_AREA, real.height + 2 * BORDER_GRAB_AREA}; const CBox grab = {real.x - BORDER_GRAB_AREA, real.y - BORDER_GRAB_AREA, real.width + 2 * BORDER_GRAB_AREA, real.height + 2 * BORDER_GRAB_AREA};
if ((grab.containsPoint(mouseCoords) && (!real.containsPoint(mouseCoords) || w->isInCurvedCorner(mouseCoords.x, mouseCoords.y))) && !w->hasPopupAt(mouseCoords)) { if ((grab.containsPoint(mouseCoords) && (!real.containsPoint(mouseCoords) || w->isInCurvedCorner(mouseCoords.x, mouseCoords.y))) && !w->hasPopupAt(mouseCoords)) {

View file

@ -38,7 +38,7 @@ void CInputManager::beginWorkspaceSwipe() {
if (PWORKSPACE->m_bHasFullscreenWindow) { if (PWORKSPACE->m_bHasFullscreenWindow) {
for (auto const& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLayers[2]) { for (auto const& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLayers[2]) {
ls->alpha = 1.f; *ls->alpha = 1.f;
} }
} }
} }
@ -58,8 +58,8 @@ void CInputManager::endWorkspaceSwipe() {
static auto PSWIPENEW = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe_create_new"); static auto PSWIPENEW = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe_create_new");
static auto PSWIPEUSER = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe_use_r"); static auto PSWIPEUSER = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe_use_r");
static auto PWORKSPACEGAP = CConfigValue<Hyprlang::INT>("general:gaps_workspaces"); static auto PWORKSPACEGAP = CConfigValue<Hyprlang::INT>("general:gaps_workspaces");
const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || const auto ANIMSTYLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->getStyle();
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); const bool VERTANIMS = ANIMSTYLE == "slidevert" || ANIMSTYLE.starts_with("slidefadevert");
// commit // commit
auto workspaceIDLeft = getWorkspaceIDNameFromString((*PSWIPEUSER ? "r-1" : "m-1")).id; auto workspaceIDLeft = getWorkspaceIDNameFromString((*PSWIPEUSER ? "r-1" : "m-1")).id;
@ -86,7 +86,7 @@ void CInputManager::endWorkspaceSwipe() {
auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); // not guaranteed if PSWIPENEW || PSWIPENUMBER auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); // not guaranteed if PSWIPENEW || PSWIPENUMBER
auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); // not guaranteed if PSWIPENUMBER auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); // not guaranteed if PSWIPENUMBER
const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.value(); const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->value();
const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + *PWORKSPACEGAP; const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + *PWORKSPACEGAP;
const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + *PWORKSPACEGAP; const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + *PWORKSPACEGAP;
@ -97,35 +97,35 @@ void CInputManager::endWorkspaceSwipe() {
// revert // revert
if (abs(m_sActiveSwipe.delta) < 2) { if (abs(m_sActiveSwipe.delta) < 2) {
if (PWORKSPACEL) if (PWORKSPACEL)
PWORKSPACEL->m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); PWORKSPACEL->m_vRenderOffset->setValueAndWarp(Vector2D(0, 0));
if (PWORKSPACER) if (PWORKSPACER)
PWORKSPACER->m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); PWORKSPACER->m_vRenderOffset->setValueAndWarp(Vector2D(0, 0));
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(0, 0));
} else { } else {
if (m_sActiveSwipe.delta < 0) { if (m_sActiveSwipe.delta < 0) {
// to left // to left
if (PWORKSPACEL) { if (PWORKSPACEL) {
if (VERTANIMS) if (VERTANIMS)
PWORKSPACEL->m_vRenderOffset = Vector2D{0.0, -YDISTANCE}; *PWORKSPACEL->m_vRenderOffset = Vector2D{0.0, -YDISTANCE};
else else
PWORKSPACEL->m_vRenderOffset = Vector2D{-XDISTANCE, 0.0}; *PWORKSPACEL->m_vRenderOffset = Vector2D{-XDISTANCE, 0.0};
} }
} else if (PWORKSPACER) { } else if (PWORKSPACER) {
// to right // to right
if (VERTANIMS) if (VERTANIMS)
PWORKSPACER->m_vRenderOffset = Vector2D{0.0, YDISTANCE}; *PWORKSPACER->m_vRenderOffset = Vector2D{0.0, YDISTANCE};
else else
PWORKSPACER->m_vRenderOffset = Vector2D{XDISTANCE, 0.0}; *PWORKSPACER->m_vRenderOffset = Vector2D{XDISTANCE, 0.0};
} }
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(); *m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D();
} }
pSwitchedTo = m_sActiveSwipe.pWorkspaceBegin; pSwitchedTo = m_sActiveSwipe.pWorkspaceBegin;
} else if (m_sActiveSwipe.delta < 0) { } else if (m_sActiveSwipe.delta < 0) {
// switch to left // switch to left
const auto RENDEROFFSET = PWORKSPACEL ? PWORKSPACEL->m_vRenderOffset.value() : Vector2D(); const auto RENDEROFFSET = PWORKSPACEL ? PWORKSPACEL->m_vRenderOffset->value() : Vector2D();
if (PWORKSPACEL) if (PWORKSPACEL)
m_sActiveSwipe.pMonitor->changeWorkspace(workspaceIDLeft); m_sActiveSwipe.pMonitor->changeWorkspace(workspaceIDLeft);
@ -134,15 +134,15 @@ void CInputManager::endWorkspaceSwipe() {
PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
} }
PWORKSPACEL->m_vRenderOffset.setValue(RENDEROFFSET); PWORKSPACEL->m_vRenderOffset->setValue(RENDEROFFSET);
PWORKSPACEL->m_fAlpha.setValueAndWarp(1.f); PWORKSPACEL->m_fAlpha->setValueAndWarp(1.f);
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE); m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValue(RENDEROFFSETMIDDLE);
if (VERTANIMS) if (VERTANIMS)
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0.0, YDISTANCE); *m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0.0, YDISTANCE);
else else
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(XDISTANCE, 0.0); *m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(XDISTANCE, 0.0);
m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(1.f); m_sActiveSwipe.pWorkspaceBegin->m_fAlpha->setValueAndWarp(1.f);
g_pInputManager->unconstrainMouse(); g_pInputManager->unconstrainMouse();
@ -151,7 +151,7 @@ void CInputManager::endWorkspaceSwipe() {
pSwitchedTo = PWORKSPACEL; pSwitchedTo = PWORKSPACEL;
} else { } else {
// switch to right // switch to right
const auto RENDEROFFSET = PWORKSPACER ? PWORKSPACER->m_vRenderOffset.value() : Vector2D(); const auto RENDEROFFSET = PWORKSPACER ? PWORKSPACER->m_vRenderOffset->value() : Vector2D();
if (PWORKSPACER) if (PWORKSPACER)
m_sActiveSwipe.pMonitor->changeWorkspace(workspaceIDRight); m_sActiveSwipe.pMonitor->changeWorkspace(workspaceIDRight);
@ -160,15 +160,15 @@ void CInputManager::endWorkspaceSwipe() {
PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight);
} }
PWORKSPACER->m_vRenderOffset.setValue(RENDEROFFSET); PWORKSPACER->m_vRenderOffset->setValue(RENDEROFFSET);
PWORKSPACER->m_fAlpha.setValueAndWarp(1.f); PWORKSPACER->m_fAlpha->setValueAndWarp(1.f);
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE); m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValue(RENDEROFFSETMIDDLE);
if (VERTANIMS) if (VERTANIMS)
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0.0, -YDISTANCE); *m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0.0, -YDISTANCE);
else else
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-XDISTANCE, 0.0); *m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-XDISTANCE, 0.0);
m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(1.f); m_sActiveSwipe.pWorkspaceBegin->m_fAlpha->setValueAndWarp(1.f);
g_pInputManager->unconstrainMouse(); g_pInputManager->unconstrainMouse();
@ -193,7 +193,7 @@ void CInputManager::endWorkspaceSwipe() {
// apply alpha // apply alpha
for (auto const& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLayers[2]) { for (auto const& ls : g_pCompositor->m_pLastMonitor->m_aLayerSurfaceLayers[2]) {
ls->alpha = pSwitchedTo->m_bHasFullscreenWindow && pSwitchedTo->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; *ls->alpha = pSwitchedTo->m_bHasFullscreenWindow && pSwitchedTo->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f;
} }
} }
@ -203,8 +203,8 @@ void CInputManager::onSwipeUpdate(IPointer::SSwipeUpdateEvent e) {
if (!m_sActiveSwipe.pWorkspaceBegin) if (!m_sActiveSwipe.pWorkspaceBegin)
return; return;
static auto PSWIPEINVR = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe_invert"); static auto PSWIPEINVR = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe_invert");
const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || const auto ANIMSTYLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->getStyle();
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); const bool VERTANIMS = ANIMSTYLE == "slidevert" || ANIMSTYLE.starts_with("slidefadevert");
const double delta = m_sActiveSwipe.delta + (VERTANIMS ? (*PSWIPEINVR ? -e.delta.y : e.delta.y) : (*PSWIPEINVR ? -e.delta.x : e.delta.x)); const double delta = m_sActiveSwipe.delta + (VERTANIMS ? (*PSWIPEINVR ? -e.delta.y : e.delta.y) : (*PSWIPEINVR ? -e.delta.x : e.delta.x));
updateWorkspaceSwipe(delta); updateWorkspaceSwipe(delta);
@ -222,8 +222,8 @@ void CInputManager::updateWorkspaceSwipe(double delta) {
const auto SWIPEDISTANCE = std::clamp(*PSWIPEDIST, (int64_t)1LL, (int64_t)UINT32_MAX); const auto SWIPEDISTANCE = std::clamp(*PSWIPEDIST, (int64_t)1LL, (int64_t)UINT32_MAX);
const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + *PWORKSPACEGAP; const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + *PWORKSPACEGAP;
const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + *PWORKSPACEGAP; const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + *PWORKSPACEGAP;
const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || const auto ANIMSTYLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->getStyle();
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); const bool VERTANIMS = ANIMSTYLE == "slidevert" || ANIMSTYLE.starts_with("slidefadevert");
const double d = m_sActiveSwipe.delta - delta; const double d = m_sActiveSwipe.delta - delta;
m_sActiveSwipe.delta = delta; m_sActiveSwipe.delta = delta;
@ -265,9 +265,9 @@ void CInputManager::updateWorkspaceSwipe(double delta) {
g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor.lock()); g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor.lock());
if (VERTANIMS) if (VERTANIMS)
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE));
else else
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0));
m_sActiveSwipe.pWorkspaceBegin->updateWindowDecos(); m_sActiveSwipe.pWorkspaceBegin->updateWindowDecos();
return; return;
@ -277,23 +277,23 @@ void CInputManager::updateWorkspaceSwipe(double delta) {
} }
PWORKSPACE->m_bForceRendering = true; PWORKSPACE->m_bForceRendering = true;
PWORKSPACE->m_fAlpha.setValueAndWarp(1.f); PWORKSPACE->m_fAlpha->setValueAndWarp(1.f);
if (workspaceIDLeft != workspaceIDRight && workspaceIDRight != m_sActiveSwipe.pWorkspaceBegin->m_iID) { if (workspaceIDLeft != workspaceIDRight && workspaceIDRight != m_sActiveSwipe.pWorkspaceBegin->m_iID) {
const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight);
if (PWORKSPACER) { if (PWORKSPACER) {
PWORKSPACER->m_bForceRendering = false; PWORKSPACER->m_bForceRendering = false;
PWORKSPACER->m_fAlpha.setValueAndWarp(0.f); PWORKSPACER->m_fAlpha->setValueAndWarp(0.f);
} }
} }
if (VERTANIMS) { if (VERTANIMS) {
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE - YDISTANCE)); PWORKSPACE->m_vRenderOffset->setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE - YDISTANCE));
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE));
} else { } else {
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE - XDISTANCE, 0.0)); PWORKSPACE->m_vRenderOffset->setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE - XDISTANCE, 0.0));
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0));
} }
PWORKSPACE->updateWindowDecos(); PWORKSPACE->updateWindowDecos();
@ -305,9 +305,9 @@ void CInputManager::updateWorkspaceSwipe(double delta) {
g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor.lock()); g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor.lock());
if (VERTANIMS) if (VERTANIMS)
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE));
else else
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0));
m_sActiveSwipe.pWorkspaceBegin->updateWindowDecos(); m_sActiveSwipe.pWorkspaceBegin->updateWindowDecos();
return; return;
@ -317,23 +317,23 @@ void CInputManager::updateWorkspaceSwipe(double delta) {
} }
PWORKSPACE->m_bForceRendering = true; PWORKSPACE->m_bForceRendering = true;
PWORKSPACE->m_fAlpha.setValueAndWarp(1.f); PWORKSPACE->m_fAlpha->setValueAndWarp(1.f);
if (workspaceIDLeft != workspaceIDRight && workspaceIDLeft != m_sActiveSwipe.pWorkspaceBegin->m_iID) { if (workspaceIDLeft != workspaceIDRight && workspaceIDLeft != m_sActiveSwipe.pWorkspaceBegin->m_iID) {
const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
if (PWORKSPACEL) { if (PWORKSPACEL) {
PWORKSPACEL->m_bForceRendering = false; PWORKSPACEL->m_bForceRendering = false;
PWORKSPACEL->m_fAlpha.setValueAndWarp(0.f); PWORKSPACEL->m_fAlpha->setValueAndWarp(0.f);
} }
} }
if (VERTANIMS) { if (VERTANIMS) {
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE + YDISTANCE)); PWORKSPACE->m_vRenderOffset->setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE + YDISTANCE));
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE)); m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(0.0, ((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * YDISTANCE));
} else { } else {
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE + XDISTANCE, 0.0)); PWORKSPACE->m_vRenderOffset->setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE + XDISTANCE, 0.0));
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0)); m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / SWIPEDISTANCE) * XDISTANCE, 0.0));
} }
PWORKSPACE->updateWindowDecos(); PWORKSPACE->updateWindowDecos();

View file

@ -69,7 +69,7 @@ static void refocusTablet(SP<CTablet> tab, SP<CTabletTool> tool, bool motion = f
// yes, this technically ignores any regions set by the app. Too bad! // yes, this technically ignores any regions set by the app. Too bad!
if (LASTHLSURFACE->getWindow()) if (LASTHLSURFACE->getWindow())
local = tool->absolutePos * LASTHLSURFACE->getWindow()->m_vRealSize.goal(); local = tool->absolutePos * LASTHLSURFACE->getWindow()->m_vRealSize->goal();
else else
local = tool->absolutePos * BOX->size(); local = tool->absolutePos * BOX->size();

View file

@ -3,6 +3,7 @@
#include "../../config/ConfigValue.hpp" #include "../../config/ConfigValue.hpp"
#include "../../devices/ITouch.hpp" #include "../../devices/ITouch.hpp"
#include "../SeatManager.hpp" #include "../SeatManager.hpp"
#include "managers/AnimationManager.hpp"
void CInputManager::onTouchDown(ITouch::SDownEvent e) { void CInputManager::onTouchDown(ITouch::SDownEvent e) {
m_bLastInputTouch = true; m_bLastInputTouch = true;
@ -37,8 +38,8 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) {
// TODO: Don't swipe if you touched a floating window. // TODO: Don't swipe if you touched a floating window.
} else if (*PSWIPETOUCH && (m_pFoundLSToFocus.expired() || m_pFoundLSToFocus->layer <= 1)) { } else if (*PSWIPETOUCH && (m_pFoundLSToFocus.expired() || m_pFoundLSToFocus->layer <= 1)) {
const auto PWORKSPACE = PMONITOR->activeWorkspace; const auto PWORKSPACE = PMONITOR->activeWorkspace;
const bool VERTANIMS = PWORKSPACE->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || const auto STYLE = PWORKSPACE->m_vRenderOffset->getStyle();
PWORKSPACE->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); const bool VERTANIMS = STYLE == "slidevert" || STYLE.starts_with("slidefadevert");
const double TARGETLEFT = ((VERTANIMS ? gapsOut.top : gapsOut.left) + *PBORDERSIZE) / (VERTANIMS ? PMONITOR->vecSize.y : PMONITOR->vecSize.x); const double TARGETLEFT = ((VERTANIMS ? gapsOut.top : gapsOut.left) + *PBORDERSIZE) / (VERTANIMS ? PMONITOR->vecSize.y : PMONITOR->vecSize.x);
const double TARGETRIGHT = 1 - (((VERTANIMS ? gapsOut.bottom : gapsOut.right) + *PBORDERSIZE) / (VERTANIMS ? PMONITOR->vecSize.y : PMONITOR->vecSize.x)); const double TARGETRIGHT = 1 - (((VERTANIMS ? gapsOut.bottom : gapsOut.right) + *PBORDERSIZE) / (VERTANIMS ? PMONITOR->vecSize.y : PMONITOR->vecSize.x));
const double POSITION = (VERTANIMS ? e.pos.y : e.pos.x); const double POSITION = (VERTANIMS ? e.pos.y : e.pos.x);
@ -62,8 +63,8 @@ void CInputManager::onTouchDown(ITouch::SDownEvent e) {
if (!m_sTouchData.touchFocusWindow.expired()) { if (!m_sTouchData.touchFocusWindow.expired()) {
if (m_sTouchData.touchFocusWindow->m_bIsX11) { if (m_sTouchData.touchFocusWindow->m_bIsX11) {
local = (g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchFocusWindow->m_vRealPosition.goal()) * m_sTouchData.touchFocusWindow->m_fX11SurfaceScaledBy; local = (g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchFocusWindow->m_vRealPosition->goal()) * m_sTouchData.touchFocusWindow->m_fX11SurfaceScaledBy;
m_sTouchData.touchSurfaceOrigin = m_sTouchData.touchFocusWindow->m_vRealPosition.goal(); m_sTouchData.touchSurfaceOrigin = m_sTouchData.touchFocusWindow->m_vRealPosition->goal();
} else { } else {
g_pCompositor->vectorWindowToSurface(g_pInputManager->getMouseCoordsInternal(), m_sTouchData.touchFocusWindow.lock(), local); g_pCompositor->vectorWindowToSurface(g_pInputManager->getMouseCoordsInternal(), m_sTouchData.touchFocusWindow.lock(), local);
m_sTouchData.touchSurfaceOrigin = g_pInputManager->getMouseCoordsInternal() - local; m_sTouchData.touchSurfaceOrigin = g_pInputManager->getMouseCoordsInternal() - local;
@ -101,8 +102,9 @@ void CInputManager::onTouchMove(ITouch::SMotionEvent e) {
// Do nothing if this is using a different finger. // Do nothing if this is using a different finger.
if (e.touchID != m_sActiveSwipe.touch_id) if (e.touchID != m_sActiveSwipe.touch_id)
return; return;
const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" ||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); const auto ANIMSTYLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset->getStyle();
const bool VERTANIMS = ANIMSTYLE == "slidevert" || ANIMSTYLE.starts_with("slidefadevert");
static auto PSWIPEINVR = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe_touch_invert"); static auto PSWIPEINVR = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe_touch_invert");
static auto PSWIPEDIST = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe_distance"); static auto PSWIPEDIST = CConfigValue<Hyprlang::INT>("gestures:workspace_swipe_distance");
const auto SWIPEDISTANCE = std::clamp(*PSWIPEDIST, (int64_t)1LL, (int64_t)UINT32_MAX); const auto SWIPEDISTANCE = std::clamp(*PSWIPEDIST, (int64_t)1LL, (int64_t)UINT32_MAX);

View file

@ -3,6 +3,7 @@
#include "../render/Renderer.hpp" #include "../render/Renderer.hpp"
#include "core/Output.hpp" #include "core/Output.hpp"
#include "../config/ConfigValue.hpp" #include "../config/ConfigValue.hpp"
#include "managers/AnimationManager.hpp"
CHyprlandCTMControlResource::CHyprlandCTMControlResource(SP<CHyprlandCtmControlManagerV1> resource_) : resource(resource_) { CHyprlandCTMControlResource::CHyprlandCTMControlResource(SP<CHyprlandCtmControlManagerV1> resource_) : resource(resource_) {
if (!good()) if (!good())
@ -92,8 +93,7 @@ bool CHyprlandCTMControlProtocol::isCTMAnimationEnabled() {
} }
CHyprlandCTMControlProtocol::SCTMData::SCTMData() { CHyprlandCTMControlProtocol::SCTMData::SCTMData() {
progress.create(g_pConfigManager->getAnimationPropertyConfig("__internal_fadeCTM"), AVARDAMAGE_NONE); g_pAnimationManager->createAnimation(0.f, progress, g_pConfigManager->getAnimationPropertyConfig("__internal_fadeCTM"), AVARDAMAGE_NONE);
progress.setValueAndWarp(0.F);
} }
void CHyprlandCTMControlProtocol::setCTM(PHLMONITOR monitor, const Mat3x3& ctm) { void CHyprlandCTMControlProtocol::setCTM(PHLMONITOR monitor, const Mat3x3& ctm) {
@ -112,18 +112,18 @@ void CHyprlandCTMControlProtocol::setCTM(PHLMONITOR monitor, const Mat3x3& ctm)
data->ctmFrom = data->ctmTo; data->ctmFrom = data->ctmTo;
data->ctmTo = ctm; data->ctmTo = ctm;
data->progress.setValueAndWarp(0.F); data->progress->setValueAndWarp(0.F);
data->progress = 1.F; *data->progress = 1.F;
monitor->setCTM(data->ctmFrom); monitor->setCTM(data->ctmFrom);
data->progress.setUpdateCallback([monitor = PHLMONITORREF{monitor}, this](void* self) { data->progress->setUpdateCallback([monitor = PHLMONITORREF{monitor}, this](auto) {
if (!monitor || !m_mCTMDatas.contains(monitor)) if (!monitor || !m_mCTMDatas.contains(monitor))
return; return;
auto& data = m_mCTMDatas.at(monitor); auto& data = m_mCTMDatas.at(monitor);
const auto from = data->ctmFrom.getMatrix(); const auto from = data->ctmFrom.getMatrix();
const auto to = data->ctmTo.getMatrix(); const auto to = data->ctmTo.getMatrix();
const auto PROGRESS = data->progress.getPercent(); const auto PROGRESS = data->progress->getPercent();
static const auto lerp = [](const float one, const float two, const float progress) -> float { return one + (two - one) * progress; }; static const auto lerp = [](const float one, const float two, const float progress) -> float { return one + (two - one) * progress; };
@ -135,7 +135,7 @@ void CHyprlandCTMControlProtocol::setCTM(PHLMONITOR monitor, const Mat3x3& ctm)
monitor->setCTM(mtx); monitor->setCTM(mtx);
}); });
data->progress.setCallbackOnEnd([monitor = PHLMONITORREF{monitor}, this](void* self) { data->progress->setCallbackOnEnd([monitor = PHLMONITORREF{monitor}, this](auto) {
if (!monitor || !m_mCTMDatas.contains(monitor)) { if (!monitor || !m_mCTMDatas.contains(monitor)) {
monitor->setCTM(Mat3x3::identity()); monitor->setCTM(Mat3x3::identity());
return; return;

View file

@ -43,7 +43,7 @@ class CHyprlandCTMControlProtocol : public IWaylandProtocol {
struct SCTMData { struct SCTMData {
SCTMData(); SCTMData();
Mat3x3 ctmFrom = Mat3x3::identity(), ctmTo = Mat3x3::identity(); Mat3x3 ctmFrom = Mat3x3::identity(), ctmTo = Mat3x3::identity();
CAnimatedVariable<float> progress; PHLANIMVAR<float> progress;
}; };
std::map<PHLMONITORREF, std::unique_ptr<SCTMData>> m_mCTMDatas; std::map<PHLMONITORREF, std::unique_ptr<SCTMData>> m_mCTMDatas;

View file

@ -0,0 +1,571 @@
#include "ColorManagement.hpp"
#include "Compositor.hpp"
CColorManager::CColorManager(SP<CXxColorManagerV4> resource_) : resource(resource_) {
if (!good())
return;
resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_PARAMETRIC);
resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_EXTENDED_TARGET_VOLUME);
resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES);
resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_SET_PRIMARIES);
resource->sendSupportedFeature(XX_COLOR_MANAGER_V4_FEATURE_SET_LUMINANCES);
resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_SRGB);
// resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_PAL_M);
// resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_PAL);
// resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_NTSC);
// resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_GENERIC_FILM);
resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_BT2020);
// resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_CIE1931_XYZ);
// resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_DCI_P3);
// resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_DISPLAY_P3);
// resource->sendSupportedPrimariesNamed(XX_COLOR_MANAGER_V4_PRIMARIES_ADOBE_RGB);
// resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_GAMMA22);
resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB);
resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ);
// resource->sendSupportedTfNamed(XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_LINEAR);
resource->sendSupportedIntent(XX_COLOR_MANAGER_V4_RENDER_INTENT_PERCEPTUAL);
// resource->sendSupportedIntent(XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE);
// resource->sendSupportedIntent(XX_COLOR_MANAGER_V4_RENDER_INTENT_ABSOLUTE);
// resource->sendSupportedIntent(XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE_BPC);
resource->setDestroy([](CXxColorManagerV4* r) { LOGM(TRACE, "Destroy xx_color_manager at {:x} (generated default)", (uintptr_t)r); });
resource->setGetOutput([](CXxColorManagerV4* r, uint32_t id, wl_resource* output) {
LOGM(TRACE, "Get output for id={}, output={}", id, (uintptr_t)output);
const auto RESOURCE =
PROTO::colorManagement->m_vOutputs.emplace_back(makeShared<CColorManagementOutput>(makeShared<CXxColorManagementOutputV4>(r->client(), r->version(), id)));
if (!RESOURCE->good()) {
r->noMemory();
PROTO::colorManagement->m_vOutputs.pop_back();
return;
}
RESOURCE->self = RESOURCE;
});
resource->setGetSurface([](CXxColorManagerV4* r, uint32_t id, wl_resource* surface) {
LOGM(TRACE, "Get surface for id={}, surface={}", id, (uintptr_t)surface);
auto SURF = CWLSurfaceResource::fromResource(surface);
if (!SURF) {
LOGM(ERR, "No surface for resource {}", (uintptr_t)surface);
r->error(-1, "Invalid surface (2)");
return;
}
if (SURF->colorManagement) {
r->error(XX_COLOR_MANAGER_V4_ERROR_SURFACE_EXISTS, "CM Surface already exists");
return;
}
const auto RESOURCE =
PROTO::colorManagement->m_vSurfaces.emplace_back(makeShared<CColorManagementSurface>(makeShared<CXxColorManagementSurfaceV4>(r->client(), r->version(), id), SURF));
if (!RESOURCE->good()) {
r->noMemory();
PROTO::colorManagement->m_vSurfaces.pop_back();
return;
}
RESOURCE->self = RESOURCE;
SURF->colorManagement = RESOURCE;
});
resource->setGetFeedbackSurface([](CXxColorManagerV4* r, uint32_t id, wl_resource* surface) {
LOGM(TRACE, "Get feedback surface for id={}, surface={}", id, (uintptr_t)surface);
auto SURF = CWLSurfaceResource::fromResource(surface);
if (!SURF) {
LOGM(ERR, "No surface for resource {}", (uintptr_t)surface);
r->error(-1, "Invalid surface (2)");
return;
}
const auto RESOURCE = PROTO::colorManagement->m_vFeedbackSurfaces.emplace_back(
makeShared<CColorManagementFeedbackSurface>(makeShared<CXxColorManagementFeedbackSurfaceV4>(r->client(), r->version(), id), SURF));
if (!RESOURCE->good()) {
r->noMemory();
PROTO::colorManagement->m_vFeedbackSurfaces.pop_back();
return;
}
RESOURCE->self = RESOURCE;
});
resource->setNewIccCreator([](CXxColorManagerV4* r, uint32_t id) {
LOGM(WARN, "New ICC creator for id={} (unsupported)", id);
r->error(XX_COLOR_MANAGER_V4_ERROR_UNSUPPORTED_FEATURE, "ICC profiles are not supported");
});
resource->setNewParametricCreator([](CXxColorManagerV4* r, uint32_t id) {
LOGM(TRACE, "New parametric creator for id={}", id);
const auto RESOURCE = PROTO::colorManagement->m_vParametricCreators.emplace_back(
makeShared<CColorManagementParametricCreator>(makeShared<CXxImageDescriptionCreatorParamsV4>(r->client(), r->version(), id)));
if (!RESOURCE->good()) {
r->noMemory();
PROTO::colorManagement->m_vParametricCreators.pop_back();
return;
}
RESOURCE->self = RESOURCE;
});
resource->setOnDestroy([this](CXxColorManagerV4* r) { PROTO::colorManagement->destroyResource(this); });
}
bool CColorManager::good() {
return resource->resource();
}
CColorManagementOutput::CColorManagementOutput(SP<CXxColorManagementOutputV4> resource_) : resource(resource_) {
if (!good())
return;
pClient = resource->client();
resource->setDestroy([this](CXxColorManagementOutputV4* r) { PROTO::colorManagement->destroyResource(this); });
resource->setOnDestroy([this](CXxColorManagementOutputV4* r) { PROTO::colorManagement->destroyResource(this); });
resource->setGetImageDescription([this](CXxColorManagementOutputV4* r, uint32_t id) {
LOGM(TRACE, "Get image description for output={}, id={}", (uintptr_t)r, id);
if (imageDescription.valid())
PROTO::colorManagement->destroyResource(imageDescription.get());
const auto RESOURCE = PROTO::colorManagement->m_vImageDescriptions.emplace_back(
makeShared<CColorManagementImageDescription>(makeShared<CXxImageDescriptionV4>(r->client(), r->version(), id)));
if (!RESOURCE->good()) {
r->noMemory();
PROTO::colorManagement->m_vImageDescriptions.pop_back();
return;
}
RESOURCE->self = RESOURCE;
});
}
bool CColorManagementOutput::good() {
return resource->resource();
}
wl_client* CColorManagementOutput::client() {
return pClient;
}
CColorManagementSurface::CColorManagementSurface(SP<CWLSurfaceResource> surface_) : surface(surface_) {
// only for frog cm untill wayland cm is adopted
}
CColorManagementSurface::CColorManagementSurface(SP<CXxColorManagementSurfaceV4> resource_, SP<CWLSurfaceResource> surface_) : surface(surface_), resource(resource_) {
if (!good())
return;
pClient = resource->client();
resource->setDestroy([this](CXxColorManagementSurfaceV4* r) {
LOGM(TRACE, "Destroy xx cm surface {}", (uintptr_t)surface);
PROTO::colorManagement->destroyResource(this);
});
resource->setOnDestroy([this](CXxColorManagementSurfaceV4* r) {
LOGM(TRACE, "Destroy xx cm surface {}", (uintptr_t)surface);
PROTO::colorManagement->destroyResource(this);
});
resource->setSetImageDescription([this](CXxColorManagementSurfaceV4* r, wl_resource* image_description, uint32_t render_intent) {
LOGM(TRACE, "Set image description for surface={}, desc={}, intent={}", (uintptr_t)r, (uintptr_t)image_description, render_intent);
const auto PO = (CXxImageDescriptionV4*)wl_resource_get_user_data(image_description);
if (!PO) { // FIXME check validity
r->error(XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_IMAGE_DESCRIPTION, "Image description creation failed");
return;
}
if (render_intent != XX_COLOR_MANAGER_V4_RENDER_INTENT_PERCEPTUAL) {
r->error(XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_RENDER_INTENT, "Unsupported render intent");
return;
}
const auto imageDescription = std::find_if(PROTO::colorManagement->m_vImageDescriptions.begin(), PROTO::colorManagement->m_vImageDescriptions.end(),
[&](const auto& other) { return other->resource()->resource() == image_description; });
if (imageDescription == PROTO::colorManagement->m_vImageDescriptions.end()) {
r->error(XX_COLOR_MANAGEMENT_SURFACE_V4_ERROR_IMAGE_DESCRIPTION, "Image description not found");
return;
}
m_hasImageDescription = true;
m_imageDescription = imageDescription->get()->settings;
});
resource->setUnsetImageDescription([this](CXxColorManagementSurfaceV4* r) {
LOGM(TRACE, "Unset image description for surface={}", (uintptr_t)r);
m_imageDescription = SImageDescription{};
m_hasImageDescription = false;
});
}
bool CColorManagementSurface::good() {
return resource && resource->resource();
}
wl_client* CColorManagementSurface::client() {
return pClient;
}
const SImageDescription& CColorManagementSurface::imageDescription() {
if (!hasImageDescription())
LOGM(WARN, "Reading imageDescription while none set. Returns default or empty values");
return m_imageDescription;
}
bool CColorManagementSurface::hasImageDescription() {
return m_hasImageDescription;
}
CColorManagementFeedbackSurface::CColorManagementFeedbackSurface(SP<CXxColorManagementFeedbackSurfaceV4> resource_, SP<CWLSurfaceResource> surface_) :
surface(surface_), resource(resource_) {
if (!good())
return;
pClient = resource->client();
resource->setDestroy([this](CXxColorManagementFeedbackSurfaceV4* r) {
LOGM(TRACE, "Destroy xx cm feedback surface {}", (uintptr_t)surface);
if (m_currentPreferred.valid())
PROTO::colorManagement->destroyResource(m_currentPreferred.get());
PROTO::colorManagement->destroyResource(this);
});
resource->setOnDestroy([this](CXxColorManagementFeedbackSurfaceV4* r) {
LOGM(TRACE, "Destroy xx cm feedback surface {}", (uintptr_t)surface);
if (m_currentPreferred.valid())
PROTO::colorManagement->destroyResource(m_currentPreferred.get());
PROTO::colorManagement->destroyResource(this);
});
resource->setGetPreferred([this](CXxColorManagementFeedbackSurfaceV4* r, uint32_t id) {
LOGM(TRACE, "Get preferred for id {}", id);
if (m_currentPreferred.valid())
PROTO::colorManagement->destroyResource(m_currentPreferred.get());
const auto RESOURCE = PROTO::colorManagement->m_vImageDescriptions.emplace_back(
makeShared<CColorManagementImageDescription>(makeShared<CXxImageDescriptionV4>(r->client(), r->version(), id), true));
if (!RESOURCE->good()) {
r->noMemory();
PROTO::colorManagement->m_vImageDescriptions.pop_back();
return;
}
RESOURCE->self = RESOURCE;
m_currentPreferred = RESOURCE;
m_currentPreferred->settings = g_pCompositor->getPreferredImageDescription();
RESOURCE->resource()->sendReady(id);
});
}
bool CColorManagementFeedbackSurface::good() {
return resource->resource();
}
wl_client* CColorManagementFeedbackSurface::client() {
return pClient;
}
CColorManagementParametricCreator::CColorManagementParametricCreator(SP<CXxImageDescriptionCreatorParamsV4> resource_) : resource(resource_) {
if (!good())
return;
//
pClient = resource->client();
resource->setOnDestroy([this](CXxImageDescriptionCreatorParamsV4* r) { PROTO::colorManagement->destroyResource(this); });
resource->setCreate([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t id) {
LOGM(TRACE, "Create image description from params for id {}", id);
// FIXME actually check completeness
if (!valuesSet) {
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INCOMPLETE_SET, "Missing required settings");
return;
}
// FIXME actually check consistency
if (!valuesSet) {
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INCONSISTENT_SET, "Set is not consistent");
return;
}
const auto RESOURCE = PROTO::colorManagement->m_vImageDescriptions.emplace_back(
makeShared<CColorManagementImageDescription>(makeShared<CXxImageDescriptionV4>(r->client(), r->version(), id)));
if (!RESOURCE->good()) {
r->noMemory();
PROTO::colorManagement->m_vImageDescriptions.pop_back();
return;
}
// FIXME actually check support
if (!valuesSet) {
RESOURCE->resource()->sendFailed(XX_IMAGE_DESCRIPTION_V4_CAUSE_UNSUPPORTED, "unsupported");
return;
}
RESOURCE->self = RESOURCE;
RESOURCE->settings = settings;
RESOURCE->resource()->sendReady(id);
PROTO::colorManagement->destroyResource(this);
});
resource->setSetTfNamed([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t tf) {
LOGM(TRACE, "Set image description transfer function to {}", tf);
if (valuesSet & PC_TF) {
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Transfer function already set");
return;
}
switch (tf) {
case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB: break;
case XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ: break;
default: r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INVALID_TF, "Unsupported transfer function"); return;
}
settings.transferFunction = (xxColorManagerV4TransferFunction)tf;
valuesSet |= PC_TF;
});
resource->setSetTfPower([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t eexp) {
LOGM(TRACE, "Set image description tf power to {}", eexp);
if (valuesSet & PC_TF_POWER) {
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Transfer function power already set");
return;
}
settings.transferFunctionPower = eexp / 10000.0f;
valuesSet |= PC_TF_POWER;
});
resource->setSetPrimariesNamed([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t primaries) {
LOGM(TRACE, "Set image description primaries by name {}", primaries);
if (valuesSet & PC_PRIMARIES) {
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Primaries already set");
return;
}
switch (primaries) {
case XX_COLOR_MANAGER_V4_PRIMARIES_SRGB:
settings.primariesNameSet = true;
settings.primariesNamed = XX_COLOR_MANAGER_V4_PRIMARIES_SRGB;
settings.primaries = NColorPrimaries::BT709;
valuesSet |= PC_PRIMARIES;
break;
case XX_COLOR_MANAGER_V4_PRIMARIES_BT2020:
settings.primariesNameSet = true;
settings.primariesNamed = XX_COLOR_MANAGER_V4_PRIMARIES_BT2020;
settings.primaries = NColorPrimaries::BT2020;
valuesSet |= PC_PRIMARIES;
break;
default: r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INVALID_PRIMARIES, "Unsupported primaries");
}
});
resource->setSetPrimaries(
[this](CXxImageDescriptionCreatorParamsV4* r, int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, int32_t b_x, int32_t b_y, int32_t w_x, int32_t w_y) {
LOGM(TRACE, "Set image description primaries by values r:{},{} g:{},{} b:{},{} w:{},{}", r_x, r_y, g_x, g_y, b_x, b_y, w_x, w_y);
if (valuesSet & PC_PRIMARIES) {
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Primaries already set");
return;
}
settings.primariesNameSet = false;
settings.primaries =
SImageDescription::SPCPRimaries{.red = {.x = r_x, .y = r_y}, .green = {.x = g_x, .y = g_y}, .blue = {.x = b_x, .y = b_y}, .white = {.x = w_x, .y = w_y}};
valuesSet |= PC_PRIMARIES;
});
resource->setSetLuminances([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t min_lum, uint32_t max_lum, uint32_t reference_lum) {
auto min = min_lum / 10000.0f;
LOGM(TRACE, "Set image description luminances to {} - {} ({})", min, max_lum, reference_lum);
if (valuesSet & PC_LUMINANCES) {
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Luminances already set");
return;
}
if (max_lum < reference_lum || reference_lum <= min) {
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INVALID_LUMINANCE, "Invalid luminances");
return;
}
settings.luminances = SImageDescription::SPCLuminances{.min = min, .max = max_lum, .reference = reference_lum};
valuesSet |= PC_LUMINANCES;
});
resource->setSetMasteringDisplayPrimaries(
[this](CXxImageDescriptionCreatorParamsV4* r, int32_t r_x, int32_t r_y, int32_t g_x, int32_t g_y, int32_t b_x, int32_t b_y, int32_t w_x, int32_t w_y) {
LOGM(TRACE, "Set image description mastering primaries by values r:{},{} g:{},{} b:{},{} w:{},{}", r_x, r_y, g_x, g_y, b_x, b_y, w_x, w_y);
// if (valuesSet & PC_MASTERING_PRIMARIES) {
// r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Mastering primaries already set");
// return;
// }
settings.masteringPrimaries =
SImageDescription::SPCPRimaries{.red = {.x = r_x, .y = r_y}, .green = {.x = g_x, .y = g_y}, .blue = {.x = b_x, .y = b_y}, .white = {.x = w_x, .y = w_y}};
valuesSet |= PC_MASTERING_PRIMARIES;
});
resource->setSetMasteringLuminance([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t min_lum, uint32_t max_lum) {
auto min = min_lum / 10000.0f;
LOGM(TRACE, "Set image description mastering luminances to {} - {}", min, max_lum);
// if (valuesSet & PC_MASTERING_LUMINANCES) {
// r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Mastering luminances already set");
// return;
// }
if (min > 0 && max_lum > 0 && max_lum <= min) {
r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_INVALID_LUMINANCE, "Invalid luminances");
return;
}
settings.masteringLuminances = SImageDescription::SPCMasteringLuminances{.min = min, .max = max_lum};
valuesSet |= PC_MASTERING_LUMINANCES;
});
resource->setSetMaxCll([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t max_cll) {
LOGM(TRACE, "Set image description max content light level to {}", max_cll);
// if (valuesSet & PC_CLL) {
// r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Max CLL already set");
// return;
// }
settings.maxCLL = max_cll;
valuesSet |= PC_CLL;
});
resource->setSetMaxFall([this](CXxImageDescriptionCreatorParamsV4* r, uint32_t max_fall) {
LOGM(TRACE, "Set image description max frame-average light level to {}", max_fall);
// if (valuesSet & PC_FALL) {
// r->error(XX_IMAGE_DESCRIPTION_CREATOR_PARAMS_V4_ERROR_ALREADY_SET, "Max FALL already set");
// return;
// }
settings.maxFALL = max_fall;
valuesSet |= PC_FALL;
});
}
bool CColorManagementParametricCreator::good() {
return resource->resource();
}
wl_client* CColorManagementParametricCreator::client() {
return pClient;
}
CColorManagementImageDescription::CColorManagementImageDescription(SP<CXxImageDescriptionV4> resource_, bool allowGetInformation) :
m_resource(resource_), m_allowGetInformation(allowGetInformation) {
if (!good())
return;
pClient = m_resource->client();
m_resource->setDestroy([this](CXxImageDescriptionV4* r) { PROTO::colorManagement->destroyResource(this); });
m_resource->setOnDestroy([this](CXxImageDescriptionV4* r) { PROTO::colorManagement->destroyResource(this); });
m_resource->setGetInformation([this](CXxImageDescriptionV4* r, uint32_t id) {
LOGM(TRACE, "Get image information for image={}, id={}", (uintptr_t)r, id);
if (!m_allowGetInformation) {
r->error(XX_IMAGE_DESCRIPTION_V4_ERROR_NO_INFORMATION, "Image descriptions doesn't allow get_information request");
return;
}
auto RESOURCE = makeShared<CColorManagementImageDescriptionInfo>(makeShared<CXxImageDescriptionInfoV4>(r->client(), r->version(), id), settings);
if (!RESOURCE->good())
r->noMemory();
// CColorManagementImageDescriptionInfo should send everything in the constructor and be ready for destroying at this point
RESOURCE.reset();
});
}
bool CColorManagementImageDescription::good() {
return m_resource->resource();
}
wl_client* CColorManagementImageDescription::client() {
return pClient;
}
SP<CXxImageDescriptionV4> CColorManagementImageDescription::resource() {
return m_resource;
}
CColorManagementImageDescriptionInfo::CColorManagementImageDescriptionInfo(SP<CXxImageDescriptionInfoV4> resource_, const SImageDescription& settings_) :
m_resource(resource_), settings(settings_) {
if (!good())
return;
pClient = m_resource->client();
const auto toProto = [](float value) { return int32_t(std::round(value * 10000)); };
if (settings.iccFd >= 0)
m_resource->sendIccFile(settings.iccFd, settings.iccSize);
// send preferred client paramateres
m_resource->sendPrimaries(toProto(settings.primaries.red.x), toProto(settings.primaries.red.y), toProto(settings.primaries.green.x), toProto(settings.primaries.green.y),
toProto(settings.primaries.blue.x), toProto(settings.primaries.blue.y), toProto(settings.primaries.white.x), toProto(settings.primaries.white.y));
if (settings.primariesNameSet)
m_resource->sendPrimariesNamed(settings.primariesNamed);
m_resource->sendTfPower(std::round(settings.transferFunctionPower * 10000));
m_resource->sendTfNamed(settings.transferFunction);
m_resource->sendLuminances(std::round(settings.luminances.min * 10000), settings.luminances.max, settings.luminances.reference);
// send expexted display paramateres
m_resource->sendTargetPrimaries(toProto(settings.masteringPrimaries.red.x), toProto(settings.masteringPrimaries.red.y), toProto(settings.masteringPrimaries.green.x),
toProto(settings.masteringPrimaries.green.y), toProto(settings.masteringPrimaries.blue.x), toProto(settings.masteringPrimaries.blue.y),
toProto(settings.masteringPrimaries.white.x), toProto(settings.masteringPrimaries.white.y));
m_resource->sendTargetLuminance(std::round(settings.masteringLuminances.min * 10000), settings.masteringLuminances.max);
m_resource->sendTargetMaxCll(settings.maxCLL);
m_resource->sendTargetMaxFall(settings.maxFALL);
m_resource->sendDone();
}
bool CColorManagementImageDescriptionInfo::good() {
return m_resource->resource();
}
wl_client* CColorManagementImageDescriptionInfo::client() {
return pClient;
}
CColorManagementProtocol::CColorManagementProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
;
}
void CColorManagementProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
const auto RESOURCE = m_vManagers.emplace_back(makeShared<CColorManager>(makeShared<CXxColorManagerV4>(client, ver, id)));
if (!RESOURCE->good()) {
wl_client_post_no_memory(client);
m_vManagers.pop_back();
return;
}
LOGM(TRACE, "New xx_color_manager at {:x}", (uintptr_t)RESOURCE.get());
}
void CColorManagementProtocol::onImagePreferredChanged() {
for (auto const& feedback : m_vFeedbackSurfaces) {
feedback->resource->sendPreferredChanged();
}
}
void CColorManagementProtocol::destroyResource(CColorManager* resource) {
std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == resource; });
}
void CColorManagementProtocol::destroyResource(CColorManagementOutput* resource) {
std::erase_if(m_vOutputs, [&](const auto& other) { return other.get() == resource; });
}
void CColorManagementProtocol::destroyResource(CColorManagementSurface* resource) {
std::erase_if(m_vSurfaces, [&](const auto& other) { return other.get() == resource; });
}
void CColorManagementProtocol::destroyResource(CColorManagementFeedbackSurface* resource) {
std::erase_if(m_vFeedbackSurfaces, [&](const auto& other) { return other.get() == resource; });
}
void CColorManagementProtocol::destroyResource(CColorManagementParametricCreator* resource) {
std::erase_if(m_vParametricCreators, [&](const auto& other) { return other.get() == resource; });
}
void CColorManagementProtocol::destroyResource(CColorManagementImageDescription* resource) {
std::erase_if(m_vImageDescriptions, [&](const auto& other) { return other.get() == resource; });
}

View file

@ -0,0 +1,182 @@
#pragma once
#include <memory>
#include <vector>
#include <cstdint>
#include "WaylandProtocol.hpp"
#include "protocols/core/Compositor.hpp"
#include "xx-color-management-v4.hpp"
#include "types/ColorManagement.hpp"
class CColorManager;
class CColorManagementOutput;
class CColorManagementImageDescription;
class CColorManagementProtocol;
class CColorManager {
public:
CColorManager(SP<CXxColorManagerV4> resource_);
bool good();
private:
SP<CXxColorManagerV4> resource;
};
class CColorManagementOutput {
public:
CColorManagementOutput(SP<CXxColorManagementOutputV4> resource_);
bool good();
wl_client* client();
WP<CColorManagementOutput> self;
WP<CColorManagementImageDescription> imageDescription;
private:
SP<CXxColorManagementOutputV4> resource;
wl_client* pClient = nullptr;
friend class CColorManagementProtocol;
friend class CColorManagementImageDescription;
};
class CColorManagementSurface {
public:
CColorManagementSurface(SP<CWLSurfaceResource> surface_); // temporary interface for frog CM
CColorManagementSurface(SP<CXxColorManagementSurfaceV4> resource_, SP<CWLSurfaceResource> surface_);
bool good();
wl_client* client();
WP<CColorManagementSurface> self;
WP<CWLSurfaceResource> surface;
const SImageDescription& imageDescription();
bool hasImageDescription();
private:
SP<CXxColorManagementSurfaceV4> resource;
wl_client* pClient = nullptr;
SImageDescription m_imageDescription;
bool m_hasImageDescription = false;
friend class CFrogColorManagementSurface;
};
class CColorManagementFeedbackSurface {
public:
CColorManagementFeedbackSurface(SP<CXxColorManagementFeedbackSurfaceV4> resource_, SP<CWLSurfaceResource> surface_);
bool good();
wl_client* client();
WP<CColorManagementFeedbackSurface> self;
WP<CWLSurfaceResource> surface;
private:
SP<CXxColorManagementFeedbackSurfaceV4> resource;
wl_client* pClient = nullptr;
WP<CColorManagementImageDescription> m_currentPreferred;
friend class CColorManagementProtocol;
};
class CColorManagementParametricCreator {
public:
CColorManagementParametricCreator(SP<CXxImageDescriptionCreatorParamsV4> resource_);
bool good();
wl_client* client();
WP<CColorManagementParametricCreator> self;
SImageDescription settings;
private:
enum eValuesSet : uint32_t { // NOLINT
PC_TF = (1 << 0),
PC_TF_POWER = (1 << 1),
PC_PRIMARIES = (1 << 2),
PC_LUMINANCES = (1 << 3),
PC_MASTERING_PRIMARIES = (1 << 4),
PC_MASTERING_LUMINANCES = (1 << 5),
PC_CLL = (1 << 6),
PC_FALL = (1 << 7),
};
SP<CXxImageDescriptionCreatorParamsV4> resource;
wl_client* pClient = nullptr;
uint32_t valuesSet = 0; // enum eValuesSet
};
class CColorManagementImageDescription {
public:
CColorManagementImageDescription(SP<CXxImageDescriptionV4> resource_, bool allowGetInformation = false);
bool good();
wl_client* client();
SP<CXxImageDescriptionV4> resource();
WP<CColorManagementImageDescription> self;
SImageDescription settings;
private:
SP<CXxImageDescriptionV4> m_resource;
wl_client* pClient = nullptr;
bool m_allowGetInformation = false;
friend class CColorManagementOutput;
};
class CColorManagementImageDescriptionInfo {
public:
CColorManagementImageDescriptionInfo(SP<CXxImageDescriptionInfoV4> resource_, const SImageDescription& settings_);
bool good();
wl_client* client();
private:
SP<CXxImageDescriptionInfoV4> m_resource;
wl_client* pClient = nullptr;
SImageDescription settings;
};
class CColorManagementProtocol : public IWaylandProtocol {
public:
CColorManagementProtocol(const wl_interface* iface, const int& ver, const std::string& name);
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
void onImagePreferredChanged();
private:
void destroyResource(CColorManager* resource);
void destroyResource(CColorManagementOutput* resource);
void destroyResource(CColorManagementSurface* resource);
void destroyResource(CColorManagementFeedbackSurface* resource);
void destroyResource(CColorManagementParametricCreator* resource);
void destroyResource(CColorManagementImageDescription* resource);
std::vector<SP<CColorManager>> m_vManagers;
std::vector<SP<CColorManagementOutput>> m_vOutputs;
std::vector<SP<CColorManagementSurface>> m_vSurfaces;
std::vector<SP<CColorManagementFeedbackSurface>> m_vFeedbackSurfaces;
std::vector<SP<CColorManagementParametricCreator>> m_vParametricCreators;
std::vector<SP<CColorManagementImageDescription>> m_vImageDescriptions;
friend class CColorManager;
friend class CColorManagementOutput;
friend class CColorManagementSurface;
friend class CColorManagementFeedbackSurface;
friend class CColorManagementParametricCreator;
friend class CColorManagementImageDescription;
friend class CFrogColorManagementSurface;
};
namespace PROTO {
inline UP<CColorManagementProtocol> colorManagement;
};

View file

@ -0,0 +1,159 @@
#include "FrogColorManagement.hpp"
#include "protocols/ColorManagement.hpp"
#include "protocols/core/Subcompositor.hpp"
CFrogColorManager::CFrogColorManager(SP<CFrogColorManagementFactoryV1> resource_) : resource(resource_) {
if (!good())
return;
resource->setDestroy([](CFrogColorManagementFactoryV1* r) { LOGM(TRACE, "Destroy frog_color_management at {:x} (generated default)", (uintptr_t)r); });
resource->setOnDestroy([this](CFrogColorManagementFactoryV1* r) { PROTO::frogColorManagement->destroyResource(this); });
resource->setGetColorManagedSurface([](CFrogColorManagementFactoryV1* r, wl_resource* surface, uint32_t id) {
LOGM(TRACE, "Get surface for id={}, surface={}", id, (uintptr_t)surface);
auto SURF = CWLSurfaceResource::fromResource(surface);
if (!SURF) {
LOGM(ERR, "No surface for resource {}", (uintptr_t)surface);
r->error(-1, "Invalid surface (2)");
return;
}
if (SURF->role->role() == SURFACE_ROLE_SUBSURFACE)
SURF = ((CSubsurfaceRole*)SURF->role.get())->subsurface->t1Parent();
const auto RESOURCE = PROTO::frogColorManagement->m_vSurfaces.emplace_back(
makeShared<CFrogColorManagementSurface>(makeShared<CFrogColorManagedSurface>(r->client(), r->version(), id), SURF));
if (!RESOURCE->good()) {
r->noMemory();
PROTO::frogColorManagement->m_vSurfaces.pop_back();
return;
}
RESOURCE->self = RESOURCE;
});
}
bool CFrogColorManager::good() {
return resource->resource();
}
CFrogColorManagementSurface::CFrogColorManagementSurface(SP<CFrogColorManagedSurface> resource_, SP<CWLSurfaceResource> surface_) : surface(surface_), resource(resource_) {
if (!good())
return;
pClient = resource->client();
if (!surface->colorManagement.valid()) {
const auto RESOURCE = PROTO::colorManagement->m_vSurfaces.emplace_back(makeShared<CColorManagementSurface>(surface_));
if (!RESOURCE) {
resource->noMemory();
PROTO::colorManagement->m_vSurfaces.pop_back();
return;
}
RESOURCE->self = RESOURCE;
surface->colorManagement = RESOURCE;
resource->setOnDestroy([this](CFrogColorManagedSurface* r) {
LOGM(TRACE, "Destroy frog cm and xx cm for surface {}", (uintptr_t)surface);
if (surface.valid())
PROTO::colorManagement->destroyResource(surface->colorManagement.get());
PROTO::frogColorManagement->destroyResource(this);
});
} else
resource->setOnDestroy([this](CFrogColorManagedSurface* r) {
LOGM(TRACE, "Destroy frog cm surface {}", (uintptr_t)surface);
PROTO::frogColorManagement->destroyResource(this);
});
resource->setDestroy([this](CFrogColorManagedSurface* r) {
LOGM(TRACE, "Destroy frog cm surface {}", (uintptr_t)surface);
PROTO::frogColorManagement->destroyResource(this);
});
resource->setSetKnownTransferFunction([this](CFrogColorManagedSurface* r, frogColorManagedSurfaceTransferFunction tf) {
LOGM(TRACE, "Set frog cm transfer function {} for {}", (uint32_t)tf, surface->id());
switch (tf) {
case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_ST2084_PQ:
surface->colorManagement->m_imageDescription.transferFunction = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ;
break;
;
case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_GAMMA_22:
if (pqIntentSent) {
LOGM(TRACE,
"FIXME: assuming broken enum value 2 (FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_GAMMA_22) referring to eotf value 2 (TRANSFER_FUNCTION_ST2084_PQ)");
surface->colorManagement->m_imageDescription.transferFunction = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ;
break;
}; // intended fall through
case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_UNDEFINED:
case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_SCRGB_LINEAR: LOGM(TRACE, "FIXME: add tf support for {}", (uint32_t)tf); // intended fall through
case FROG_COLOR_MANAGED_SURFACE_TRANSFER_FUNCTION_SRGB:
surface->colorManagement->m_imageDescription.transferFunction = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB;
surface->colorManagement->m_hasImageDescription = true;
}
});
resource->setSetKnownContainerColorVolume([this](CFrogColorManagedSurface* r, frogColorManagedSurfacePrimaries primariesName) {
LOGM(TRACE, "Set frog cm primaries {}", (uint32_t)primariesName);
switch (primariesName) {
case FROG_COLOR_MANAGED_SURFACE_PRIMARIES_UNDEFINED:
case FROG_COLOR_MANAGED_SURFACE_PRIMARIES_REC709: surface->colorManagement->m_imageDescription.primaries = NColorPrimaries::BT709; break;
case FROG_COLOR_MANAGED_SURFACE_PRIMARIES_REC2020: surface->colorManagement->m_imageDescription.primaries = NColorPrimaries::BT2020; break;
}
surface->colorManagement->m_hasImageDescription = true;
});
resource->setSetRenderIntent([this](CFrogColorManagedSurface* r, frogColorManagedSurfaceRenderIntent intent) {
LOGM(TRACE, "Set frog cm intent {}", (uint32_t)intent);
pqIntentSent = intent == FROG_COLOR_MANAGED_SURFACE_RENDER_INTENT_PERCEPTUAL;
surface->colorManagement->m_hasImageDescription = true;
});
resource->setSetHdrMetadata([this](CFrogColorManagedSurface* r, uint32_t r_x, uint32_t r_y, uint32_t g_x, uint32_t g_y, uint32_t b_x, uint32_t b_y, uint32_t w_x, uint32_t w_y,
uint32_t max_lum, uint32_t min_lum, uint32_t cll, uint32_t fall) {
LOGM(TRACE, "Set frog primaries r:{},{} g:{},{} b:{},{} w:{},{} luminances {} - {} cll {} fall {}", r_x, r_y, g_x, g_y, b_x, b_y, w_x, w_y, min_lum, max_lum, cll, fall);
surface->colorManagement->m_imageDescription.masteringPrimaries = SImageDescription::SPCPRimaries{.red = {.x = r_x / 50000.0f, .y = r_y / 50000.0f},
.green = {.x = g_x / 50000.0f, .y = g_y / 50000.0f},
.blue = {.x = b_x / 50000.0f, .y = b_y / 50000.0f},
.white = {.x = w_x / 50000.0f, .y = w_y / 50000.0f}};
surface->colorManagement->m_imageDescription.masteringLuminances.min = min_lum / 10000.0f;
surface->colorManagement->m_imageDescription.masteringLuminances.max = max_lum;
surface->colorManagement->m_imageDescription.maxCLL = cll;
surface->colorManagement->m_imageDescription.maxFALL = fall;
surface->colorManagement->m_hasImageDescription = true;
});
}
bool CFrogColorManagementSurface::good() {
return resource->resource();
}
wl_client* CFrogColorManagementSurface::client() {
return pClient;
}
CFrogColorManagementProtocol::CFrogColorManagementProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
;
}
void CFrogColorManagementProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
const auto RESOURCE = m_vManagers.emplace_back(makeShared<CFrogColorManager>(makeShared<CFrogColorManagementFactoryV1>(client, ver, id)));
if (!RESOURCE->good()) {
wl_client_post_no_memory(client);
m_vManagers.pop_back();
return;
}
LOGM(TRACE, "New frog_color_management at {:x}", (uintptr_t)RESOURCE.get());
}
void CFrogColorManagementProtocol::destroyResource(CFrogColorManager* resource) {
std::erase_if(m_vManagers, [&](const auto& other) { return other.get() == resource; });
}
void CFrogColorManagementProtocol::destroyResource(CFrogColorManagementSurface* resource) {
std::erase_if(m_vSurfaces, [&](const auto& other) { return other.get() == resource; });
}

View file

@ -0,0 +1,55 @@
#pragma once
#include <memory>
#include <cstdint>
#include "WaylandProtocol.hpp"
#include "protocols/core/Compositor.hpp"
#include "frog-color-management-v1.hpp"
class CFrogColorManager {
public:
CFrogColorManager(SP<CFrogColorManagementFactoryV1> resource_);
bool good();
private:
SP<CFrogColorManagementFactoryV1> resource;
};
class CFrogColorManagementSurface {
public:
CFrogColorManagementSurface(SP<CFrogColorManagedSurface> resource_, SP<CWLSurfaceResource> surface_);
bool good();
wl_client* client();
WP<CFrogColorManagementSurface> self;
WP<CWLSurfaceResource> surface;
bool pqIntentSent = false;
private:
SP<CFrogColorManagedSurface> resource;
wl_client* pClient = nullptr;
};
class CFrogColorManagementProtocol : public IWaylandProtocol {
public:
CFrogColorManagementProtocol(const wl_interface* iface, const int& ver, const std::string& name);
virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
private:
void destroyResource(CFrogColorManager* resource);
void destroyResource(CFrogColorManagementSurface* resource);
std::vector<SP<CFrogColorManager>> m_vManagers;
std::vector<SP<CFrogColorManagementSurface>> m_vSurfaces;
friend class CFrogColorManager;
friend class CFrogColorManagementSurface;
};
namespace PROTO {
inline UP<CFrogColorManagementProtocol> frogColorManagement;
};

View file

@ -119,7 +119,7 @@ CToplevelExportFrame::CToplevelExportFrame(SP<CHyprlandToplevelExportFrameV1> re
dmabufFormat = PMONITOR->output->state->state().drmFormat; dmabufFormat = PMONITOR->output->state->state().drmFormat;
box = {0, 0, (int)(pWindow->m_vRealSize.value().x * PMONITOR->scale), (int)(pWindow->m_vRealSize.value().y * PMONITOR->scale)}; box = {0, 0, (int)(pWindow->m_vRealSize->value().x * PMONITOR->scale), (int)(pWindow->m_vRealSize->value().y * PMONITOR->scale)};
box.transform(wlTransformToHyprutils(PMONITOR->transform), PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y).round(); box.transform(wlTransformToHyprutils(PMONITOR->transform), PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y).round();
@ -263,7 +263,7 @@ bool CToplevelExportFrame::copyShm(timespec* now) {
g_pHyprRenderer->m_bBlockSurfaceFeedback = false; g_pHyprRenderer->m_bBlockSurfaceFeedback = false;
if (overlayCursor) if (overlayCursor)
g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition.value()); g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition->value());
const auto PFORMAT = NFormatUtils::getPixelFormatFromDRM(shm.format); const auto PFORMAT = NFormatUtils::getPixelFormatFromDRM(shm.format);
if (!PFORMAT) { if (!PFORMAT) {
@ -315,7 +315,7 @@ bool CToplevelExportFrame::copyDmabuf(timespec* now) {
g_pHyprRenderer->m_bBlockSurfaceFeedback = false; g_pHyprRenderer->m_bBlockSurfaceFeedback = false;
if (overlayCursor) if (overlayCursor)
g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition.value()); g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition->value());
g_pHyprOpenGL->m_RenderData.blockScreenShader = true; g_pHyprOpenGL->m_RenderData.blockScreenShader = true;
g_pHyprRenderer->endRender(); g_pHyprRenderer->endRender();
@ -386,7 +386,7 @@ void CToplevelExportProtocol::onOutputCommit(PHLMONITOR pMonitor) {
if (pMonitor != PWINDOW->m_pMonitor.lock()) if (pMonitor != PWINDOW->m_pMonitor.lock())
continue; continue;
CBox geometry = {PWINDOW->m_vRealPosition.value().x, PWINDOW->m_vRealPosition.value().y, PWINDOW->m_vRealSize.value().x, PWINDOW->m_vRealSize.value().y}; CBox geometry = {PWINDOW->m_vRealPosition->value().x, PWINDOW->m_vRealPosition->value().y, PWINDOW->m_vRealSize->value().x, PWINDOW->m_vRealSize->value().y};
if (geometry.intersection({pMonitor->vecPosition, pMonitor->vecSize}).empty()) if (geometry.intersection({pMonitor->vecPosition, pMonitor->vecSize}).empty())
continue; continue;

View file

@ -428,6 +428,7 @@ void CWLSurfaceResource::commitPendingState() {
pending.damage.clear(); pending.damage.clear();
pending.bufferDamage.clear(); pending.bufferDamage.clear();
pending.newBuffer = false; pending.newBuffer = false;
dropPendingBuffer(); // at this point current.buffer holds the same SP and we don't use pending anymore
events.roleCommit.emit(); events.roleCommit.emit();
@ -448,10 +449,9 @@ void CWLSurfaceResource::commitPendingState() {
// release the buffer if it's synchronous as update() has done everything thats needed // release the buffer if it's synchronous as update() has done everything thats needed
// so we can let the app know we're done. // so we can let the app know we're done.
if (current.buffer->buffer->isSynchronous()) { // Some clients aren't ready to receive a release this early. Should be fine to release it on the next commitPendingState.
dropCurrentBuffer(); // if (current.buffer->buffer->isSynchronous())
dropPendingBuffer(); // pending atm is just a copied ref of the current, drop it too to send a release // dropCurrentBuffer();
}
} }
// TODO: we should _accumulate_ and not replace above if sync // TODO: we should _accumulate_ and not replace above if sync

View file

@ -25,6 +25,8 @@ class CWLSurfaceResource;
class CWLSubsurfaceResource; class CWLSubsurfaceResource;
class CViewportResource; class CViewportResource;
class CDRMSyncobjSurfaceResource; class CDRMSyncobjSurfaceResource;
class CColorManagementSurface;
class CFrogColorManagementSurface;
class CWLCallbackResource { class CWLCallbackResource {
public: public:
@ -121,6 +123,7 @@ class CWLSurfaceResource {
SP<ISurfaceRole> role; SP<ISurfaceRole> role;
WP<CViewportResource> viewportResource; WP<CViewportResource> viewportResource;
WP<CDRMSyncobjSurfaceResource> syncobj; // may not be present WP<CDRMSyncobjSurfaceResource> syncobj; // may not be present
WP<CColorManagementSurface> colorManagement;
void breadthfirst(std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data); void breadthfirst(std::function<void(SP<CWLSurfaceResource>, const Vector2D&, void*)> fn, void* data);
CRegion accumulateCurrentBufferDamage(); CRegion accumulateCurrentBufferDamage();

View file

@ -417,7 +417,7 @@ void CWLDataDeviceProtocol::destroyResource(CWLDataOfferResource* resource) {
SP<IDataDevice> CWLDataDeviceProtocol::dataDeviceForClient(wl_client* c) { SP<IDataDevice> CWLDataDeviceProtocol::dataDeviceForClient(wl_client* c) {
#ifndef NO_XWAYLAND #ifndef NO_XWAYLAND
if (c == g_pXWayland->pServer->xwaylandClient) if (g_pXWayland->pServer && c == g_pXWayland->pServer->xwaylandClient)
return g_pXWayland->pWM->getDataDevice(); return g_pXWayland->pWM->getDataDevice();
#endif #endif

View file

@ -0,0 +1,47 @@
#pragma once
#include "xx-color-management-v4.hpp"
struct SImageDescription {
int iccFd = -1;
uint32_t iccSize = 0;
xxColorManagerV4TransferFunction transferFunction = XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_SRGB;
float transferFunctionPower = 1.0f;
bool primariesNameSet = false;
xxColorManagerV4Primaries primariesNamed = XX_COLOR_MANAGER_V4_PRIMARIES_SRGB;
// primaries are stored as FP values with the same scale as standard defines (0.0 - 1.0)
// wayland protocol expects int32_t values multiplied by 10000
// drm expects uint16_t values multiplied by 50000
// frog protocol expects drm values
struct SPCPRimaries {
struct {
float x = 0;
float y = 0;
} red, green, blue, white;
} primaries, masteringPrimaries;
// luminances in cd/m²
// protos and drm expect min * 10000
struct SPCLuminances {
float min = 0.2; // 0.2 cd/m²
uint32_t max = 80; // 80 cd/m²
uint32_t reference = 80; // 80 cd/m²
} luminances;
struct SPCMasteringLuminances {
float min = 0;
uint32_t max = 0;
} masteringLuminances;
uint32_t maxCLL = 0;
uint32_t maxFALL = 0;
};
namespace NColorPrimaries {
static const auto BT709 =
SImageDescription::SPCPRimaries{.red = {.x = 0.64, .y = 0.33}, .green = {.x = 0.30, .y = 0.60}, .blue = {.x = 0.15, .y = 0.06}, .white = {.x = 0.3127, .y = 0.3290}};
static const auto BT2020 =
SImageDescription::SPCPRimaries{.red = {.x = 0.708, .y = 0.292}, .green = {.x = 0.170, .y = 0.797}, .blue = {.x = 0.131, .y = 0.046}, .white = {.x = 0.3127, .y = 0.3290}};
}

View file

@ -713,7 +713,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(PHLMONITOR pMonitor) {
if (!ws->m_bIsSpecialWorkspace || ws->m_pMonitor != pMonitor) if (!ws->m_bIsSpecialWorkspace || ws->m_pMonitor != pMonitor)
continue; continue;
if (ws->m_fAlpha.value() == 0) if (ws->m_fAlpha->value() == 0)
continue; continue;
return true; return true;
@ -843,12 +843,10 @@ void CHyprOpenGLImpl::begin(PHLMONITOR pMonitor, const CRegion& damage_, CFrameb
m_RenderData.pCurrentMonData->offloadFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->offloadFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat);
m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat);
m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat); m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat);
m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->output->state->state().drmFormat);
m_RenderData.pCurrentMonData->offloadFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); m_RenderData.pCurrentMonData->offloadFB.addStencil(m_RenderData.pCurrentMonData->stencilTex);
m_RenderData.pCurrentMonData->mirrorFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); m_RenderData.pCurrentMonData->mirrorFB.addStencil(m_RenderData.pCurrentMonData->stencilTex);
m_RenderData.pCurrentMonData->mirrorSwapFB.addStencil(m_RenderData.pCurrentMonData->stencilTex); m_RenderData.pCurrentMonData->mirrorSwapFB.addStencil(m_RenderData.pCurrentMonData->stencilTex);
m_RenderData.pCurrentMonData->offMainFB.addStencil(m_RenderData.pCurrentMonData->stencilTex);
} }
if (m_RenderData.pCurrentMonData->monitorMirrorFB.isAllocated() && m_RenderData.pMonitor->mirrors.empty()) if (m_RenderData.pCurrentMonData->monitorMirrorFB.isAllocated() && m_RenderData.pMonitor->mirrors.empty())
@ -954,6 +952,12 @@ void CHyprOpenGLImpl::end() {
m_RenderData.mainFB = nullptr; m_RenderData.mainFB = nullptr;
m_RenderData.outFB = nullptr; m_RenderData.outFB = nullptr;
// if we dropped to offMain, release it now.
// if there is a plugin constantly using it, this might be a bit slow,
// but I havent seen a single plugin yet use these, so it's better to drop a bit of vram.
if (m_RenderData.pCurrentMonData->offMainFB.isAllocated())
m_RenderData.pCurrentMonData->offMainFB.release();
// check for gl errors // check for gl errors
const GLenum ERR = glGetError(); const GLenum ERR = glGetError();
@ -979,6 +983,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shQUAD.topLeft = glGetUniformLocation(prog, "topLeft"); m_RenderData.pCurrentMonData->m_shQUAD.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shQUAD.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shQUAD.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shQUAD.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shQUAD.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shQUAD.roundingPower = glGetUniformLocation(prog, "roundingPower");
prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBA); prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBA);
m_RenderData.pCurrentMonData->m_shRGBA.program = prog; m_RenderData.pCurrentMonData->m_shRGBA.program = prog;
@ -995,6 +1000,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shRGBA.topLeft = glGetUniformLocation(prog, "topLeft"); m_RenderData.pCurrentMonData->m_shRGBA.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shRGBA.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shRGBA.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shRGBA.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shRGBA.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shRGBA.roundingPower = glGetUniformLocation(prog, "roundingPower");
m_RenderData.pCurrentMonData->m_shRGBA.applyTint = glGetUniformLocation(prog, "applyTint"); m_RenderData.pCurrentMonData->m_shRGBA.applyTint = glGetUniformLocation(prog, "applyTint");
m_RenderData.pCurrentMonData->m_shRGBA.tint = glGetUniformLocation(prog, "tint"); m_RenderData.pCurrentMonData->m_shRGBA.tint = glGetUniformLocation(prog, "tint");
m_RenderData.pCurrentMonData->m_shRGBA.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte"); m_RenderData.pCurrentMonData->m_shRGBA.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte");
@ -1037,6 +1043,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shRGBX.topLeft = glGetUniformLocation(prog, "topLeft"); m_RenderData.pCurrentMonData->m_shRGBX.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shRGBX.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shRGBX.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shRGBX.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shRGBX.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shRGBX.roundingPower = glGetUniformLocation(prog, "roundingPower");
m_RenderData.pCurrentMonData->m_shRGBX.applyTint = glGetUniformLocation(prog, "applyTint"); m_RenderData.pCurrentMonData->m_shRGBX.applyTint = glGetUniformLocation(prog, "applyTint");
m_RenderData.pCurrentMonData->m_shRGBX.tint = glGetUniformLocation(prog, "tint"); m_RenderData.pCurrentMonData->m_shRGBX.tint = glGetUniformLocation(prog, "tint");
@ -1053,6 +1060,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shEXT.topLeft = glGetUniformLocation(prog, "topLeft"); m_RenderData.pCurrentMonData->m_shEXT.topLeft = glGetUniformLocation(prog, "topLeft");
m_RenderData.pCurrentMonData->m_shEXT.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shEXT.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shEXT.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shEXT.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shEXT.roundingPower = glGetUniformLocation(prog, "roundingPower");
m_RenderData.pCurrentMonData->m_shEXT.applyTint = glGetUniformLocation(prog, "applyTint"); m_RenderData.pCurrentMonData->m_shEXT.applyTint = glGetUniformLocation(prog, "applyTint");
m_RenderData.pCurrentMonData->m_shEXT.tint = glGetUniformLocation(prog, "tint"); m_RenderData.pCurrentMonData->m_shEXT.tint = glGetUniformLocation(prog, "tint");
@ -1106,6 +1114,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight"); m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight");
m_RenderData.pCurrentMonData->m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize");
m_RenderData.pCurrentMonData->m_shSHADOW.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shSHADOW.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shSHADOW.roundingPower = glGetUniformLocation(prog, "roundingPower");
m_RenderData.pCurrentMonData->m_shSHADOW.range = glGetUniformLocation(prog, "range"); m_RenderData.pCurrentMonData->m_shSHADOW.range = glGetUniformLocation(prog, "range");
m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower"); m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower");
m_RenderData.pCurrentMonData->m_shSHADOW.color = glGetUniformLocation(prog, "color"); m_RenderData.pCurrentMonData->m_shSHADOW.color = glGetUniformLocation(prog, "color");
@ -1122,6 +1131,7 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed = glGetUniformLocation(prog, "fullSizeUntransformed"); m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed = glGetUniformLocation(prog, "fullSizeUntransformed");
m_RenderData.pCurrentMonData->m_shBORDER1.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shBORDER1.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter = glGetUniformLocation(prog, "radiusOuter"); m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter = glGetUniformLocation(prog, "radiusOuter");
m_RenderData.pCurrentMonData->m_shBORDER1.roundingPower = glGetUniformLocation(prog, "roundingPower");
m_RenderData.pCurrentMonData->m_shBORDER1.gradient = glGetUniformLocation(prog, "gradient"); m_RenderData.pCurrentMonData->m_shBORDER1.gradient = glGetUniformLocation(prog, "gradient");
m_RenderData.pCurrentMonData->m_shBORDER1.gradient2 = glGetUniformLocation(prog, "gradient2"); m_RenderData.pCurrentMonData->m_shBORDER1.gradient2 = glGetUniformLocation(prog, "gradient2");
m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength = glGetUniformLocation(prog, "gradientLength"); m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength = glGetUniformLocation(prog, "gradientLength");
@ -1244,12 +1254,12 @@ void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h
scissor(&box, transform); scissor(&box, transform);
} }
void CHyprOpenGLImpl::renderRect(CBox* box, const CHyprColor& col, int round) { void CHyprOpenGLImpl::renderRect(CBox* box, const CHyprColor& col, int round, float roundingPower) {
if (!m_RenderData.damage.empty()) if (!m_RenderData.damage.empty())
renderRectWithDamage(box, col, m_RenderData.damage, round); renderRectWithDamage(box, col, m_RenderData.damage, round, roundingPower);
} }
void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int round, float blurA, bool xray) { void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int round, float roundingPower, float blurA, bool xray) {
if (m_RenderData.damage.empty()) if (m_RenderData.damage.empty())
return; return;
@ -1271,7 +1281,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int r
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
renderRect(box, CHyprColor(0, 0, 0, 0), round); renderRect(box, CHyprColor(0, 0, 0, 0), round, roundingPower);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 1, 0xFF); glStencilFunc(GL_EQUAL, 1, 0xFF);
@ -1282,7 +1292,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int r
m_bEndFrame = true; // fix transformed m_bEndFrame = true; // fix transformed
const auto SAVEDRENDERMODIF = m_RenderData.renderModif; const auto SAVEDRENDERMODIF = m_RenderData.renderModif;
m_RenderData.renderModif = {}; // fix shit m_RenderData.renderModif = {}; // fix shit
renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, blurA, damage, 0, false, false, false); renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, blurA, damage, 0, 2.0f, false, false, false);
m_bEndFrame = false; m_bEndFrame = false;
m_RenderData.renderModif = SAVEDRENDERMODIF; m_RenderData.renderModif = SAVEDRENDERMODIF;
@ -1293,10 +1303,10 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CHyprColor& col, int r
glStencilFunc(GL_ALWAYS, 1, 0xFF); glStencilFunc(GL_ALWAYS, 1, 0xFF);
scissor((CBox*)nullptr); scissor((CBox*)nullptr);
renderRectWithDamage(box, col, m_RenderData.damage, round); renderRectWithDamage(box, col, m_RenderData.damage, round, roundingPower);
} }
void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, const CRegion& damage, int round) { void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, const CRegion& damage, int round, float roundingPower) {
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
@ -1334,6 +1344,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, con
glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y); glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y);
glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y); glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_RenderData.pCurrentMonData->m_shQUAD.radius, round); glUniform1f(m_RenderData.pCurrentMonData->m_shQUAD.radius, round);
glUniform1f(m_RenderData.pCurrentMonData->m_shQUAD.roundingPower, roundingPower);
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@ -1361,25 +1372,25 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CHyprColor& col, con
scissor((CBox*)nullptr); scissor((CBox*)nullptr);
} }
void CHyprOpenGLImpl::renderTexture(SP<CTexture> tex, CBox* pBox, float alpha, int round, bool discardActive, bool allowCustomUV) { void CHyprOpenGLImpl::renderTexture(SP<CTexture> tex, CBox* pBox, float alpha, int round, float roundingPower, bool discardActive, bool allowCustomUV) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.damage, round, discardActive, false, allowCustomUV, true); renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.damage, round, roundingPower, discardActive, false, allowCustomUV, true);
scissor((CBox*)nullptr); scissor((CBox*)nullptr);
} }
void CHyprOpenGLImpl::renderTextureWithDamage(SP<CTexture> tex, CBox* pBox, const CRegion& damage, float alpha, int round, bool discardActive, bool allowCustomUV, void CHyprOpenGLImpl::renderTextureWithDamage(SP<CTexture> tex, CBox* pBox, const CRegion& damage, float alpha, int round, float roundingPower, bool discardActive,
SP<CSyncTimeline> waitTimeline, uint64_t waitPoint) { bool allowCustomUV, SP<CSyncTimeline> waitTimeline, uint64_t waitPoint) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
renderTextureInternalWithDamage(tex, pBox, alpha, damage, round, discardActive, false, allowCustomUV, true, waitTimeline, waitPoint); renderTextureInternalWithDamage(tex, pBox, alpha, damage, round, roundingPower, discardActive, false, allowCustomUV, true, waitTimeline, waitPoint);
scissor((CBox*)nullptr); scissor((CBox*)nullptr);
} }
void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pBox, float alpha, const CRegion& damage, int round, bool discardActive, bool noAA, void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pBox, float alpha, const CRegion& damage, int round, float roundingPower, bool discardActive,
bool allowCustomUV, bool allowDim, SP<CSyncTimeline> waitTimeline, uint64_t waitPoint) { bool noAA, bool allowCustomUV, bool allowDim, SP<CSyncTimeline> waitTimeline, uint64_t waitPoint) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
RASSERT((tex->m_iTexID > 0), "Attempted to draw nullptr texture!"); RASSERT((tex->m_iTexID > 0), "Attempted to draw nullptr texture!");
@ -1506,10 +1517,11 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(SP<CTexture> tex, CBox* pB
glUniform2f(shader->topLeft, TOPLEFT.x, TOPLEFT.y); glUniform2f(shader->topLeft, TOPLEFT.x, TOPLEFT.y);
glUniform2f(shader->fullSize, FULLSIZE.x, FULLSIZE.y); glUniform2f(shader->fullSize, FULLSIZE.x, FULLSIZE.y);
glUniform1f(shader->radius, round); glUniform1f(shader->radius, round);
glUniform1f(shader->roundingPower, roundingPower);
if (allowDim && m_RenderData.currentWindow) { if (allowDim && m_RenderData.currentWindow) {
glUniform1i(shader->applyTint, 1); glUniform1i(shader->applyTint, 1);
const auto DIM = m_RenderData.currentWindow->m_fDimPercent.value(); const auto DIM = m_RenderData.currentWindow->m_fDimPercent->value();
glUniform3f(shader->tint, 1.f - DIM, 1.f - DIM, 1.f - DIM); glUniform3f(shader->tint, 1.f - DIM, 1.f - DIM, 1.f - DIM);
} else { } else {
glUniform1i(shader->applyTint, 0); glUniform1i(shader->applyTint, 0);
@ -1923,7 +1935,7 @@ void CHyprOpenGLImpl::preRender(PHLMONITOR pMonitor) {
const auto PSURFACE = pWindow->m_pWLSurface->resource(); const auto PSURFACE = pWindow->m_pWLSurface->resource();
const auto PWORKSPACE = pWindow->m_pWorkspace; const auto PWORKSPACE = pWindow->m_pWorkspace;
const float A = pWindow->m_fAlpha.value() * pWindow->m_fActiveInactiveAlpha.value() * PWORKSPACE->m_fAlpha.value(); const float A = pWindow->m_fAlpha->value() * pWindow->m_fActiveInactiveAlpha->value() * PWORKSPACE->m_fAlpha->value();
if (A >= 1.f) { if (A >= 1.f) {
// if (PSURFACE->opaque) // if (PSURFACE->opaque)
@ -1961,7 +1973,7 @@ void CHyprOpenGLImpl::preRender(PHLMONITOR pMonitor) {
if (!ls->layerSurface || ls->xray != 1) if (!ls->layerSurface || ls->xray != 1)
continue; continue;
// if (ls->layerSurface->surface->opaque && ls->alpha.value() >= 1.f) // if (ls->layerSurface->surface->opaque && ls->alpha->value() >= 1.f)
// continue; // continue;
hasWindows = true; hasWindows = true;
@ -1997,7 +2009,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() {
clear(CHyprColor(0, 0, 0, 0)); clear(CHyprColor(0, 0, 0, 0));
m_bEndFrame = true; // fix transformed m_bEndFrame = true; // fix transformed
renderTextureInternalWithDamage(POUTFB->getTexture(), &wholeMonitor, 1, fakeDamage, 0, false, true, false); renderTextureInternalWithDamage(POUTFB->getTexture(), &wholeMonitor, 1, fakeDamage, 0, 2.0f, false, true, false);
m_bEndFrame = false; m_bEndFrame = false;
m_RenderData.currentFB->bind(); m_RenderData.currentFB->bind();
@ -2045,8 +2057,8 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(PHLLS pLayer, PHLWINDOW pWin
return false; return false;
} }
void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float a, SP<CWLSurfaceResource> pSurface, int round, bool blockBlurOptimization, float blurA, void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float a, SP<CWLSurfaceResource> pSurface, int round, float roundingPower, bool blockBlurOptimization,
float overallA) { float blurA, float overallA) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!");
static auto PNOBLUROVERSIZED = CConfigValue<Hyprlang::INT>("decoration:no_blur_on_oversized"); static auto PNOBLUROVERSIZED = CConfigValue<Hyprlang::INT>("decoration:no_blur_on_oversized");
@ -2063,7 +2075,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
m_RenderData.renderModif.applyToRegion(texDamage); m_RenderData.renderModif.applyToRegion(texDamage);
if (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) { if (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) {
renderTexture(tex, pBox, a, round, false, true); renderTexture(tex, pBox, a, round, roundingPower, false, true);
return; return;
} }
@ -2076,7 +2088,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
inverseOpaque.invert(&surfbox).intersect(0, 0, pSurface->current.size.x * pSurface->current.scale, pSurface->current.size.y * pSurface->current.scale); inverseOpaque.invert(&surfbox).intersect(0, 0, pSurface->current.size.x * pSurface->current.scale, pSurface->current.size.y * pSurface->current.scale);
if (inverseOpaque.empty()) { if (inverseOpaque.empty()) {
renderTexture(tex, pBox, a, round, false, true); renderTexture(tex, pBox, a, round, roundingPower, false, true);
return; return;
} }
} else { } else {
@ -2112,9 +2124,9 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
if (USENEWOPTIMIZE && !(m_RenderData.discardMode & DISCARD_ALPHA)) if (USENEWOPTIMIZE && !(m_RenderData.discardMode & DISCARD_ALPHA))
renderRect(pBox, CHyprColor(0, 0, 0, 0), round); renderRect(pBox, CHyprColor(0, 0, 0, 0), round, roundingPower);
else else
renderTexture(tex, pBox, a, round, true, true); // discard opaque renderTexture(tex, pBox, a, round, roundingPower, true, true); // discard opaque
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 1, 0xFF); glStencilFunc(GL_EQUAL, 1, 0xFF);
@ -2127,7 +2139,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
setMonitorTransformEnabled(true); setMonitorTransformEnabled(true);
if (!USENEWOPTIMIZE) if (!USENEWOPTIMIZE)
setRenderModifEnabled(false); setRenderModifEnabled(false);
renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, (*PBLURIGNOREOPACITY ? blurA : a * blurA) * overallA, texDamage, 0, false, false, false); renderTextureInternalWithDamage(POUTFB->getTexture(), &MONITORBOX, (*PBLURIGNOREOPACITY ? blurA : a * blurA) * overallA, texDamage, 0, 2.0f, false, false, false);
if (!USENEWOPTIMIZE) if (!USENEWOPTIMIZE)
setRenderModifEnabled(true); setRenderModifEnabled(true);
setMonitorTransformEnabled(false); setMonitorTransformEnabled(false);
@ -2138,14 +2150,14 @@ void CHyprOpenGLImpl::renderTextureWithBlur(SP<CTexture> tex, CBox* pBox, float
// draw window // draw window
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
renderTextureInternalWithDamage(tex, pBox, a * overallA, texDamage, round, false, false, true, true); renderTextureInternalWithDamage(tex, pBox, a * overallA, texDamage, round, roundingPower, false, false, true, true);
glStencilMask(0xFF); glStencilMask(0xFF);
glStencilFunc(GL_ALWAYS, 1, 0xFF); glStencilFunc(GL_ALWAYS, 1, 0xFF);
scissor((CBox*)nullptr); scissor((CBox*)nullptr);
} }
void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, int round, int borderSize, float a, int outerRound) { void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, int round, float roundingPower, int borderSize, float a, int outerRound) {
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
@ -2207,6 +2219,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height); glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.roundingPower, roundingPower);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize);
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@ -2238,7 +2251,8 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in
blend(BLEND); blend(BLEND);
} }
void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, const CGradientValueData& grad2, float lerp, int round, int borderSize, float a, int outerRound) { void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, const CGradientValueData& grad2, float lerp, int round, float roundingPower, int borderSize, float a,
int outerRound) {
RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!");
RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!");
@ -2304,6 +2318,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, c
glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height); glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.roundingPower, roundingPower);
glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize);
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
@ -2335,7 +2350,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad1, c
blend(BLEND); blend(BLEND);
} }
void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const CHyprColor& color, float a) { void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, float roundingPower, int range, const CHyprColor& color, float a) {
RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!"); RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!");
RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!"); RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!");
RASSERT(m_RenderData.currentWindow, "Tried to render shadow without a window!"); RASSERT(m_RenderData.currentWindow, "Tried to render shadow without a window!");
@ -2381,6 +2396,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const
glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y); glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight, (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y); glUniform2f(m_RenderData.pCurrentMonData->m_shSHADOW.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y);
glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.radius, range + round); glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.radius, range + round);
glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.roundingPower, roundingPower);
glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.range, range); glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.range, range);
glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower, SHADOWPOWER); glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower, SHADOWPOWER);
@ -2421,7 +2437,7 @@ void CHyprOpenGLImpl::saveBufferForMirror(CBox* box) {
blend(false); blend(false);
renderTexture(m_RenderData.currentFB->getTexture(), box, 1.f, 0, false, false); renderTexture(m_RenderData.currentFB->getTexture(), box, 1.f, 0, 2.0f, false, false);
blend(true); blend(true);
@ -2869,6 +2885,13 @@ void CHyprOpenGLImpl::restoreMatrix() {
} }
void CHyprOpenGLImpl::bindOffMain() { void CHyprOpenGLImpl::bindOffMain() {
if (!m_RenderData.pCurrentMonData->offMainFB.isAllocated()) {
m_RenderData.pCurrentMonData->offMainFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y,
m_RenderData.pMonitor->output->state->state().drmFormat);
m_RenderData.pCurrentMonData->offMainFB.addStencil(m_RenderData.pCurrentMonData->stencilTex);
}
m_RenderData.pCurrentMonData->offMainFB.bind(); m_RenderData.pCurrentMonData->offMainFB.bind();
clear(CHyprColor(0, 0, 0, 0)); clear(CHyprColor(0, 0, 0, 0));
m_RenderData.currentFB = &m_RenderData.pCurrentMonData->offMainFB; m_RenderData.currentFB = &m_RenderData.pCurrentMonData->offMainFB;

View file

@ -170,17 +170,18 @@ class CHyprOpenGLImpl {
void beginSimple(PHLMONITOR, const CRegion& damage, SP<CRenderbuffer> rb = nullptr, CFramebuffer* fb = nullptr); void beginSimple(PHLMONITOR, const CRegion& damage, SP<CRenderbuffer> rb = nullptr, CFramebuffer* fb = nullptr);
void end(); void end();
void renderRect(CBox*, const CHyprColor&, int round = 0); void renderRect(CBox*, const CHyprColor&, int round = 0, float roundingPower = 2.0f);
void renderRectWithBlur(CBox*, const CHyprColor&, int round = 0, float blurA = 1.f, bool xray = false); void renderRectWithBlur(CBox*, const CHyprColor&, int round = 0, float roundingPower = 2.0f, float blurA = 1.f, bool xray = false);
void renderRectWithDamage(CBox*, const CHyprColor&, const CRegion& damage, int round = 0); void renderRectWithDamage(CBox*, const CHyprColor&, const CRegion& damage, int round = 0, float roundingPower = 2.0f);
void renderTexture(SP<CTexture>, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); void renderTexture(SP<CTexture>, CBox*, float a, int round = 0, float roundingPower = 2.0f, bool discardActive = false, bool allowCustomUV = false);
void renderTextureWithDamage(SP<CTexture>, CBox*, const CRegion& damage, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false, void renderTextureWithDamage(SP<CTexture>, CBox*, const CRegion& damage, float a, int round = 0, float roundingPower = 2.0f, bool discardActive = false,
SP<CSyncTimeline> waitTimeline = nullptr, uint64_t waitPoint = 0); bool allowCustomUV = false, SP<CSyncTimeline> waitTimeline = nullptr, uint64_t waitPoint = 0);
void renderTextureWithBlur(SP<CTexture>, CBox*, float a, SP<CWLSurfaceResource> pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f, void renderTextureWithBlur(SP<CTexture>, CBox*, float a, SP<CWLSurfaceResource> pSurface, int round = 0, float roundingPower = 2.0f, bool blockBlurOptimization = false,
float overallA = 1.f); float blurA = 1.f, float overallA = 1.f);
void renderRoundedShadow(CBox*, int round, int range, const CHyprColor& color, float a = 1.0); void renderRoundedShadow(CBox*, int round, float roundingPower, int range, const CHyprColor& color, float a = 1.0);
void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); void renderBorder(CBox*, const CGradientValueData&, int round, float roundingPower, int borderSize, float a = 1.0, int outerRound = -1 /* use round */);
void renderBorder(CBox*, const CGradientValueData&, const CGradientValueData&, float lerp, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); void renderBorder(CBox*, const CGradientValueData&, const CGradientValueData&, float lerp, int round, float roundingPower, int borderSize, float a = 1.0,
int outerRound = -1 /* use round */);
void renderTextureMatte(SP<CTexture> tex, CBox* pBox, CFramebuffer& matte); void renderTextureMatte(SP<CTexture> tex, CBox* pBox, CFramebuffer& matte);
void setMonitorTransformEnabled(bool enabled); void setMonitorTransformEnabled(bool enabled);
@ -311,8 +312,8 @@ class CHyprOpenGLImpl {
// returns the out FB, can be either Mirror or MirrorSwap // returns the out FB, can be either Mirror or MirrorSwap
CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage); CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage);
void renderTextureInternalWithDamage(SP<CTexture>, CBox* pBox, float a, const CRegion& damage, int round = 0, bool discardOpaque = false, bool noAA = false, void renderTextureInternalWithDamage(SP<CTexture>, CBox* pBox, float a, const CRegion& damage, int round = 0, float roundingPower = 2.0f, bool discardOpaque = false,
bool allowCustomUV = false, bool allowDim = false, SP<CSyncTimeline> = nullptr, uint64_t waitPoint = 0); bool noAA = false, bool allowCustomUV = false, bool allowDim = false, SP<CSyncTimeline> = nullptr, uint64_t waitPoint = 0);
void renderTexturePrimitive(SP<CTexture> tex, CBox* pBox); void renderTexturePrimitive(SP<CTexture> tex, CBox* pBox);
void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size); void renderSplash(cairo_t* const, cairo_surface_t* const, double offset, const Vector2D& size);

View file

@ -25,6 +25,7 @@
#include "pass/RendererHintsPassElement.hpp" #include "pass/RendererHintsPassElement.hpp"
#include "pass/SurfacePassElement.hpp" #include "pass/SurfacePassElement.hpp"
#include "debug/Log.hpp" #include "debug/Log.hpp"
#include "protocols/ColorManagement.hpp"
#include <hyprutils/utils/ScopeGuard.hpp> #include <hyprutils/utils/ScopeGuard.hpp>
using namespace Hyprutils::Utils; using namespace Hyprutils::Utils;
@ -172,21 +173,21 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) {
return true; return true;
// if the window is being moved to a workspace that is not invisible, and the alpha is > 0.F, render it. // if the window is being moved to a workspace that is not invisible, and the alpha is > 0.F, render it.
if (pWindow->m_iMonitorMovedFrom != -1 && pWindow->m_fMovingToWorkspaceAlpha.isBeingAnimated() && pWindow->m_fMovingToWorkspaceAlpha.value() > 0.F && pWindow->m_pWorkspace && if (pWindow->m_iMonitorMovedFrom != -1 && pWindow->m_fMovingToWorkspaceAlpha->isBeingAnimated() && pWindow->m_fMovingToWorkspaceAlpha->value() > 0.F && pWindow->m_pWorkspace &&
!pWindow->m_pWorkspace->isVisible()) !pWindow->m_pWorkspace->isVisible())
return true; return true;
const auto PWINDOWWORKSPACE = pWindow->m_pWorkspace; const auto PWINDOWWORKSPACE = pWindow->m_pWorkspace;
if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_pMonitor == pMonitor) { if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_pMonitor == pMonitor) {
if (PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWINDOWWORKSPACE->m_fAlpha.isBeingAnimated() || PWINDOWWORKSPACE->m_bForceRendering) if (PWINDOWWORKSPACE->m_vRenderOffset->isBeingAnimated() || PWINDOWWORKSPACE->m_fAlpha->isBeingAnimated() || PWINDOWWORKSPACE->m_bForceRendering)
return true; return true;
// if hidden behind fullscreen // if hidden behind fullscreen
if (PWINDOWWORKSPACE->m_bHasFullscreenWindow && !pWindow->isFullscreen() && (!pWindow->m_bIsFloating || !pWindow->m_bCreatedOverFullscreen) && if (PWINDOWWORKSPACE->m_bHasFullscreenWindow && !pWindow->isFullscreen() && (!pWindow->m_bIsFloating || !pWindow->m_bCreatedOverFullscreen) &&
pWindow->m_fAlpha.value() == 0) pWindow->m_fAlpha->value() == 0)
return false; return false;
if (!PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated() && !PWINDOWWORKSPACE->m_fAlpha.isBeingAnimated() && !PWINDOWWORKSPACE->isVisible()) if (!PWINDOWWORKSPACE->m_vRenderOffset->isBeingAnimated() && !PWINDOWWORKSPACE->m_fAlpha->isBeingAnimated() && !PWINDOWWORKSPACE->isVisible())
return false; return false;
} }
@ -204,17 +205,17 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor) {
return true; return true;
// if window is tiled and it's flying in, don't render on other mons (for slide) // if window is tiled and it's flying in, don't render on other mons (for slide)
if (!pWindow->m_bIsFloating && pWindow->m_vRealPosition.isBeingAnimated() && pWindow->m_bAnimatingIn && pWindow->m_pMonitor != pMonitor) if (!pWindow->m_bIsFloating && pWindow->m_vRealPosition->isBeingAnimated() && pWindow->m_bAnimatingIn && pWindow->m_pMonitor != pMonitor)
return false; return false;
if (pWindow->m_vRealPosition.isBeingAnimated()) { if (pWindow->m_vRealPosition->isBeingAnimated()) {
if (PWINDOWWORKSPACE && !PWINDOWWORKSPACE->m_bIsSpecialWorkspace && PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated()) if (PWINDOWWORKSPACE && !PWINDOWWORKSPACE->m_bIsSpecialWorkspace && PWINDOWWORKSPACE->m_vRenderOffset->isBeingAnimated())
return false; return false;
// render window if window and monitor intersect // render window if window and monitor intersect
// (when moving out of or through a monitor) // (when moving out of or through a monitor)
CBox windowBox = pWindow->getFullWindowBoundingBox(); CBox windowBox = pWindow->getFullWindowBoundingBox();
if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated()) if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_vRenderOffset->isBeingAnimated())
windowBox.translate(PWINDOWWORKSPACE->m_vRenderOffset.value()); windowBox.translate(PWINDOWWORKSPACE->m_vRenderOffset->value());
windowBox.translate(pWindow->m_vFloatingOffset); windowBox.translate(pWindow->m_vFloatingOffset);
const CBox monitorBox = {pMonitor->vecPosition, pMonitor->vecSize}; const CBox monitorBox = {pMonitor->vecPosition, pMonitor->vecSize};
@ -242,7 +243,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow) {
return true; return true;
for (auto const& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
if (PWORKSPACE && PWORKSPACE->m_pMonitor == m && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())) if (PWORKSPACE && PWORKSPACE->m_pMonitor == m && (PWORKSPACE->m_vRenderOffset->isBeingAnimated() || PWORKSPACE->m_fAlpha->isBeingAnimated()))
return true; return true;
if (m->activeSpecialWorkspace && pWindow->onSpecialWorkspace()) if (m->activeSpecialWorkspace && pWindow->onSpecialWorkspace())
@ -262,7 +263,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWOR
if (!shouldRenderWindow(w, pMonitor)) if (!shouldRenderWindow(w, pMonitor))
continue; continue;
if (w->m_fAlpha.value() == 0.f) if (w->m_fAlpha->value() == 0.f)
continue; continue;
if (w->isFullscreen() || w->m_bIsFloating) if (w->isFullscreen() || w->m_bIsFloating)
@ -279,7 +280,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWOR
if (!shouldRenderWindow(w, pMonitor)) if (!shouldRenderWindow(w, pMonitor))
continue; continue;
if (w->m_fAlpha.value() == 0.f) if (w->m_fAlpha->value() == 0.f)
continue; continue;
if (w->isFullscreen() || !w->m_bIsFloating) if (w->isFullscreen() || !w->m_bIsFloating)
@ -299,7 +300,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWOR
const auto PWORKSPACE = w->m_pWorkspace; const auto PWORKSPACE = w->m_pWorkspace;
if (w->m_pWorkspace != pWorkspace || !w->isFullscreen()) { if (w->m_pWorkspace != pWorkspace || !w->isFullscreen()) {
if (!(PWORKSPACE && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated() || PWORKSPACE->m_bForceRendering))) if (!(PWORKSPACE && (PWORKSPACE->m_vRenderOffset->isBeingAnimated() || PWORKSPACE->m_fAlpha->isBeingAnimated() || PWORKSPACE->m_bForceRendering)))
continue; continue;
if (w->m_pMonitor != pMonitor) if (w->m_pMonitor != pMonitor)
@ -432,12 +433,12 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe
TRACY_GPU_ZONE("RenderWindow"); TRACY_GPU_ZONE("RenderWindow");
const auto PWORKSPACE = pWindow->m_pWorkspace; const auto PWORKSPACE = pWindow->m_pWorkspace;
const auto REALPOS = pWindow->m_vRealPosition.value() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.value()); const auto REALPOS = pWindow->m_vRealPosition->value() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset->value());
static auto PDIMAROUND = CConfigValue<Hyprlang::FLOAT>("decoration:dim_around"); static auto PDIMAROUND = CConfigValue<Hyprlang::FLOAT>("decoration:dim_around");
static auto PBLUR = CConfigValue<Hyprlang::INT>("decoration:blur:enabled"); static auto PBLUR = CConfigValue<Hyprlang::INT>("decoration:blur:enabled");
CSurfacePassElement::SRenderData renderdata = {pMonitor, time}; CSurfacePassElement::SRenderData renderdata = {pMonitor, time};
CBox textureBox = {REALPOS.x, REALPOS.y, std::max(pWindow->m_vRealSize.value().x, 5.0), std::max(pWindow->m_vRealSize.value().y, 5.0)}; CBox textureBox = {REALPOS.x, REALPOS.y, std::max(pWindow->m_vRealSize->value().x, 5.0), std::max(pWindow->m_vRealSize->value().y, 5.0)};
renderdata.pos.x = textureBox.x; renderdata.pos.x = textureBox.x;
renderdata.pos.y = textureBox.y; renderdata.pos.y = textureBox.y;
@ -458,11 +459,12 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe
renderdata.surface = pWindow->m_pWLSurface->resource(); renderdata.surface = pWindow->m_pWLSurface->resource();
renderdata.dontRound = pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN) || pWindow->m_sWindowData.noRounding.valueOrDefault(); renderdata.dontRound = pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN) || pWindow->m_sWindowData.noRounding.valueOrDefault();
renderdata.fadeAlpha = pWindow->m_fAlpha.value() * (pWindow->m_bPinned || USE_WORKSPACE_FADE_ALPHA ? 1.f : PWORKSPACE->m_fAlpha.value()) * renderdata.fadeAlpha = pWindow->m_fAlpha->value() * (pWindow->m_bPinned || USE_WORKSPACE_FADE_ALPHA ? 1.f : PWORKSPACE->m_fAlpha->value()) *
(USE_WORKSPACE_FADE_ALPHA ? pWindow->m_fMovingToWorkspaceAlpha.value() : 1.F) * pWindow->m_fMovingFromWorkspaceAlpha.value(); (USE_WORKSPACE_FADE_ALPHA ? pWindow->m_fMovingToWorkspaceAlpha->value() : 1.F) * pWindow->m_fMovingFromWorkspaceAlpha->value();
renderdata.alpha = pWindow->m_fActiveInactiveAlpha.value(); renderdata.alpha = pWindow->m_fActiveInactiveAlpha->value();
renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && !pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN); renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && !pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN);
renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale; renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale;
renderdata.roundingPower = ignoreAllGeometry || renderdata.dontRound ? 2.0f : pWindow->roundingPower();
renderdata.blur = !ignoreAllGeometry && *PBLUR && !DONT_BLUR; renderdata.blur = !ignoreAllGeometry && *PBLUR && !DONT_BLUR;
renderdata.pWindow = pWindow; renderdata.pWindow = pWindow;
@ -491,9 +493,9 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe
renderdata.pos.y += pWindow->m_vFloatingOffset.y; renderdata.pos.y += pWindow->m_vFloatingOffset.y;
// if window is floating and we have a slide animation, clip it to its full bb // if window is floating and we have a slide animation, clip it to its full bb
if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->isFullscreen() && PWORKSPACE->m_vRenderOffset.isBeingAnimated() && !pWindow->m_bPinned) { if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->isFullscreen() && PWORKSPACE->m_vRenderOffset->isBeingAnimated() && !pWindow->m_bPinned) {
CRegion rg = CRegion rg =
pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition + PWORKSPACE->m_vRenderOffset.value() + pWindow->m_vFloatingOffset).scale(pMonitor->scale); pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition + PWORKSPACE->m_vRenderOffset->value() + pWindow->m_vFloatingOffset).scale(pMonitor->scale);
renderdata.clipBox = rg.getExtents(); renderdata.clipBox = rg.getExtents();
} }
@ -656,7 +658,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* tim
if (*PDIMAROUND && pLayer->dimAround && !m_bRenderingSnapshot && !popups) { if (*PDIMAROUND && pLayer->dimAround && !m_bRenderingSnapshot && !popups) {
CRectPassElement::SRectData data; CRectPassElement::SRectData data;
data.box = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y}; data.box = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y};
data.color = CHyprColor(0, 0, 0, *PDIMAROUND * pLayer->alpha.value()); data.color = CHyprColor(0, 0, 0, *PDIMAROUND * pLayer->alpha->value());
m_sRenderPass.add(makeShared<CRectPassElement>(data)); m_sRenderPass.add(makeShared<CRectPassElement>(data));
} }
@ -670,11 +672,11 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* tim
TRACY_GPU_ZONE("RenderLayer"); TRACY_GPU_ZONE("RenderLayer");
const auto REALPOS = pLayer->realPosition.value(); const auto REALPOS = pLayer->realPosition->value();
const auto REALSIZ = pLayer->realSize.value(); const auto REALSIZ = pLayer->realSize->value();
CSurfacePassElement::SRenderData renderdata = {pMonitor, time, REALPOS}; CSurfacePassElement::SRenderData renderdata = {pMonitor, time, REALPOS};
renderdata.fadeAlpha = pLayer->alpha.value(); renderdata.fadeAlpha = pLayer->alpha->value();
renderdata.blur = pLayer->forceBlur && *PBLUR; renderdata.blur = pLayer->forceBlur && *PBLUR;
renderdata.surface = pLayer->surface->resource(); renderdata.surface = pLayer->surface->resource();
renderdata.decorate = false; renderdata.decorate = false;
@ -865,8 +867,8 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA
// and then special // and then special
for (auto const& ws : g_pCompositor->m_vWorkspaces) { for (auto const& ws : g_pCompositor->m_vWorkspaces) {
if (ws->m_pMonitor == pMonitor && ws->m_fAlpha.value() > 0.f && ws->m_bIsSpecialWorkspace) { if (ws->m_pMonitor == pMonitor && ws->m_fAlpha->value() > 0.f && ws->m_bIsSpecialWorkspace) {
const auto SPECIALANIMPROGRS = ws->m_vRenderOffset.isBeingAnimated() ? ws->m_vRenderOffset.getCurveValue() : ws->m_fAlpha.getCurveValue(); const auto SPECIALANIMPROGRS = ws->m_vRenderOffset->isBeingAnimated() ? ws->m_vRenderOffset->getCurveValue() : ws->m_fAlpha->getCurveValue();
const bool ANIMOUT = !pMonitor->activeSpecialWorkspace; const bool ANIMOUT = !pMonitor->activeSpecialWorkspace;
if (*PDIMSPECIAL != 0.f) { if (*PDIMSPECIAL != 0.f) {
@ -893,7 +895,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA
// special // special
for (auto const& ws : g_pCompositor->m_vWorkspaces) { for (auto const& ws : g_pCompositor->m_vWorkspaces) {
if (ws->m_fAlpha.value() > 0.f && ws->m_bIsSpecialWorkspace) { if (ws->m_fAlpha->value() > 0.f && ws->m_bIsSpecialWorkspace) {
if (ws->m_bHasFullscreenWindow) if (ws->m_bHasFullscreenWindow)
renderWorkspaceWindowsFullscreen(pMonitor, ws, time); renderWorkspaceWindowsFullscreen(pMonitor, ws, time);
else else
@ -1373,6 +1375,82 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor) {
} }
} }
static const auto BT709 = Aquamarine::IOutput::SChromaticityCoords{
.red = Aquamarine::IOutput::xy{.x = 0.64, .y = 0.33},
.green = Aquamarine::IOutput::xy{.x = 0.30, .y = 0.60},
.blue = Aquamarine::IOutput::xy{.x = 0.15, .y = 0.06},
.white = Aquamarine::IOutput::xy{.x = 0.3127, .y = 0.3290},
};
static hdr_output_metadata createHDRMetadata(uint8_t eotf, Aquamarine::IOutput::SParsedEDID edid) {
if (eotf == 0)
return hdr_output_metadata{.hdmi_metadata_type1 = hdr_metadata_infoframe{.eotf = 0}}; // empty metadata for SDR
const auto toNits = [](float value) { return uint16_t(std::round(value)); };
const auto to16Bit = [](float value) { return uint16_t(std::round(value * 50000)); };
const auto colorimetry = edid.chromaticityCoords.value_or(BT709);
Debug::log(TRACE, "ColorManagement primaries {},{} {},{} {},{} {},{}", colorimetry.red.x, colorimetry.red.y, colorimetry.green.x, colorimetry.green.y, colorimetry.blue.x,
colorimetry.blue.y, colorimetry.white.x, colorimetry.white.y);
Debug::log(TRACE, "ColorManagement max avg {}, min {}, max {}", edid.hdrMetadata->desiredMaxFrameAverageLuminance, edid.hdrMetadata->desiredContentMinLuminance,
edid.hdrMetadata->desiredContentMaxLuminance);
return hdr_output_metadata{
.metadata_type = 0,
.hdmi_metadata_type1 =
hdr_metadata_infoframe{
.eotf = eotf,
.metadata_type = 0,
.display_primaries =
{
{.x = to16Bit(colorimetry.red.x), .y = to16Bit(colorimetry.red.y)},
{.x = to16Bit(colorimetry.green.x), .y = to16Bit(colorimetry.green.y)},
{.x = to16Bit(colorimetry.blue.x), .y = to16Bit(colorimetry.blue.y)},
},
.white_point = {.x = to16Bit(colorimetry.white.x), .y = to16Bit(colorimetry.white.y)},
.max_display_mastering_luminance = toNits(edid.hdrMetadata->desiredMaxFrameAverageLuminance),
.min_display_mastering_luminance = toNits(edid.hdrMetadata->desiredContentMinLuminance * 10000),
.max_cll = toNits(edid.hdrMetadata->desiredMaxFrameAverageLuminance),
.max_fall = toNits(edid.hdrMetadata->desiredMaxFrameAverageLuminance),
},
};
}
static hdr_output_metadata createHDRMetadata(SImageDescription settings, Aquamarine::IOutput::SParsedEDID edid) {
if (settings.transferFunction != XX_COLOR_MANAGER_V4_TRANSFER_FUNCTION_ST2084_PQ)
return hdr_output_metadata{.hdmi_metadata_type1 = hdr_metadata_infoframe{.eotf = 0}}; // empty metadata for SDR
const auto toNits = [](uint32_t value) { return uint16_t(std::round(value)); };
const auto to16Bit = [](uint32_t value) { return uint16_t(std::round(value * 50000)); };
auto colorimetry = settings.primaries;
auto luminances = settings.masteringLuminances.max > 0 ?
settings.masteringLuminances :
SImageDescription::SPCMasteringLuminances{.min = edid.hdrMetadata->desiredContentMinLuminance, .max = edid.hdrMetadata->desiredContentMaxLuminance};
Debug::log(TRACE, "ColorManagement primaries {},{} {},{} {},{} {},{}", colorimetry.red.x, colorimetry.red.y, colorimetry.green.x, colorimetry.green.y, colorimetry.blue.x,
colorimetry.blue.y, colorimetry.white.x, colorimetry.white.y);
Debug::log(TRACE, "ColorManagement min {}, max {}, cll {}, fall {}", luminances.min, luminances.max, settings.maxCLL, settings.maxFALL);
return hdr_output_metadata{
.metadata_type = 0,
.hdmi_metadata_type1 =
hdr_metadata_infoframe{
.eotf = 2,
.metadata_type = 0,
.display_primaries =
{
{.x = to16Bit(colorimetry.red.x), .y = to16Bit(colorimetry.red.y)},
{.x = to16Bit(colorimetry.green.x), .y = to16Bit(colorimetry.green.y)},
{.x = to16Bit(colorimetry.blue.x), .y = to16Bit(colorimetry.blue.y)},
},
.white_point = {.x = to16Bit(colorimetry.white.x), .y = to16Bit(colorimetry.white.y)},
.max_display_mastering_luminance = toNits(luminances.max),
.min_display_mastering_luminance = toNits(luminances.min * 10000),
.max_cll = toNits(settings.maxCLL),
.max_fall = toNits(settings.maxFALL),
},
};
}
bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) {
// apply timelines for explicit sync // apply timelines for explicit sync
// save inFD otherwise reset will reset it // save inFD otherwise reset will reset it
@ -1381,6 +1459,27 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) {
if (inFD >= 0) if (inFD >= 0)
pMonitor->output->state->setExplicitInFence(inFD); pMonitor->output->state->setExplicitInFence(inFD);
static auto PWIDE = CConfigValue<Hyprlang::INT>("experimental:wide_color_gamut");
if (pMonitor->output->state->state().wideColorGamut != *PWIDE)
Debug::log(TRACE, "Setting wide color gamut {}", *PWIDE ? "on" : "off");
pMonitor->output->state->setWideColorGamut(*PWIDE);
static auto PHDR = CConfigValue<Hyprlang::INT>("experimental:hdr");
const bool SUPPORTSPQ = pMonitor->output->parsedEDID.hdrMetadata.has_value() ? pMonitor->output->parsedEDID.hdrMetadata->supportsPQ : false;
Debug::log(TRACE, "ColorManagement supportsBT2020 {}, supportsPQ {}", pMonitor->output->parsedEDID.supportsBT2020, SUPPORTSPQ);
if (pMonitor->output->parsedEDID.supportsBT2020 && SUPPORTSPQ) {
if (pMonitor->activeWorkspace && pMonitor->activeWorkspace->m_bHasFullscreenWindow && pMonitor->activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) {
const auto WINDOW = pMonitor->activeWorkspace->getFullscreenWindow();
const auto SURF = WINDOW->m_pWLSurface->resource();
if (SURF->colorManagement.valid() && SURF->colorManagement->hasImageDescription())
pMonitor->output->state->setHDRMetadata(createHDRMetadata(SURF->colorManagement.get()->imageDescription(), pMonitor->output->parsedEDID));
else
pMonitor->output->state->setHDRMetadata(*PHDR ? createHDRMetadata(2, pMonitor->output->parsedEDID) : createHDRMetadata(0, pMonitor->output->parsedEDID));
} else
pMonitor->output->state->setHDRMetadata(*PHDR ? createHDRMetadata(2, pMonitor->output->parsedEDID) : createHDRMetadata(0, pMonitor->output->parsedEDID));
}
if (pMonitor->ctmUpdated) { if (pMonitor->ctmUpdated) {
pMonitor->ctmUpdated = false; pMonitor->ctmUpdated = false;
pMonitor->output->state->setCTM(pMonitor->ctm); pMonitor->output->state->setCTM(pMonitor->ctm);
@ -1616,8 +1715,8 @@ void CHyprRenderer::arrangeLayerArray(PHLMONITOR pMonitor, const std::vector<PHL
if (Vector2D{box.width, box.height} != OLDSIZE) if (Vector2D{box.width, box.height} != OLDSIZE)
ls->layerSurface->configure(box.size()); ls->layerSurface->configure(box.size());
ls->realPosition = box.pos(); *ls->realPosition = box.pos();
ls->realSize = box.size(); *ls->realSize = box.size();
} }
} }
@ -1726,8 +1825,8 @@ void CHyprRenderer::damageWindow(PHLWINDOW pWindow, bool forceFull) {
CBox windowBox = pWindow->getFullWindowBoundingBox(); CBox windowBox = pWindow->getFullWindowBoundingBox();
const auto PWINDOWWORKSPACE = pWindow->m_pWorkspace; const auto PWINDOWWORKSPACE = pWindow->m_pWorkspace;
if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated() && !pWindow->m_bPinned) if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_vRenderOffset->isBeingAnimated() && !pWindow->m_bPinned)
windowBox.translate(PWINDOWWORKSPACE->m_vRenderOffset.value()); windowBox.translate(PWINDOWWORKSPACE->m_vRenderOffset->value());
windowBox.translate(pWindow->m_vFloatingOffset); windowBox.translate(pWindow->m_vFloatingOffset);
for (auto const& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
@ -1976,8 +2075,8 @@ void CHyprRenderer::recheckSolitaryForMonitor(PHLMONITOR pMonitor) {
const auto PWORKSPACE = pMonitor->activeWorkspace; const auto PWORKSPACE = pMonitor->activeWorkspace;
if (!PWORKSPACE || !PWORKSPACE->m_bHasFullscreenWindow || PROTO::data->dndActive() || pMonitor->activeSpecialWorkspace || PWORKSPACE->m_fAlpha.value() != 1.f || if (!PWORKSPACE || !PWORKSPACE->m_bHasFullscreenWindow || PROTO::data->dndActive() || pMonitor->activeSpecialWorkspace || PWORKSPACE->m_fAlpha->value() != 1.f ||
PWORKSPACE->m_vRenderOffset.value() != Vector2D{}) PWORKSPACE->m_vRenderOffset->value() != Vector2D{})
return; return;
const auto PCANDIDATE = PWORKSPACE->getFullscreenWindow(); const auto PCANDIDATE = PWORKSPACE->getFullscreenWindow();
@ -1988,15 +2087,15 @@ void CHyprRenderer::recheckSolitaryForMonitor(PHLMONITOR pMonitor) {
if (!PCANDIDATE->opaque()) if (!PCANDIDATE->opaque())
return; return;
if (PCANDIDATE->m_vRealSize.value() != pMonitor->vecSize || PCANDIDATE->m_vRealPosition.value() != pMonitor->vecPosition || PCANDIDATE->m_vRealPosition.isBeingAnimated() || if (PCANDIDATE->m_vRealSize->value() != pMonitor->vecSize || PCANDIDATE->m_vRealPosition->value() != pMonitor->vecPosition || PCANDIDATE->m_vRealPosition->isBeingAnimated() ||
PCANDIDATE->m_vRealSize.isBeingAnimated()) PCANDIDATE->m_vRealSize->isBeingAnimated())
return; return;
if (!pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY].empty()) if (!pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY].empty())
return; return;
for (auto const& topls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { for (auto const& topls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
if (topls->alpha.value() != 0.f) if (topls->alpha->value() != 0.f)
return; return;
} }
@ -2409,13 +2508,13 @@ void CHyprRenderer::renderSnapshot(PHLWINDOW pWindow) {
CBox windowBox; CBox windowBox;
// some mafs to figure out the correct box // some mafs to figure out the correct box
// the originalClosedPos is relative to the monitor's pos // the originalClosedPos is relative to the monitor's pos
Vector2D scaleXY = Vector2D((PMONITOR->scale * pWindow->m_vRealSize.value().x / (pWindow->m_vOriginalClosedSize.x * PMONITOR->scale)), Vector2D scaleXY = Vector2D((PMONITOR->scale * pWindow->m_vRealSize->value().x / (pWindow->m_vOriginalClosedSize.x * PMONITOR->scale)),
(PMONITOR->scale * pWindow->m_vRealSize.value().y / (pWindow->m_vOriginalClosedSize.y * PMONITOR->scale))); (PMONITOR->scale * pWindow->m_vRealSize->value().y / (pWindow->m_vOriginalClosedSize.y * PMONITOR->scale)));
windowBox.width = PMONITOR->vecTransformedSize.x * scaleXY.x; windowBox.width = PMONITOR->vecTransformedSize.x * scaleXY.x;
windowBox.height = PMONITOR->vecTransformedSize.y * scaleXY.y; windowBox.height = PMONITOR->vecTransformedSize.y * scaleXY.y;
windowBox.x = ((pWindow->m_vRealPosition.value().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - ((pWindow->m_vOriginalClosedPos.x * PMONITOR->scale) * scaleXY.x); windowBox.x = ((pWindow->m_vRealPosition->value().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - ((pWindow->m_vOriginalClosedPos.x * PMONITOR->scale) * scaleXY.x);
windowBox.y = ((pWindow->m_vRealPosition.value().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - ((pWindow->m_vOriginalClosedPos.y * PMONITOR->scale) * scaleXY.y); windowBox.y = ((pWindow->m_vRealPosition->value().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - ((pWindow->m_vOriginalClosedPos.y * PMONITOR->scale) * scaleXY.y);
CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
@ -2424,7 +2523,7 @@ void CHyprRenderer::renderSnapshot(PHLWINDOW pWindow) {
CRectPassElement::SRectData data; CRectPassElement::SRectData data;
data.box = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y}; data.box = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y};
data.color = CHyprColor(0, 0, 0, *PDIMAROUND * pWindow->m_fAlpha.value()); data.color = CHyprColor(0, 0, 0, *PDIMAROUND * pWindow->m_fAlpha->value());
m_sRenderPass.add(makeShared<CRectPassElement>(data)); m_sRenderPass.add(makeShared<CRectPassElement>(data));
damageMonitor(PMONITOR); damageMonitor(PMONITOR);
@ -2434,7 +2533,7 @@ void CHyprRenderer::renderSnapshot(PHLWINDOW pWindow) {
data.flipEndFrame = true; data.flipEndFrame = true;
data.tex = FBDATA->getTexture(); data.tex = FBDATA->getTexture();
data.box = windowBox; data.box = windowBox;
data.a = pWindow->m_fAlpha.value(); data.a = pWindow->m_fAlpha->value();
data.damage = fakeDamage; data.damage = fakeDamage;
m_sRenderPass.add(makeShared<CTexPassElement>(data)); m_sRenderPass.add(makeShared<CTexPassElement>(data));
@ -2454,13 +2553,13 @@ void CHyprRenderer::renderSnapshot(PHLLS pLayer) {
CBox layerBox; CBox layerBox;
// some mafs to figure out the correct box // some mafs to figure out the correct box
// the originalClosedPos is relative to the monitor's pos // the originalClosedPos is relative to the monitor's pos
Vector2D scaleXY = Vector2D((PMONITOR->scale * pLayer->realSize.value().x / (pLayer->geometry.w * PMONITOR->scale)), Vector2D scaleXY = Vector2D((PMONITOR->scale * pLayer->realSize->value().x / (pLayer->geometry.w * PMONITOR->scale)),
(PMONITOR->scale * pLayer->realSize.value().y / (pLayer->geometry.h * PMONITOR->scale))); (PMONITOR->scale * pLayer->realSize->value().y / (pLayer->geometry.h * PMONITOR->scale)));
layerBox.width = PMONITOR->vecTransformedSize.x * scaleXY.x; layerBox.width = PMONITOR->vecTransformedSize.x * scaleXY.x;
layerBox.height = PMONITOR->vecTransformedSize.y * scaleXY.y; layerBox.height = PMONITOR->vecTransformedSize.y * scaleXY.y;
layerBox.x = ((pLayer->realPosition.value().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - (((pLayer->geometry.x - PMONITOR->vecPosition.x) * PMONITOR->scale) * scaleXY.x); layerBox.x = ((pLayer->realPosition->value().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - (((pLayer->geometry.x - PMONITOR->vecPosition.x) * PMONITOR->scale) * scaleXY.x);
layerBox.y = ((pLayer->realPosition.value().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - (((pLayer->geometry.y - PMONITOR->vecPosition.y) * PMONITOR->scale) * scaleXY.y); layerBox.y = ((pLayer->realPosition->value().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - (((pLayer->geometry.y - PMONITOR->vecPosition.y) * PMONITOR->scale) * scaleXY.y);
CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
@ -2468,7 +2567,7 @@ void CHyprRenderer::renderSnapshot(PHLLS pLayer) {
data.flipEndFrame = true; data.flipEndFrame = true;
data.tex = FBDATA->getTexture(); data.tex = FBDATA->getTexture();
data.box = layerBox; data.box = layerBox;
data.a = pLayer->alpha.value(); data.a = pLayer->alpha->value();
data.damage = fakeDamage; data.damage = fakeDamage;
m_sRenderPass.add(makeShared<CTexPassElement>(data)); m_sRenderPass.add(makeShared<CTexPassElement>(data));

View file

@ -26,6 +26,7 @@ class CShader {
GLint fullSizeUntransformed = -1; GLint fullSizeUntransformed = -1;
GLint radius = -1; GLint radius = -1;
GLint radiusOuter = -1; GLint radiusOuter = -1;
GLfloat roundingPower = -1;
GLint thick = -1; GLint thick = -1;

View file

@ -43,7 +43,7 @@ CBox CHyprBorderDecoration::assignedBoxGlobal() {
if (!PWORKSPACE) if (!PWORKSPACE)
return box; return box;
const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.value() : Vector2D(); const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset->value() : Vector2D();
return box.translate(WORKSPACEOFFSET); return box.translate(WORKSPACEOFFSET);
} }
@ -60,20 +60,22 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) {
return; return;
auto grad = m_pWindow->m_cRealBorderColor; auto grad = m_pWindow->m_cRealBorderColor;
const bool ANIMATED = m_pWindow->m_fBorderFadeAnimationProgress.isBeingAnimated(); const bool ANIMATED = m_pWindow->m_fBorderFadeAnimationProgress->isBeingAnimated();
if (m_pWindow->m_fBorderAngleAnimationProgress.getConfig()->pValues->internalEnabled) { if (m_pWindow->m_fBorderAngleAnimationProgress->enabled()) {
grad.m_fAngle += m_pWindow->m_fBorderAngleAnimationProgress.value() * M_PI * 2; grad.m_fAngle += m_pWindow->m_fBorderAngleAnimationProgress->value() * M_PI * 2;
grad.m_fAngle = normalizeAngleRad(grad.m_fAngle); grad.m_fAngle = normalizeAngleRad(grad.m_fAngle);
} }
int borderSize = m_pWindow->getRealBorderSize(); int borderSize = m_pWindow->getRealBorderSize();
const auto ROUNDING = m_pWindow->rounding() * pMonitor->scale; const auto ROUNDING = m_pWindow->rounding() * pMonitor->scale;
const auto ROUNDINGPOWER = m_pWindow->roundingPower();
CBorderPassElement::SBorderData data; CBorderPassElement::SBorderData data;
data.box = windowBox; data.box = windowBox;
data.grad1 = grad; data.grad1 = grad;
data.round = ROUNDING; data.round = ROUNDING;
data.roundingPower = ROUNDINGPOWER;
data.a = a; data.a = a;
data.borderSize = borderSize; data.borderSize = borderSize;
@ -81,7 +83,7 @@ void CHyprBorderDecoration::draw(PHLMONITOR pMonitor, float const& a) {
data.hasGrad2 = true; data.hasGrad2 = true;
data.grad1 = m_pWindow->m_cRealBorderColorPrevious; data.grad1 = m_pWindow->m_cRealBorderColorPrevious;
data.grad2 = grad; data.grad2 = grad;
data.lerp = m_pWindow->m_fBorderFadeAnimationProgress.value(); data.lerp = m_pWindow->m_fBorderFadeAnimationProgress->value();
} }
g_pHyprRenderer->m_sRenderPass.add(makeShared<CBorderPassElement>(data)); g_pHyprRenderer->m_sRenderPass.add(makeShared<CBorderPassElement>(data));
@ -115,8 +117,8 @@ void CHyprBorderDecoration::damageEntire() {
const auto BORDERSIZE = m_pWindow->getRealBorderSize() + 1; const auto BORDERSIZE = m_pWindow->getRealBorderSize() + 1;
const auto PWINDOWWORKSPACE = m_pWindow->m_pWorkspace; const auto PWINDOWWORKSPACE = m_pWindow->m_pWorkspace;
if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated() && !m_pWindow->m_bPinned) if (PWINDOWWORKSPACE && PWINDOWWORKSPACE->m_vRenderOffset->isBeingAnimated() && !m_pWindow->m_bPinned)
surfaceBox.translate(PWINDOWWORKSPACE->m_vRenderOffset.value()); surfaceBox.translate(PWINDOWWORKSPACE->m_vRenderOffset->value());
surfaceBox.translate(m_pWindow->m_vFloatingOffset); surfaceBox.translate(m_pWindow->m_vFloatingOffset);
CBox surfaceBoxExpandedBorder = surfaceBox; CBox surfaceBoxExpandedBorder = surfaceBox;

View file

@ -44,24 +44,25 @@ void CHyprDropShadowDecoration::damageEntire() {
const auto PWINDOW = m_pWindow.lock(); const auto PWINDOW = m_pWindow.lock();
CBox shadowBox = {PWINDOW->m_vRealPosition.value().x - m_seExtents.topLeft.x, PWINDOW->m_vRealPosition.value().y - m_seExtents.topLeft.y, CBox shadowBox = {PWINDOW->m_vRealPosition->value().x - m_seExtents.topLeft.x, PWINDOW->m_vRealPosition->value().y - m_seExtents.topLeft.y,
PWINDOW->m_vRealSize.value().x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x, PWINDOW->m_vRealSize->value().x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x,
PWINDOW->m_vRealSize.value().y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y}; PWINDOW->m_vRealSize->value().y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y};
const auto PWORKSPACE = PWINDOW->m_pWorkspace; const auto PWORKSPACE = PWINDOW->m_pWorkspace;
if (PWORKSPACE && PWORKSPACE->m_vRenderOffset.isBeingAnimated() && !PWINDOW->m_bPinned) if (PWORKSPACE && PWORKSPACE->m_vRenderOffset->isBeingAnimated() && !PWINDOW->m_bPinned)
shadowBox.translate(PWORKSPACE->m_vRenderOffset.value()); shadowBox.translate(PWORKSPACE->m_vRenderOffset->value());
shadowBox.translate(PWINDOW->m_vFloatingOffset); shadowBox.translate(PWINDOW->m_vFloatingOffset);
static auto PSHADOWIGNOREWINDOW = CConfigValue<Hyprlang::INT>("decoration:shadow:ignore_window"); static auto PSHADOWIGNOREWINDOW = CConfigValue<Hyprlang::INT>("decoration:shadow:ignore_window");
const auto ROUNDING = PWINDOW->rounding(); const auto ROUNDING = PWINDOW->rounding();
const auto ROUNDINGPOWER = PWINDOW->roundingPower();
const auto ROUNDINGSIZE = ROUNDING - M_SQRT1_2 * ROUNDING + 1; const auto ROUNDINGSIZE = ROUNDING - M_SQRT1_2 * ROUNDING + 1;
CRegion shadowRegion(shadowBox); CRegion shadowRegion(shadowBox);
if (*PSHADOWIGNOREWINDOW) { if (*PSHADOWIGNOREWINDOW) {
CBox surfaceBox = PWINDOW->getWindowMainSurfaceBox(); CBox surfaceBox = PWINDOW->getWindowMainSurfaceBox();
if (PWORKSPACE && PWORKSPACE->m_vRenderOffset.isBeingAnimated() && !PWINDOW->m_bPinned) if (PWORKSPACE && PWORKSPACE->m_vRenderOffset->isBeingAnimated() && !PWINDOW->m_bPinned)
surfaceBox.translate(PWORKSPACE->m_vRenderOffset.value()); surfaceBox.translate(PWORKSPACE->m_vRenderOffset->value());
surfaceBox.translate(PWINDOW->m_vFloatingOffset); surfaceBox.translate(PWINDOW->m_vFloatingOffset);
surfaceBox.expand(-ROUNDINGSIZE); surfaceBox.expand(-ROUNDINGSIZE);
shadowRegion.subtract(CRegion(surfaceBox)); shadowRegion.subtract(CRegion(surfaceBox));
@ -80,8 +81,8 @@ void CHyprDropShadowDecoration::damageEntire() {
void CHyprDropShadowDecoration::updateWindow(PHLWINDOW pWindow) { void CHyprDropShadowDecoration::updateWindow(PHLWINDOW pWindow) {
const auto PWINDOW = m_pWindow.lock(); const auto PWINDOW = m_pWindow.lock();
m_vLastWindowPos = PWINDOW->m_vRealPosition.value(); m_vLastWindowPos = PWINDOW->m_vRealPosition->value();
m_vLastWindowSize = PWINDOW->m_vRealSize.value(); m_vLastWindowSize = PWINDOW->m_vRealSize->value();
m_bLastWindowBox = {m_vLastWindowPos.x, m_vLastWindowPos.y, m_vLastWindowSize.x, m_vLastWindowSize.y}; m_bLastWindowBox = {m_vLastWindowPos.x, m_vLastWindowPos.y, m_vLastWindowSize.x, m_vLastWindowSize.y};
m_bLastWindowBoxWithDecos = g_pDecorationPositioner->getBoxWithIncludedDecos(pWindow); m_bLastWindowBoxWithDecos = g_pDecorationPositioner->getBoxWithIncludedDecos(pWindow);
@ -100,7 +101,7 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
if (!validMapped(PWINDOW)) if (!validMapped(PWINDOW))
return; return;
if (PWINDOW->m_cRealShadowColor.value() == CHyprColor(0, 0, 0, 0)) if (PWINDOW->m_cRealShadowColor->value() == CHyprColor(0, 0, 0, 0))
return; // don't draw invisible shadows return; // don't draw invisible shadows
if (!PWINDOW->m_sWindowData.decorate.valueOrDefault()) if (!PWINDOW->m_sWindowData.decorate.valueOrDefault())
@ -119,9 +120,10 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
return; // disabled return; // disabled
const auto ROUNDINGBASE = PWINDOW->rounding(); const auto ROUNDINGBASE = PWINDOW->rounding();
const auto ROUNDINGPOWER = PWINDOW->roundingPower();
const auto ROUNDING = ROUNDINGBASE > 0 ? ROUNDINGBASE + PWINDOW->getRealBorderSize() : 0; const auto ROUNDING = ROUNDINGBASE > 0 ? ROUNDINGBASE + PWINDOW->getRealBorderSize() : 0;
const auto PWORKSPACE = PWINDOW->m_pWorkspace; const auto PWORKSPACE = PWINDOW->m_pWorkspace;
const auto WORKSPACEOFFSET = PWORKSPACE && !PWINDOW->m_bPinned ? PWORKSPACE->m_vRenderOffset.value() : Vector2D(); const auto WORKSPACEOFFSET = PWORKSPACE && !PWINDOW->m_bPinned ? PWORKSPACE->m_vRenderOffset->value() : Vector2D();
// draw the shadow // draw the shadow
CBox fullBox = m_bLastWindowBoxWithDecos; CBox fullBox = m_bLastWindowBoxWithDecos;
@ -192,15 +194,15 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
g_pHyprOpenGL->renderRect(&fullBox, CHyprColor(0, 0, 0, 1), 0); g_pHyprOpenGL->renderRect(&fullBox, CHyprColor(0, 0, 0, 1), 0);
// render white shadow with the alpha of the shadow color (otherwise we clear with alpha later and shit it to 2 bit) // render white shadow with the alpha of the shadow color (otherwise we clear with alpha later and shit it to 2 bit)
drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CHyprColor(1, 1, 1, PWINDOW->m_cRealShadowColor.value().a), a); drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, ROUNDINGPOWER, *PSHADOWSIZE * pMonitor->scale, CHyprColor(1, 1, 1, PWINDOW->m_cRealShadowColor->value().a), a);
// render black window box ("clip") // render black window box ("clip")
g_pHyprOpenGL->renderRect(&windowBox, CHyprColor(0, 0, 0, 1.0), (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->scale); g_pHyprOpenGL->renderRect(&windowBox, CHyprColor(0, 0, 0, 1.0), (ROUNDING + 1 /* This fixes small pixel gaps. */) * pMonitor->scale, ROUNDINGPOWER);
alphaSwapFB.bind(); alphaSwapFB.bind();
// alpha swap just has the shadow color. It will be the "texture" to render. // alpha swap just has the shadow color. It will be the "texture" to render.
g_pHyprOpenGL->renderRect(&fullBox, PWINDOW->m_cRealShadowColor.value().stripA(), 0); g_pHyprOpenGL->renderRect(&fullBox, PWINDOW->m_cRealShadowColor->value().stripA(), 0);
LASTFB->bind(); LASTFB->bind();
@ -214,7 +216,7 @@ void CHyprDropShadowDecoration::render(PHLMONITOR pMonitor, float const& a) {
g_pHyprOpenGL->m_RenderData.damage = saveDamage; g_pHyprOpenGL->m_RenderData.damage = saveDamage;
} else } else
drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, PWINDOW->m_cRealShadowColor.value(), a); drawShadowInternal(&fullBox, ROUNDING * pMonitor->scale, ROUNDINGPOWER, *PSHADOWSIZE * pMonitor->scale, PWINDOW->m_cRealShadowColor->value(), a);
if (m_seExtents != m_seReportedExtents) if (m_seExtents != m_seReportedExtents)
g_pDecorationPositioner->repositionDeco(this); g_pDecorationPositioner->repositionDeco(this);
@ -226,7 +228,7 @@ eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() {
return DECORATION_LAYER_BOTTOM; return DECORATION_LAYER_BOTTOM;
} }
void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, int range, CHyprColor color, float a) { void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, float roundingPower, int range, CHyprColor color, float a) {
static auto PSHADOWSHARP = CConfigValue<Hyprlang::INT>("decoration:shadow:sharp"); static auto PSHADOWSHARP = CConfigValue<Hyprlang::INT>("decoration:shadow:sharp");
g_pHyprOpenGL->blend(true); g_pHyprOpenGL->blend(true);
@ -234,7 +236,7 @@ void CHyprDropShadowDecoration::drawShadowInternal(CBox* box, int round, int ran
color.a *= a; color.a *= a;
if (*PSHADOWSHARP) if (*PSHADOWSHARP)
g_pHyprOpenGL->renderRect(box, color, round); g_pHyprOpenGL->renderRect(box, color, round, roundingPower);
else else
g_pHyprOpenGL->renderRoundedShadow(box, round, range, color, 1.F); g_pHyprOpenGL->renderRoundedShadow(box, round, roundingPower, range, color, 1.F);
} }

View file

@ -36,7 +36,7 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration {
Vector2D m_vLastWindowPos; Vector2D m_vLastWindowPos;
Vector2D m_vLastWindowSize; Vector2D m_vLastWindowSize;
void drawShadowInternal(CBox* box, int round, int range, CHyprColor color, float a); void drawShadowInternal(CBox* box, int round, float roundingPower, int range, CHyprColor color, float a);
CBox m_bLastWindowBox = {0}; CBox m_bLastWindowBox = {0};
CBox m_bLastWindowBoxWithDecos = {0}; CBox m_bLastWindowBoxWithDecos = {0};

View file

@ -391,8 +391,8 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND
// restores the group // restores the group
for (auto it = members.begin(); it != members.end(); ++it) { for (auto it = members.begin(); it != members.end(); ++it) {
(*it)->m_bIsFloating = pWindowInsertAfter->m_bIsFloating; // match the floating state of group members (*it)->m_bIsFloating = pWindowInsertAfter->m_bIsFloating; // match the floating state of group members
(*it)->m_vRealSize = pWindowInsertAfter->m_vRealSize.goal(); // match the size of group members *(*it)->m_vRealSize = pWindowInsertAfter->m_vRealSize->goal(); // match the size of group members
(*it)->m_vRealPosition = pWindowInsertAfter->m_vRealPosition.goal(); // match the position of group members *(*it)->m_vRealPosition = pWindowInsertAfter->m_vRealPosition->goal(); // match the position of group members
if (std::next(it) != members.end()) if (std::next(it) != members.end())
(*it)->m_sGroupData.pNextWindow = *std::next(it); (*it)->m_sGroupData.pNextWindow = *std::next(it);
else else
@ -406,7 +406,7 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND
pDraggedWindow->m_bIsFloating = pWindowInsertAfter->m_bIsFloating; // match the floating state of the window pDraggedWindow->m_bIsFloating = pWindowInsertAfter->m_bIsFloating; // match the floating state of the window
if (pWindowInsertAfter->m_bIsFloating) if (pWindowInsertAfter->m_bIsFloating)
g_pXWaylandManager->setWindowSize(pDraggedWindow, pWindowInsertAfter->m_vRealSize.goal()); // match the size of the window g_pXWaylandManager->setWindowSize(pDraggedWindow, pWindowInsertAfter->m_vRealSize->goal()); // match the size of the window
pWindowInsertAfter->insertWindowToGroup(pDraggedWindow); pWindowInsertAfter->insertWindowToGroup(pDraggedWindow);
@ -515,7 +515,7 @@ CBox CHyprGroupBarDecoration::assignedBoxGlobal() {
const auto PWORKSPACE = m_pWindow->m_pWorkspace; const auto PWORKSPACE = m_pWindow->m_pWorkspace;
if (PWORKSPACE && !m_pWindow->m_bPinned) if (PWORKSPACE && !m_pWindow->m_bPinned)
box.translate(PWORKSPACE->m_vRenderOffset.value()); box.translate(PWORKSPACE->m_vRenderOffset->value());
return box; return box;
} }

View file

@ -124,7 +124,7 @@ void CDecorationPositioner::onWindowUpdate(PHLWINDOW pWindow) {
datas.push_back(getDataFor(wd.get(), pWindow)); datas.push_back(getDataFor(wd.get(), pWindow));
} }
if (WINDOWDATA->lastWindowSize == pWindow->m_vRealSize.value() /* position not changed */ if (WINDOWDATA->lastWindowSize == pWindow->m_vRealSize->value() /* position not changed */
&& std::all_of(m_vWindowPositioningDatas.begin(), m_vWindowPositioningDatas.end(), && std::all_of(m_vWindowPositioningDatas.begin(), m_vWindowPositioningDatas.end(),
[pWindow](const auto& data) { return pWindow != data->pWindow.lock() || !data->needsReposition; }) [pWindow](const auto& data) { return pWindow != data->pWindow.lock() || !data->needsReposition; })
/* all window datas are either not for this window or don't need a reposition */ /* all window datas are either not for this window or don't need a reposition */
@ -132,9 +132,9 @@ void CDecorationPositioner::onWindowUpdate(PHLWINDOW pWindow) {
) )
return; return;
WINDOWDATA->lastWindowSize = pWindow->m_vRealSize.value(); WINDOWDATA->lastWindowSize = pWindow->m_vRealSize->value();
WINDOWDATA->needsRecalc = false; WINDOWDATA->needsRecalc = false;
const bool EPHEMERAL = pWindow->m_vRealSize.isBeingAnimated(); const bool EPHEMERAL = pWindow->m_vRealSize->isBeingAnimated();
std::sort(datas.begin(), datas.end(), [](const auto& a, const auto& b) { return a->positioningInfo.priority > b->positioningInfo.priority; }); std::sort(datas.begin(), datas.end(), [](const auto& a, const auto& b) { return a->positioningInfo.priority > b->positioningInfo.priority; });

View file

@ -7,9 +7,9 @@ CBorderPassElement::CBorderPassElement(const CBorderPassElement::SBorderData& da
void CBorderPassElement::draw(const CRegion& damage) { void CBorderPassElement::draw(const CRegion& damage) {
if (data.hasGrad2) if (data.hasGrad2)
g_pHyprOpenGL->renderBorder(&data.box, data.grad1, data.grad2, data.lerp, data.round, data.borderSize, data.a, data.outerRound); g_pHyprOpenGL->renderBorder(&data.box, data.grad1, data.grad2, data.lerp, data.round, data.roundingPower, data.borderSize, data.a, data.outerRound);
else else
g_pHyprOpenGL->renderBorder(&data.box, data.grad1, data.round, data.borderSize, data.a, data.outerRound); g_pHyprOpenGL->renderBorder(&data.box, data.grad1, data.round, data.roundingPower, data.borderSize, data.a, data.outerRound);
} }
bool CBorderPassElement::needsLiveBlur() { bool CBorderPassElement::needsLiveBlur() {

View file

@ -12,6 +12,7 @@ class CBorderPassElement : public IPassElement {
bool hasGrad2 = false; bool hasGrad2 = false;
float lerp = 0.F, a = 1.F; float lerp = 0.F, a = 1.F;
int round = 0, borderSize = 1, outerRound = -1; int round = 0, borderSize = 1, outerRound = -1;
float roundingPower = 2.F;
}; };
CBorderPassElement(const SBorderData& data_); CBorderPassElement(const SBorderData& data_);

View file

@ -88,7 +88,7 @@ void CRenderPass::simplify() {
} }
newDamage.subtract(opaque); newDamage.subtract(opaque);
if (*PDEBUGPASS) if (*PDEBUGPASS)
occludedRegion.add(opaque); occludedRegions.emplace_back(opaque);
} }
} }
@ -115,8 +115,10 @@ CRegion CRenderPass::render(const CRegion& damage_) {
const auto WILLBLUR = std::ranges::any_of(m_vPassElements, [](const auto& el) { return el->element->needsLiveBlur(); }); const auto WILLBLUR = std::ranges::any_of(m_vPassElements, [](const auto& el) { return el->element->needsLiveBlur(); });
damage = *PDEBUGPASS ? CRegion{CBox{{}, {INT32_MAX, INT32_MAX}}} : damage_.copy(); damage = *PDEBUGPASS ? CRegion{CBox{{}, {INT32_MAX, INT32_MAX}}} : damage_.copy();
occludedRegion = CRegion{}; if (*PDEBUGPASS) {
occludedRegions.clear();
totalLiveBlurRegion = CRegion{}; totalLiveBlurRegion = CRegion{};
}
if (damage.empty()) { if (damage.empty()) {
g_pHyprOpenGL->m_RenderData.damage = damage; g_pHyprOpenGL->m_RenderData.damage = damage;
@ -198,7 +200,9 @@ CRegion CRenderPass::render(const CRegion& damage_) {
void CRenderPass::renderDebugData() { void CRenderPass::renderDebugData() {
CBox box = {{}, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize}; CBox box = {{}, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize};
g_pHyprOpenGL->renderRectWithDamage(&box, Colors::RED.modifyA(0.1F), occludedRegion); for (const auto& rg : occludedRegions) {
g_pHyprOpenGL->renderRectWithDamage(&box, Colors::RED.modifyA(0.1F), rg);
}
g_pHyprOpenGL->renderRectWithDamage(&box, Colors::GREEN.modifyA(0.1F), totalLiveBlurRegion); g_pHyprOpenGL->renderRectWithDamage(&box, Colors::GREEN.modifyA(0.1F), totalLiveBlurRegion);
std::unordered_map<CWLSurfaceResource*, float> offsets; std::unordered_map<CWLSurfaceResource*, float> offsets;
@ -222,12 +226,13 @@ void CRenderPass::renderDebugData() {
if (box.intersection(CBox{{}, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize}).empty()) if (box.intersection(CBox{{}, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize}).empty())
return; return;
g_pHyprOpenGL->renderRectWithDamage(&box, color, CRegion{0, 0, INT32_MAX, INT32_MAX});
if (offsets.contains(surface.get())) if (offsets.contains(surface.get()))
box.translate(Vector2D{0.F, offsets[surface.get()]}); box.translate(Vector2D{0.F, offsets[surface.get()]});
else else
offsets[surface.get()] = 0; offsets[surface.get()] = 0;
g_pHyprOpenGL->renderRectWithDamage(&box, Colors::PURPLE.modifyA(0.1F), CRegion{0, 0, INT32_MAX, INT32_MAX});
box = {box.pos(), texture->m_vSize}; box = {box.pos(), texture->m_vSize};
g_pHyprOpenGL->renderRectWithDamage(&box, CHyprColor{0.F, 0.F, 0.F, 0.2F}, CRegion{0, 0, INT32_MAX, INT32_MAX}, std::min(5.0, box.size().y)); g_pHyprOpenGL->renderRectWithDamage(&box, CHyprColor{0.F, 0.F, 0.F, 0.2F}, CRegion{0, 0, INT32_MAX, INT32_MAX}, std::min(5.0, box.size().y));
g_pHyprOpenGL->renderTexture(texture, &box, 1.F); g_pHyprOpenGL->renderTexture(texture, &box, 1.F);
@ -239,6 +244,34 @@ void CRenderPass::renderDebugData() {
renderHLSurface(debugData.pointerFocusText, g_pSeatManager->state.pointerFocus.lock(), Colors::ORANGE.modifyA(0.1F)); renderHLSurface(debugData.pointerFocusText, g_pSeatManager->state.pointerFocus.lock(), Colors::ORANGE.modifyA(0.1F));
if (g_pCompositor->m_pLastWindow) if (g_pCompositor->m_pLastWindow)
renderHLSurface(debugData.lastWindowText, g_pCompositor->m_pLastWindow->m_pWLSurface->resource(), Colors::LIGHT_BLUE.modifyA(0.1F)); renderHLSurface(debugData.lastWindowText, g_pCompositor->m_pLastWindow->m_pWLSurface->resource(), Colors::LIGHT_BLUE.modifyA(0.1F));
const auto DISCARDED_ELEMENTS = std::count_if(m_vPassElements.begin(), m_vPassElements.end(), [](const auto& e) { return e->discard; });
auto tex = g_pHyprOpenGL->renderText(std::format("occlusion layers: {}\npass elements: {} ({} discarded)\nviewport: {:X0}", occludedRegions.size(), m_vPassElements.size(),
DISCARDED_ELEMENTS, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize),
Colors::WHITE, 12);
if (tex) {
box = CBox{{0.F, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.y - tex->m_vSize.y}, tex->m_vSize}.scale(g_pHyprOpenGL->m_RenderData.pMonitor->scale);
g_pHyprOpenGL->renderTexture(tex, &box, 1.F);
}
std::string passStructure;
auto yn = [](const bool val) -> const char* { return val ? "yes" : "no"; };
auto tick = [](const bool val) -> const char* { return val ? "" : ""; };
for (const auto& el : m_vPassElements | std::views::reverse) {
passStructure += std::format("{} {} (bb: {} op: {})\n", tick(!el->discard), el->element->passName(), yn(el->element->boundingBox().has_value()),
yn(!el->element->opaqueRegion().empty()));
}
if (!passStructure.empty())
passStructure.pop_back();
tex = g_pHyprOpenGL->renderText(passStructure, Colors::WHITE, 12);
if (tex) {
box = CBox{{g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.x - tex->m_vSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.y - tex->m_vSize.y}, tex->m_vSize}.scale(
g_pHyprOpenGL->m_RenderData.pMonitor->scale);
g_pHyprOpenGL->renderTexture(tex, &box, 1.F);
}
} }
float CRenderPass::oneBlurRadius() { float CRenderPass::oneBlurRadius() {

View file

@ -20,7 +20,7 @@ class CRenderPass {
private: private:
CRegion damage; CRegion damage;
CRegion occludedRegion; std::vector<CRegion> occludedRegions;
CRegion totalLiveBlurRegion; CRegion totalLiveBlurRegion;
struct SPassElementData { struct SPassElementData {

View file

@ -10,9 +10,9 @@ void CRectPassElement::draw(const CRegion& damage) {
return; return;
if (data.color.a == 1.F || !data.blur) if (data.color.a == 1.F || !data.blur)
g_pHyprOpenGL->renderRectWithDamage(&data.box, data.color, damage, data.round); g_pHyprOpenGL->renderRectWithDamage(&data.box, data.color, damage, data.round, data.roundingPower);
else else
g_pHyprOpenGL->renderRectWithBlur(&data.box, data.color, data.round, data.blurA, data.xray); g_pHyprOpenGL->renderRectWithBlur(&data.box, data.color, data.round, data.roundingPower, data.blurA, data.xray);
} }
bool CRectPassElement::needsLiveBlur() { bool CRectPassElement::needsLiveBlur() {

View file

@ -7,6 +7,7 @@ class CRectPassElement : public IPassElement {
CBox box; CBox box;
CHyprColor color; CHyprColor color;
int round = 0; int round = 0;
float roundingPower = 2.0f;
bool blur = false, xray = false; bool blur = false, xray = false;
float blurA = 1.F; float blurA = 1.F;
}; };

View file

@ -77,8 +77,10 @@ void CSurfacePassElement::draw(const CRegion& damage) {
const bool MISALIGNEDFSV1 = std::floor(data.pMonitor->scale) != data.pMonitor->scale /* Fractional */ && data.surface->current.scale == 1 /* fs protocol */ && const bool MISALIGNEDFSV1 = std::floor(data.pMonitor->scale) != data.pMonitor->scale /* Fractional */ && data.surface->current.scale == 1 /* fs protocol */ &&
windowBox.size() != data.surface->current.bufferSize /* misaligned */ && DELTALESSTHAN(windowBox.width, data.surface->current.bufferSize.x, 3) && windowBox.size() != data.surface->current.bufferSize /* misaligned */ && DELTALESSTHAN(windowBox.width, data.surface->current.bufferSize.x, 3) &&
DELTALESSTHAN(windowBox.height, data.surface->current.bufferSize.y, 3) /* off by one-or-two */ && DELTALESSTHAN(windowBox.height, data.surface->current.bufferSize.y, 3) /* off by one-or-two */ &&
(!data.pWindow || (!data.pWindow->m_vRealSize.isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */; (!data.pWindow || (!data.pWindow->m_vRealSize->isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */;
if (data.surface->colorManagement.valid())
Debug::log(TRACE, "FIXME: rendering surface with color management enabled, should apply necessary transformations");
g_pHyprRenderer->calculateUVForSurface(data.pWindow, data.surface, data.pMonitor->self.lock(), data.mainSurface, windowBox.size(), PROJSIZEUNSCALED, MISALIGNEDFSV1); g_pHyprRenderer->calculateUVForSurface(data.pWindow, data.surface, data.pMonitor->self.lock(), data.mainSurface, windowBox.size(), PROJSIZEUNSCALED, MISALIGNEDFSV1);
// check for fractional scale surfaces misaligning the buffer size // check for fractional scale surfaces misaligning the buffer size
@ -89,11 +91,14 @@ void CSurfacePassElement::draw(const CRegion& damage) {
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true;
float rounding = data.rounding; float rounding = data.rounding;
float roundingPower = data.roundingPower;
rounding -= 1; // to fix a border issue rounding -= 1; // to fix a border issue
if (data.dontRound) if (data.dontRound) {
rounding = 0; rounding = 0;
roundingPower = 2.0f;
}
const bool WINDOWOPAQUE = data.pWindow && data.pWindow->m_pWLSurface->resource() == data.surface ? data.pWindow->opaque() : false; const bool WINDOWOPAQUE = data.pWindow && data.pWindow->m_pWLSurface->resource() == data.surface ? data.pWindow->opaque() : false;
const bool CANDISABLEBLEND = ALPHA >= 1.f && OVERALL_ALPHA >= 1.f && rounding == 0 && WINDOWOPAQUE; const bool CANDISABLEBLEND = ALPHA >= 1.f && OVERALL_ALPHA >= 1.f && rounding == 0 && WINDOWOPAQUE;
@ -108,14 +113,14 @@ void CSurfacePassElement::draw(const CRegion& damage) {
// to what we do for misaligned surfaces (blur the entire thing and then render shit without blur) // to what we do for misaligned surfaces (blur the entire thing and then render shit without blur)
if (data.surfaceCounter == 0 && !data.popup) { if (data.surfaceCounter == 0 && !data.popup) {
if (BLUR) if (BLUR)
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, data.surface, rounding, data.blockBlurOptimization, data.fadeAlpha, OVERALL_ALPHA); g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, data.surface, rounding, roundingPower, data.blockBlurOptimization, data.fadeAlpha, OVERALL_ALPHA);
else else
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA * OVERALL_ALPHA, rounding, false, true); g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA * OVERALL_ALPHA, rounding, roundingPower, false, true);
} else { } else {
if (BLUR && data.popup) if (BLUR && data.popup)
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, data.surface, rounding, true, data.fadeAlpha, OVERALL_ALPHA); g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, ALPHA, data.surface, rounding, roundingPower, true, data.fadeAlpha, OVERALL_ALPHA);
else else
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA * OVERALL_ALPHA, rounding, false, true); g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, ALPHA * OVERALL_ALPHA, rounding, roundingPower, false, true);
} }
if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) if (!g_pHyprRenderer->m_bBlockSurfaceFeedback)
@ -145,8 +150,8 @@ CBox CSurfacePassElement::getTexBox() {
if (!INTERACTIVERESIZEINPROGRESS) { if (!INTERACTIVERESIZEINPROGRESS) {
windowBox.translate(CORRECT); windowBox.translate(CORRECT);
windowBox.width = SIZE.x * (PWINDOW->m_vRealSize.value().x / PWINDOW->m_vReportedSize.x); windowBox.width = SIZE.x * (PWINDOW->m_vRealSize->value().x / PWINDOW->m_vReportedSize.x);
windowBox.height = SIZE.y * (PWINDOW->m_vRealSize.value().y / PWINDOW->m_vReportedSize.y); windowBox.height = SIZE.y * (PWINDOW->m_vRealSize->value().y / PWINDOW->m_vReportedSize.y);
} else { } else {
windowBox.width = SIZE.x; windowBox.width = SIZE.x;
windowBox.height = SIZE.y; windowBox.height = SIZE.y;
@ -156,10 +161,10 @@ CBox CSurfacePassElement::getTexBox() {
} else { // here we clamp to 2, these might be some tiny specks } else { // here we clamp to 2, these might be some tiny specks
windowBox = {(int)outputX + data.pos.x + data.localPos.x, (int)outputY + data.pos.y + data.localPos.y, std::max((float)data.surface->current.size.x, 2.F), windowBox = {(int)outputX + data.pos.x + data.localPos.x, (int)outputY + data.pos.y + data.localPos.y, std::max((float)data.surface->current.size.x, 2.F),
std::max((float)data.surface->current.size.y, 2.F)}; std::max((float)data.surface->current.size.y, 2.F)};
if (data.pWindow && data.pWindow->m_vRealSize.isBeingAnimated() && data.surface && !data.mainSurface && data.squishOversized /* subsurface */) { if (data.pWindow && data.pWindow->m_vRealSize->isBeingAnimated() && data.surface && !data.mainSurface && data.squishOversized /* subsurface */) {
// adjust subsurfaces to the window // adjust subsurfaces to the window
windowBox.width = (windowBox.width / data.pWindow->m_vReportedSize.x) * data.pWindow->m_vRealSize.value().x; windowBox.width = (windowBox.width / data.pWindow->m_vReportedSize.x) * data.pWindow->m_vRealSize->value().x;
windowBox.height = (windowBox.height / data.pWindow->m_vReportedSize.y) * data.pWindow->m_vRealSize.value().y; windowBox.height = (windowBox.height / data.pWindow->m_vReportedSize.y) * data.pWindow->m_vRealSize->value().y;
} }
} }

View file

@ -13,29 +13,16 @@ class CSurfacePassElement : public IPassElement {
timespec* when = nullptr; timespec* when = nullptr;
Vector2D pos, localPos; Vector2D pos, localPos;
// for iters
void* data = nullptr; void* data = nullptr;
SP<CWLSurfaceResource> surface = nullptr; SP<CWLSurfaceResource> surface = nullptr;
SP<CTexture> texture = nullptr; SP<CTexture> texture = nullptr;
bool mainSurface = true; bool mainSurface = true;
double w = 0, h = 0; double w = 0, h = 0;
int rounding = 0;
// for rounding
bool dontRound = true; bool dontRound = true;
float roundingPower = 2.0F;
// for fade
float fadeAlpha = 1.f;
// for alpha settings
float alpha = 1.f;
// for decorations (border)
bool decorate = false; bool decorate = false;
float alpha = 1.F, fadeAlpha = 1.F;
// for custom round values
int rounding = -1; // -1 means not set
// for blurring
bool blur = false; bool blur = false;
bool blockBlurOptimization = false; bool blockBlurOptimization = false;

View file

@ -18,7 +18,8 @@ void CTexPassElement::draw(const CRegion& damage) {
if (data.replaceProjection) if (data.replaceProjection)
g_pHyprOpenGL->m_RenderData.monitorProjection = *data.replaceProjection; g_pHyprOpenGL->m_RenderData.monitorProjection = *data.replaceProjection;
g_pHyprOpenGL->renderTextureInternalWithDamage(data.tex, &data.box, data.a, data.damage.empty() ? damage : data.damage, data.round, data.syncTimeline, data.syncPoint); g_pHyprOpenGL->renderTextureInternalWithDamage(data.tex, &data.box, data.a, data.damage.empty() ? damage : data.damage, data.round, data.roundingPower, data.syncTimeline,
data.syncPoint);
if (data.replaceProjection) if (data.replaceProjection)
g_pHyprOpenGL->m_RenderData.monitorProjection = g_pHyprOpenGL->m_RenderData.pMonitor->projMatrix; g_pHyprOpenGL->m_RenderData.monitorProjection = g_pHyprOpenGL->m_RenderData.pMonitor->projMatrix;
} }

View file

@ -14,6 +14,7 @@ class CTexPassElement : public IPassElement {
float a = 1.F; float a = 1.F;
CRegion damage; CRegion damage;
int round = 0; int round = 0;
float roundingPower = 2.0f;
bool flipEndFrame = false; bool flipEndFrame = false;
SP<CSyncTimeline> syncTimeline; SP<CSyncTimeline> syncTimeline;
int64_t syncPoint = 0; int64_t syncPoint = 0;

View file

@ -15,6 +15,7 @@ uniform vec2 fullSize;
uniform vec2 fullSizeUntransformed; uniform vec2 fullSizeUntransformed;
uniform float radius; uniform float radius;
uniform float radiusOuter; uniform float radiusOuter;
uniform float roundingPower;
uniform float thick; uniform float thick;
// Gradients are in OkLabA!!!! {l, a, b, alpha} // Gradients are in OkLabA!!!! {l, a, b, alpha}
@ -138,8 +139,8 @@ void main() {
const float SMOOTHING_CONSTANT = )#" + const float SMOOTHING_CONSTANT = )#" +
std::format("{:.7f}", SHADER_ROUNDED_SMOOTHING_FACTOR) + R"#(; std::format("{:.7f}", SHADER_ROUNDED_SMOOTHING_FACTOR) + R"#(;
float dist = length(pixCoord); float dist = pow(pow(pixCoord.x,roundingPower)+pow(pixCoord.y,roundingPower),1.0/roundingPower);
float distOuter = length(pixCoordOuter); float distOuter = pow(pow(pixCoordOuter.x,roundingPower)+pow(pixCoordOuter.y,roundingPower),1.0/roundingPower);
float h = (thick / 2.0); float h = (thick / 2.0);
if (dist < radius - h) { if (dist < radius - h) {

View file

@ -11,6 +11,7 @@ uniform vec2 topLeft;
uniform vec2 bottomRight; uniform vec2 bottomRight;
uniform vec2 fullSize; uniform vec2 fullSize;
uniform float radius; uniform float radius;
uniform float roundingPower;
uniform float range; uniform float range;
uniform float shadowPower; uniform float shadowPower;
@ -26,6 +27,10 @@ float pixAlphaRoundedDistance(float distanceToCorner) {
return 1.0; return 1.0;
} }
float modifiedLength(vec2 a) {
return pow(pow(abs(a.x),roundingPower)+pow(abs(a.y),roundingPower),1.0/roundingPower);
}
void main() { void main() {
vec4 pixColor = v_color; vec4 pixColor = v_color;
@ -40,21 +45,21 @@ void main() {
if (pixCoord[0] < topLeft[0]) { if (pixCoord[0] < topLeft[0]) {
if (pixCoord[1] < topLeft[1]) { if (pixCoord[1] < topLeft[1]) {
// top left // top left
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, topLeft)); pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - topLeft));
done = true; done = true;
} else if (pixCoord[1] > bottomRight[1]) { } else if (pixCoord[1] > bottomRight[1]) {
// bottom left // bottom left
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, vec2(topLeft[0], bottomRight[1]))); pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - vec2(topLeft[0], bottomRight[1])));
done = true; done = true;
} }
} else if (pixCoord[0] > bottomRight[0]) { } else if (pixCoord[0] > bottomRight[0]) {
if (pixCoord[1] < topLeft[1]) { if (pixCoord[1] < topLeft[1]) {
// top right // top right
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, vec2(bottomRight[0], topLeft[1]))); pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - vec2(bottomRight[0], topLeft[1])));
done = true; done = true;
} else if (pixCoord[1] > bottomRight[1]) { } else if (pixCoord[1] > bottomRight[1]) {
// bottom right // bottom right
pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(distance(pixCoord, bottomRight)); pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - bottomRight));
done = true; done = true;
} }
} }

View file

@ -21,21 +21,16 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar
if (pixCoord.x + pixCoord.y > radius) { if (pixCoord.x + pixCoord.y > radius) {
float dist = length(pixCoord); float dist = pow(pow(pixCoord.x, roundingPower) + pow(pixCoord.y, roundingPower), 1.0/roundingPower);
if (dist > radius + SMOOTHING_CONSTANT * 2.0) if (dist > radius + SMOOTHING_CONSTANT)
discard; discard;
if (dist > radius - SMOOTHING_CONSTANT * 2.0) {
float dist = length(pixCoord);
float normalized = 1.0 - smoothstep(0.0, 1.0, (dist - radius + SMOOTHING_CONSTANT) / (SMOOTHING_CONSTANT * 2.0)); float normalized = 1.0 - smoothstep(0.0, 1.0, (dist - radius + SMOOTHING_CONSTANT) / (SMOOTHING_CONSTANT * 2.0));
)#" + )#" +
colorVarName + R"#( = )#" + colorVarName + R"#( * normalized; colorVarName + R"#( = )#" + colorVarName + R"#( * normalized;
} }
}
)#"; )#";
}; };
@ -63,6 +58,7 @@ varying vec4 v_color;
uniform vec2 topLeft; uniform vec2 topLeft;
uniform vec2 fullSize; uniform vec2 fullSize;
uniform float radius; uniform float radius;
uniform float roundingPower;
void main() { void main() {
@ -107,6 +103,7 @@ uniform float alpha;
uniform vec2 topLeft; uniform vec2 topLeft;
uniform vec2 fullSize; uniform vec2 fullSize;
uniform float radius; uniform float radius;
uniform float roundingPower;
uniform int discardOpaque; uniform int discardOpaque;
uniform int discardAlpha; uniform int discardAlpha;
@ -167,6 +164,7 @@ uniform float alpha;
uniform vec2 topLeft; uniform vec2 topLeft;
uniform vec2 fullSize; uniform vec2 fullSize;
uniform float radius; uniform float radius;
uniform float roundingPower;
uniform int discardOpaque; uniform int discardOpaque;
uniform int discardAlpha; uniform int discardAlpha;
@ -440,6 +438,7 @@ uniform float alpha;
uniform vec2 topLeft; uniform vec2 topLeft;
uniform vec2 fullSize; uniform vec2 fullSize;
uniform float radius; uniform float radius;
uniform float roundingPower;
uniform int discardOpaque; uniform int discardOpaque;
uniform int discardAlpha; uniform int discardAlpha;