Compare commits

...

77 Commits

Author SHA1 Message Date
vaxerski
9654749244 props: bump version to 0.28.0 2023-08-03 18:00:10 +02:00
vaxerski
da46e01b97 config: update default config for new blur changes 2023-08-03 15:16:37 +02:00
Vaxry
d96f8ff0fe renderer: Various Blur Improvements (#2877)
* move blur to its own category

* blur improvements, contrast, brightness, noise
2023-08-03 15:11:10 +02:00
vaxerski
5c50fac907 windowrules: add workspace param 2023-08-02 13:21:38 +02:00
vaxerski
51cda87fe4 hyprctl: rerender on cursor_zoom_factor dynamic calls 2023-08-01 18:08:53 +02:00
vaxerski
da0c74cdf0 config: schedule frame for mons on reload 2023-08-01 15:47:56 +02:00
vaxerski
08651736ad keybinds: add toggle to dpms 2023-07-30 16:46:37 +02:00
Mihai Fufezan
bf0d8ab4a3 NixOS module: check system version for fonts 2023-07-29 23:05:35 +03:00
rewine
a805905a49 Nix: move wayland-scanner to nativeBuildInputs (#2816) 2023-07-29 16:31:01 +03:00
vaxerski
f61a714320 renderer: cleanup old redundancies in CFramebuffer 2023-07-29 13:27:40 +02:00
Po-Yeh Chen
77818e3457 xwayland: Add temporary fix for #2808 by adding nullptr check. (#2829)
* Add temporary fix for #2808 by adding nullptr check.

* Remove redundency.
2023-07-28 17:12:24 +02:00
Alfred Wingate
2ea7d10d04 assets/meson.build: install new wallpapers
* Previous changes forgot to update meson with the new wallpapers.

70dae78c1b
9bad2a8180

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-07-27 13:25:40 +03:00
Gioele Pannetto
ef26f711c9 Added git tag in json version command (#2821) 2023-07-27 10:51:04 +02:00
Okirshen
c36c30c17b Renamed deprecated value in nix config
See 83793ca898 for more info.
2023-07-27 11:36:35 +03:00
vaxerski
a9b8e2159c renderer: reset scissor after renderTexturePrimitive 2023-07-25 13:33:08 +02:00
vaxerski
4173d2ccf6 input: fix styling 2023-07-25 11:49:36 +02:00
Mihai Fufezan
427321c5ab Nix: bump nixpkgs
Nix: bump wlroots
2023-07-25 10:27:41 +03:00
vaxerski
f5913135c6 input: add support for cursor-shape-v1 2023-07-24 18:50:17 +02:00
vaxerski
76d4a50af3 deps: update wlroots 2023-07-24 18:34:25 +02:00
vaxerski
603de16f9a renderer: adjust distribution of backgrounds 2023-07-24 18:30:00 +02:00
ferrreo
f6b340cc19 init: Fix for issue #2797 (#2799)
* Fix for issue #2797

* Fix for issue #2797

* Fix for issue #2797
2023-07-24 18:26:24 +02:00
memchr
76c6e09e39 keybinds: Make moveintogroup locking check configurable (#2796)
* groups: revert to the old moveintogroup behaviour, ignore m_sGroupData.locked

* groups: Make moveintogroup locking check configurable
2023-07-24 18:25:10 +02:00
vaxerski
9bad2a8180 backgrounds: add hypr chan var 2 2023-07-24 18:22:39 +02:00
MightyPlaza
6db3c4ef5e layout: no_border_when_only-improvements (#2791) 2023-07-24 12:13:40 +02:00
psentee
2bbe3aa122 nix: use final.hyprland instead of prev.hyprland in waybar-hyprland
Currently, waybar-hyprland package adds `prev.hyprland` to `$PATH`. This is nixpkgs' default hyprland, not hyprland injected by this overlay. I'd expect we want waybar-hyprland to depend on what's in `pkgs.hyprland` after this (and possibly user's other overlays) are applied – which is `final.hyprland`.
2023-07-23 23:19:57 +03:00
Mily
9fc5f4c48b init: Request SCHED_RR using CAP_SYS_NICE and add Python to nix dev shell (#2690)
* nix: add python3 to devShell

* init: request SCHED_RR scheduling policy

* init: checks if host supports reseting scheduler on fork

* init: make gainRealTime more compatible with other OSes

* init: remove linux-only code
2023-07-23 20:51:00 +02:00
MightyPlaza
50e6f368ff windowrules: implements nomaximizerequest (#2785)
* Window.hpp

* ConfigManager.cpp

* Windows.cpp

* fix maximize event
2023-07-23 19:47:41 +02:00
vaxerski
975c4175b2 hyprctl: unify and sanitize ver commit msg better 2023-07-23 19:43:15 +02:00
vaxerski
af395a8f55 windowrules: fix opacity override 2023-07-23 16:03:59 +02:00
vaxerski
90f69782ee window: fix segfault in boundingbox 2023-07-23 16:02:35 +02:00
vaxerski
5a64c73e05 render: use primitive end() only when no screen shader is present 2023-07-23 15:54:27 +02:00
end-4
9845f99b60 add config option to enable/disable new intuitive resizing (#2774)
dwindle:smart_resizing = 1 by default
== 1 then use new resizing
else use old resizing
2023-07-23 15:50:09 +02:00
MightyPlaza
d3bba2489d render: Border fixes (#2781)
* Window.cpp

* layout

* CHyprGroupBarDecoration.cpp
2023-07-23 15:49:49 +02:00
Rachel Knight
b21644b611 input: Fix #2376 mouse movement bug in XWayland (#2776) 2023-07-22 19:31:36 +02:00
vaxerski
b70553cf46 opengl: fix warn 2023-07-22 19:26:56 +02:00
vaxerski
1a7fb1572a renderer: disable init anim on disabled animations 2023-07-22 19:26:44 +02:00
outfoxxed
375e8385ee Fix background occlusion ignoring monitor position (#2771) 2023-07-22 10:19:51 +02:00
vaxerski
27dd07f1b8 windowrules: improve opacity 2023-07-21 19:05:00 +02:00
vaxerski
263b9c6e39 socket1: add a timeout for requests 2023-07-21 17:20:23 +02:00
vaxerski
d7e9eb65e2 renderer: use primitive rendering for copying buffers 2023-07-21 17:11:54 +02:00
Mihai Fufezan
0af97636fa Nix/HM module: solve conflict with upstream HM module 2023-07-21 15:55:56 +03:00
vaxerski
1ec0b7b59a forms: bring back auto labels 2023-07-20 21:54:57 +02:00
vaxerski
f864b15427 background: add option to force hypr chan 2023-07-20 21:01:07 +02:00
vaxerski
61dc0909ae layout: use warp() instead of setValue() 2023-07-20 20:03:27 +02:00
MightyPlaza
ca54ceff6f groups: add use_current_group_pos (#2759) 2023-07-20 19:48:32 +02:00
vaxerski
6c1f4faff2 animationmgr: avoid looping over all avars in favor of only active ones 2023-07-20 19:26:10 +02:00
vaxerski
7940f779e9 cmakelists: move tracy to debug section 2023-07-20 18:29:37 +02:00
vaxerski
a3f6a72a51 region: allow ctor from pixman_box32_t 2023-07-20 18:27:28 +02:00
vaxerski
d2a8b8c2de renderer: cleanup back buffer skip checks 2023-07-20 18:27:14 +02:00
vaxerski
833d73df09 shaders: short-circuit rounding if radius <= 0 2023-07-20 18:18:53 +02:00
vaxerski
23eda1411b renderer: scale box for occlusion 2023-07-20 18:12:29 +02:00
vaxerski
ff598b0827 renderer: don't occlude when pre-blur is queued 2023-07-20 18:03:47 +02:00
vaxerski
e5dd133808 cmake: fix compile 2023-07-20 17:57:02 +02:00
vaxerski
a3e1e5e8ba tracy: add more opengl zones 2023-07-20 17:51:38 +02:00
vaxerski
a921c5b89e Debug: add tracy 2023-07-20 17:47:49 +02:00
vaxerski
948855a984 renderer: add canSkipBackBufferClear 2023-07-20 14:11:05 +02:00
vaxerski
547305c7ed opengl: adjust blend and reduce the usage of clear 2023-07-20 13:49:28 +02:00
vaxerski
b65adf8d4a toplevelexport: support dmabuf + various fixes 2023-07-20 12:42:25 +02:00
fufexan
3a1496b4eb Nix: bump wlroots 2023-07-20 11:20:22 +03:00
Mihai Fufezan
a58b70ca07 CI: update scripts 2023-07-20 11:20:22 +03:00
Mihai Fufezan
91e3c654d3 Nix: move patches to subdir 2023-07-20 11:20:22 +03:00
vaxerski
7091d4e597 animationmanager: optimize avar state 2023-07-19 22:40:03 +02:00
vaxerski
80cd2ef3d7 renderer: remove unused var 2023-07-19 21:10:42 +02:00
vaxerski
2c2314faa0 renderer: take workspace offset into account for occlusion 2023-07-19 21:08:49 +02:00
vaxerski
88c2a02773 render: avoid allocating mirrorfb for no reason 2023-07-19 21:04:45 +02:00
Vaxry
89b87158db internal: Wrap regions (#2750) 2023-07-19 20:09:49 +02:00
vaxerski
ce9896204a renderer: fix rounding in renderSurface 2023-07-19 20:06:19 +02:00
vaxerski
f4f0f35c5b renderer: add occlusion for back layers 2023-07-19 16:13:55 +02:00
vaxerski
b08b72358a props: bump ver to 0.27.2 2023-07-19 13:31:35 +02:00
vaxerski
aac75ddcbf screencopy: guard region buffer values in frameDamage 2023-07-19 13:10:41 +02:00
outfoxxed
5cd5631fb2 Add bringWindowToTop function to IHyprLayout (#2747)
* Add bringWindowToTop function to IHyprLayout

* Rename `bringWindowToTop` to `requestFocusForWindow`

* Fix doc
2023-07-19 12:39:45 +02:00
vaxerski
b8a7b09092 screencopy: use wlr_buffer api for shm copies 2023-07-19 12:24:41 +02:00
vaxerski
81f4a4f471 screencopy: improve shm handling 2023-07-19 00:51:38 +02:00
vaxerski
2623364dbd no_xwayland: fix redef 2023-07-19 00:33:47 +02:00
MightyPlaza
3b03597784 keybinds: movegroupwindow-improvement (#2740)
* movegroupwindow-improvement

* use std::swap
2023-07-19 00:30:10 +02:00
vaxerski
ce9c5fd722 render: set refresh to 0 for both wl and x11 backends 2023-07-19 00:28:15 +02:00
vaxerski
f2999e84b9 render: set refresh to 0 for wayland backend outputs 2023-07-19 00:02:57 +02:00
78 changed files with 1388 additions and 695 deletions

View File

@@ -1,5 +1,6 @@
name: Bug Report
description: Something is not working right
labels: ["bug"]
body:
- type: markdown
attributes:

View File

@@ -1,5 +1,6 @@
name: Feature Request
description: I'd like to request additional functionality
labels: ["enhancement"]
body:
- type: markdown
attributes:

3
.gitmodules vendored
View File

@@ -7,3 +7,6 @@
[submodule "subprojects/udis86"]
path = subprojects/udis86
url = https://github.com/canihavesomecoffee/udis86
[submodule "subprojects/tracy"]
path = subprojects/tracy
url = https://github.com/wolfpld/tracy

View File

@@ -103,6 +103,21 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
add_compile_options(-fsanitize=address)
endif()
if(USE_TRACY)
message(STATUS "Tracy is turned on")
option( TRACY_ENABLE "" ON)
option( TRACY_ON_DEMAND "" ON)
add_subdirectory (subprojects/tracy)
target_link_libraries(Hyprland Tracy::TracyClient)
if(USE_TRACY_GPU)
message(STATUS "Tracy GPU Profiling is turned on")
add_compile_definitions(USE_TRACY_GPU)
endif()
endif()
add_compile_options(-pg -no-pie -fno-builtin)
add_link_options(-pg -no-pie -fno-builtin)
endif()
@@ -149,14 +164,14 @@ target_compile_definitions(Hyprland
"GIT_DIRTY=\"${GIT_DIRTY}\""
"GIT_TAG=\"${GIT_TAG}\"")
target_link_libraries(Hyprland rt)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
message(STATUS "Setting link libraries")
target_link_libraries(Hyprland rt PkgConfig::deps)
function(protocol protoPath protoName external)
if (external)
execute_process(
@@ -177,8 +192,6 @@ function(protocol protoPath protoName external)
endif()
endfunction()
target_link_libraries(Hyprland PkgConfig::deps)
target_link_libraries(Hyprland
${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.12032 # wlroots is provided by us
OpenGL::EGL
@@ -202,3 +215,4 @@ protocol("unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml" "linux-dmabuf-unst
protocol("unstable/xdg-output/xdg-output-unstable-v1.xml" "xdg-output-unstable-v1" false)
protocol("staging/fractional-scale/fractional-scale-v1.xml" "fractional-scale-v1" false)
protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false)
protocol("staging/cursor-shape/cursor-shape-v1.xml" "cursor-shape-v1" false)

View File

@@ -44,12 +44,7 @@ install:
cp -f ./hyprctl/hyprctl ${PREFIX}/bin
if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi
mkdir -p ${PREFIX}/share/hyprland
cp ./assets/wall_2K.png ${PREFIX}/share/hyprland
cp ./assets/wall_4K.png ${PREFIX}/share/hyprland
cp ./assets/wall_8K.png ${PREFIX}/share/hyprland
cp ./assets/wall_anime_2K.png ${PREFIX}/share/hyprland
cp ./assets/wall_anime_4K.png ${PREFIX}/share/hyprland
cp ./assets/wall_anime_8K.png ${PREFIX}/share/hyprland
cp ./assets/wall_* ${PREFIX}/share/hyprland
mkdir -p ${PREFIX}/share/man/man1
install -m644 ./docs/*.1 ${PREFIX}/share/man/man1

View File

@@ -1,5 +1,7 @@
wallpapers = ['wall_2K.png', 'wall_4K.png', 'wall_8K.png']
wallpaper_types = ['', 'anime_', 'anime2_']
foreach wallpaper : wallpapers
install_data(wallpapers, install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
foreach type : wallpaper_types
foreach size : [2, 4, 8]
install_data(f'wall_@type@@size@K.png', install_dir: join_paths(get_option('datadir'), 'hyprland'), install_tag: 'runtime')
endforeach
endforeach

BIN
assets/wall_anime2_2K.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 KiB

BIN
assets/wall_anime2_4K.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
assets/wall_anime2_8K.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@@ -55,10 +55,12 @@ decoration {
# See https://wiki.hyprland.org/Configuring/Variables/ for more
rounding = 10
blur = true
blur_size = 3
blur_passes = 1
blur_new_optimizations = true
blur {
enabled = true
size = 3
passes = 1
}
drop_shadow = true
shadow_range = 4

13
flake.lock generated
View File

@@ -22,11 +22,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1688500189,
"narHash": "sha256-djYYiY4lzJOlXOnTHytH6BUugrxHDZjuGxTSrU4gt4M=",
"lastModified": 1690179384,
"narHash": "sha256-+arbgqFTAtoeKtepW9wCnA0njCOyoiDFyl0Q0SBSOtE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "78419edadf0fabbe5618643bd850b2f2198ed060",
"rev": "b12803b6d90e2e583429bb79b859ca53c348b39a",
"type": "github"
},
"original": {
@@ -48,17 +48,18 @@
"flake": false,
"locked": {
"host": "gitlab.freedesktop.org",
"lastModified": 1689611045,
"narHash": "sha256-3RTOlQabkNetQ4O4UzSf57JPco9VGVHhSU1ls5uKBeE=",
"lastModified": 1690165843,
"narHash": "sha256-gv5kjss6REeQG0BmvK2gTx7jHLRdCnP25po6It6I6N8=",
"owner": "wlroots",
"repo": "wlroots",
"rev": "7791ffe0584c4ac13c170e1661ce33bdbd4a9b9e",
"rev": "e8d545a9770a2473db32e0a0bfa757b05d2af4f3",
"type": "gitlab"
},
"original": {
"host": "gitlab.freedesktop.org",
"owner": "wlroots",
"repo": "wlroots",
"rev": "e8d545a9770a2473db32e0a0bfa757b05d2af4f3",
"type": "gitlab"
}
},

View File

@@ -5,7 +5,11 @@
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
wlroots = {
url = "gitlab:wlroots/wlroots?host=gitlab.freedesktop.org";
type = "gitlab";
host = "gitlab.freedesktop.org";
owner = "wlroots";
repo = "wlroots";
rev = "e8d545a9770a2473db32e0a0bfa757b05d2af4f3";
flake = false;
};
@@ -73,7 +77,7 @@
devShells = genSystems (system: {
default = pkgsFor.${system}.mkShell {
name = "hyprland-shell";
nativeBuildInputs = with pkgsFor.${system}; [cmake];
nativeBuildInputs = with pkgsFor.${system}; [ cmake python3 ];
buildInputs = [self.packages.${system}.wlroots-hyprland];
inputsFrom = [
self.packages.${system}.wlroots-hyprland

View File

@@ -60,6 +60,7 @@ in
ninja
pkg-config
makeWrapper
wayland-scanner
];
outputs = [
@@ -81,7 +82,6 @@ in
udis86
wayland
wayland-protocols
wayland-scanner
pciutils
(wlroots.override {inherit enableXWayland hidpiXWayland nvidiaPatches;})
]
@@ -102,9 +102,9 @@ in
patches = [
# make meson use the provided wlroots instead of the git submodule
./meson-build.patch
./patches/meson-build.patch
# fixes portals search path to be picked up from $XDG_DESKTOP_PORTAL_DIR
./portals.patch
./patches/portals.patch
];
postPatch = ''

View File

@@ -11,6 +11,8 @@ self: {
inherit (cfg) nvidiaPatches;
};
in {
disabledModules = ["services/window-managers/hyprland.nix"];
meta.maintainers = [lib.maintainers.fufexan];
options.wayland.windowManager.hyprland = {

View File

@@ -72,7 +72,11 @@ in {
};
};
fonts.enableDefaultFonts = mkDefault true;
fonts =
if versionOlder config.system.stateVersion "23.11"
then {enableDefaultFonts = mkDefault true;}
else {enableDefaultPackages = mkDefault true;};
hardware.opengl.enable = mkDefault true;
programs = {

View File

@@ -58,7 +58,7 @@ in {
'';
postFixup = ''
wrapProgram $out/bin/waybar \
--suffix PATH : ${lib.makeBinPath [ prev.hyprland ]}
--suffix PATH : ${lib.makeBinPath [final.hyprland]}
'';
mesonFlags = old.mesonFlags ++ ["-Dexperimental=true"];
});

View File

@@ -12,14 +12,8 @@ NEW_VER=$(nix eval --raw github:nixos/nixpkgs/nixos-unstable#mesa.version)
if [ "$CRT_VER" != "$NEW_VER" ]; then
echo "Updating Mesa $CRT_VER -> $NEW_VER and flake inputs"
# keep wlroots rev, as we don't want to update it
WLR_REV=$(nix flake metadata --json | jq -r '.locks.nodes.wlroots.locked.rev')
# update inputs to latest versions
nix flake update
# hold back wlroots (nix/update-wlroots.nix handles updating that)
nix flake lock --override-input wlroots "gitlab:wlroots/wlroots/$WLR_REV?host=gitlab.freedesktop.org"
else
echo "nixpkgs is up to date!"
fi

View File

@@ -1,17 +1,17 @@
#!/usr/bin/env -S nix shell nixpkgs#gawk nixpkgs#git nixpkgs#gnused nixpkgs#jq nixpkgs#ripgrep -c bash
#!/usr/bin/env -S nix shell nixpkgs#gawk nixpkgs#git nixpkgs#gnused nixpkgs#ripgrep -c bash
# get wlroots revision from submodule
SUB_REV=$(git submodule status | rg wlroots | awk '{ print substr($1,2)}')
SUB_REV=$(git submodule status | rg wlroots | awk '{ print substr($1,2) }')
# and from lockfile
CRT_REV=$(jq <flake.lock '.nodes.wlroots.locked.rev' -r)
CRT_REV=$(rg rev flake.nix | awk '{ print substr($3, 2, 40) }')
if [ "$SUB_REV" != "$CRT_REV" ]; then
echo "Updating wlroots..."
# update wlroots to submodule revision
nix flake lock --override-input wlroots "gitlab:wlroots/wlroots/$SUB_REV?host=gitlab.freedesktop.org"
sed -Ei "s/\w{40}/$SUB_REV/g" flake.nix subprojects/wlroots.wrap
nix flake lock
# fix revision in wlroots.wrap
sed -Ei "s/[a-z0-9]{40}/$SUB_REV/g" subprojects/wlroots.wrap
echo "wlroots: $CRT_REV -> $SUB_REV"
else
echo "wlroots is up to date!"
fi

View File

@@ -36,7 +36,7 @@ assert (lib.assertMsg (hidpiXWayland -> enableXWayland) ''
(old.patches or [])
++ (lib.optionals (enableXWayland && hidpiXWayland) [
# adapted from https://gitlab.freedesktop.org/lilydjwg/wlroots/-/commit/6c5ffcd1fee9e44780a6a8792f74ecfbe24a1ca7
./wlroots-hidpi.patch
./patches/wlroots-hidpi.patch
(fetchpatch {
url = "https://gitlab.freedesktop.org/wlroots/wlroots/-/commit/18595000f3a21502fd60bf213122859cc348f9af.diff";
sha256 = "sha256-jvfkAMh3gzkfuoRhB4E9T5X1Hu62wgUjj4tZkJm0mrI=";
@@ -44,7 +44,7 @@ assert (lib.assertMsg (hidpiXWayland -> enableXWayland) ''
})
])
++ (lib.optionals nvidiaPatches [
./wlroots-nvidia.patch
./patches/wlroots-nvidia.patch
]);
postPatch =
(old.postPatch or "")
@@ -66,8 +66,8 @@ assert (lib.assertMsg (hidpiXWayland -> enableXWayland) ''
patches =
(old.patches or [])
++ (lib.optionals hidpiXWayland [
./xwayland-vsync.patch
./xwayland-hidpi.patch
./patches/xwayland-vsync.patch
./patches/xwayland-hidpi.patch
]);
});
}

View File

@@ -1,3 +1,3 @@
{
"version": "0.27.1"
"version": "0.28.0"
}

View File

@@ -24,6 +24,7 @@ protocols = [
[wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'],
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
[wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'],
[wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml'],
['wlr-foreign-toplevel-management-unstable-v1.xml'],
['wlr-layer-shell-unstable-v1.xml'],
['wlr-output-power-management-unstable-v1.xml'],

View File

@@ -240,6 +240,8 @@ void CCompositor::initServer() {
m_sWLRSessionLockMgr = wlr_session_lock_manager_v1_create(m_sWLDisplay);
m_sWLRCursorShapeMgr = wlr_cursor_shape_manager_v1_create(m_sWLDisplay, 1);
if (!m_sWLRHeadlessBackend) {
Debug::log(CRIT, "Couldn't create the headless backend");
throw std::runtime_error("wlr_headless_backend_create() failed!");
@@ -297,6 +299,7 @@ void CCompositor::initAllSignals() {
addWLSignal(&m_sWLRActivation->events.request_activate, &Events::listen_activateXDG, m_sWLRActivation, "ActivationV1");
addWLSignal(&m_sWLRSessionLockMgr->events.new_lock, &Events::listen_newSessionLock, m_sWLRSessionLockMgr, "SessionLockMgr");
addWLSignal(&m_sWLRGammaCtrlMgr->events.set_gamma, &Events::listen_setGamma, m_sWLRGammaCtrlMgr, "GammaCtrlMgr");
addWLSignal(&m_sWLRCursorShapeMgr->events.request_set_shape, &Events::listen_setCursorShape, m_sWLRCursorShapeMgr, "CursorShapeMgr");
if (m_sWRLDRMLeaseMgr)
addWLSignal(&m_sWRLDRMLeaseMgr->events.request, &Events::listen_leaseRequest, &m_sWRLDRMLeaseMgr, "DRM");

View File

@@ -86,6 +86,7 @@ class CCompositor {
wlr_backend* m_sWLRHeadlessBackend;
wlr_session_lock_manager_v1* m_sWLRSessionLockMgr;
wlr_gamma_control_manager_v1* m_sWLRGammaCtrlMgr;
wlr_cursor_shape_manager_v1* m_sWLRCursorShapeMgr;
// ------------------------------------------------- //
std::string m_szWLDisplaySocket = "";
@@ -101,7 +102,7 @@ class CCompositor {
std::vector<CWindow*> m_vWindowsFadingOut;
std::vector<SLayerSurface*> m_vSurfacesFadingOut;
std::unordered_map<std::string, uint64_t> m_mMonitorIDMap;
std::unordered_map<std::string, uint64_t> m_mMonitorIDMap;
void initServer();
void startCompositor();

View File

@@ -25,12 +25,22 @@ CWindow::~CWindow() {
wlr_box CWindow::getFullWindowBoundingBox() {
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{};
auto borderSize = m_sSpecialRenderData.borderSize.toUnderlying() != -1 ? m_sSpecialRenderData.borderSize.toUnderlying() : WORKSPACERULE.borderSize.value_or(*PBORDERSIZE);
if (m_sAdditionalConfigData.borderSize.toUnderlying() != -1)
borderSize = m_sAdditionalConfigData.borderSize.toUnderlying();
borderSize *= m_sSpecialRenderData.border && !m_sAdditionalConfigData.forceNoBorder;
if (m_sAdditionalConfigData.dimAround) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
}
SWindowDecorationExtents maxExtents = {{*PBORDERSIZE + 2, *PBORDERSIZE + 2}, {*PBORDERSIZE + 2, *PBORDERSIZE + 2}};
SWindowDecorationExtents maxExtents = {{borderSize + 2, borderSize + 2}, {borderSize + 2, borderSize + 2}};
for (auto& wd : m_dWindowDecorations) {
@@ -234,16 +244,7 @@ void CWindow::createToplevelHandle() {
// handle events
hyprListener_toplevelActivate.initCallback(
&m_phForeignToplevel->events.request_activate,
[&](void* owner, void* data) {
if (isHidden() && m_sGroupData.pNextWindow) {
// grouped, change the current to us
setGroupCurrent(this);
}
g_pCompositor->focusWindow(this);
},
this, "Toplevel");
&m_phForeignToplevel->events.request_activate, [&](void* owner, void* data) { g_pLayoutManager->getCurrentLayout()->requestFocusForWindow(this); }, this, "Toplevel");
hyprListener_toplevelFullscreen.initCallback(
&m_phForeignToplevel->events.request_fullscreen,
@@ -485,20 +486,30 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
try {
CVarList vars(r.szRule, 0, ' ');
for (size_t i = 1 /* first item is "opacity" */; i < vars.size(); ++i) {
if (i == 1) {
// first arg, alpha
m_sSpecialRenderData.alpha = std::stof(vars[i]);
int opacityIDX = 0;
for (auto& r : vars) {
if (r == "opacity")
continue;
if (r == "override") {
if (opacityIDX == 1) {
m_sSpecialRenderData.alphaOverride = true;
m_sSpecialRenderData.alphaInactiveOverride = true;
} else if (opacityIDX == 2)
m_sSpecialRenderData.alphaInactiveOverride = true;
} else {
if (vars[i] == "override") {
if (i == 2) {
m_sSpecialRenderData.alphaOverride = true;
} else {
m_sSpecialRenderData.alphaInactiveOverride = true;
}
if (opacityIDX == 0) {
m_sSpecialRenderData.alpha = std::stof(r);
m_sSpecialRenderData.alphaInactive = std::stof(r);
} else if (opacityIDX == 1) {
m_sSpecialRenderData.alphaInactive = std::stof(r);
m_sSpecialRenderData.alphaInactiveOverride = false;
} else {
m_sSpecialRenderData.alphaInactive = std::stof(vars[i]);
throw std::runtime_error("more than 2 alpha values");
}
opacityIDX++;
}
}
} catch (std::exception& e) { Debug::log(ERR, "Opacity rule \"%s\" failed with: %s", r.szRule.c_str(), e.what()); }
@@ -673,31 +684,24 @@ void CWindow::setGroupCurrent(CWindow* pWindow) {
}
void CWindow::insertWindowToGroup(CWindow* pWindow) {
const auto PHEAD = getGroupHead();
const auto PTAIL = getGroupTail();
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("misc:group_insert_after_current")->intValue;
if (pWindow->m_sGroupData.pNextWindow) {
const auto PHEAD = pWindow->getGroupHead();
std::vector<CWindow*> members;
CWindow* curr = PHEAD;
do {
const auto PLAST = curr;
members.push_back(curr);
curr = curr->m_sGroupData.pNextWindow;
PLAST->m_sGroupData.pNextWindow = nullptr;
PLAST->m_sGroupData.head = false;
PLAST->m_sGroupData.locked = false;
} while (curr != PHEAD);
for (auto& w : members) {
insertWindowToGroup(w);
}
const auto BEGINAT = *USECURRPOS ? this : getGroupTail();
const auto ENDAT = *USECURRPOS ? m_sGroupData.pNextWindow : getGroupHead();
if (!pWindow->m_sGroupData.pNextWindow) {
BEGINAT->m_sGroupData.pNextWindow = pWindow;
pWindow->m_sGroupData.pNextWindow = ENDAT;
pWindow->m_sGroupData.head = false;
return;
}
PTAIL->m_sGroupData.pNextWindow = pWindow;
pWindow->m_sGroupData.pNextWindow = PHEAD;
const auto SHEAD = pWindow->getGroupHead();
const auto STAIL = pWindow->getGroupTail();
SHEAD->m_sGroupData.head = false;
BEGINAT->m_sGroupData.pNextWindow = SHEAD;
STAIL->m_sGroupData.pNextWindow = ENDAT;
}
CWindow* CWindow::getGroupPrevious() {
@@ -713,30 +717,23 @@ void CWindow::switchWithWindowInGroup(CWindow* pWindow) {
if (!m_sGroupData.pNextWindow || !pWindow->m_sGroupData.pNextWindow)
return;
// TODO: probably can be done more easily but I let C++ do the algorithm stuff for us
if (m_sGroupData.pNextWindow == pWindow) { // A -> this -> pWindow -> B >> A -> pWindow -> this -> B
getGroupPrevious()->m_sGroupData.pNextWindow = pWindow;
m_sGroupData.pNextWindow = pWindow->m_sGroupData.pNextWindow;
pWindow->m_sGroupData.pNextWindow = this;
std::vector<CWindow*> group;
group.push_back(this);
CWindow* curr = this->m_sGroupData.pNextWindow;
while (curr != this) {
group.push_back(curr);
curr = curr->m_sGroupData.pNextWindow;
}
} else if (pWindow->m_sGroupData.pNextWindow == this) { // A -> pWindow -> this -> B >> A -> this -> pWindow -> B
pWindow->getGroupPrevious()->m_sGroupData.pNextWindow = this;
pWindow->m_sGroupData.pNextWindow = m_sGroupData.pNextWindow;
m_sGroupData.pNextWindow = pWindow;
auto it1 = std::find(group.begin(), group.end(), this);
auto it2 = std::find(group.begin(), group.end(), pWindow);
std::iter_swap(it1, it2);
for (auto it = group.begin(); it != group.end(); ++it) {
if (std::next(it) == group.end()) {
(*it)->m_sGroupData.pNextWindow = *group.begin();
} else {
(*it)->m_sGroupData.pNextWindow = *std::next(it);
}
} else { // A -> this -> B | C -> pWindow -> D >> A -> pWindow -> B | C -> this -> D
std::swap(m_sGroupData.pNextWindow, pWindow->m_sGroupData.pNextWindow);
std::swap(getGroupPrevious()->m_sGroupData.pNextWindow, pWindow->getGroupPrevious()->m_sGroupData.pNextWindow);
}
std::swap(m_sGroupData.head, pWindow->m_sGroupData.head);
std::swap(m_sGroupData.locked, pWindow->m_sGroupData.locked);
}
void CWindow::updateGroupOutputs() {
@@ -761,6 +758,14 @@ Vector2D CWindow::middle() {
}
bool CWindow::opaque() {
if (m_fAlpha.fl() != 1.f || m_fActiveInactiveAlpha.fl() != 1.f)
return false;
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
if (PWORKSPACE->m_fAlpha.fl() != 1.f)
return false;
if (m_bIsX11)
return !m_uSurface.xwayland->has_alpha;
@@ -773,3 +778,11 @@ bool CWindow::opaque() {
return false;
}
float CWindow::rounding() {
static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
float rounding = m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_sAdditionalConfigData.rounding.toUnderlying();
return rounding;
}

View File

@@ -136,6 +136,7 @@ struct SWindowRule {
int bFloating = -1;
int bFullscreen = -1;
int bPinned = -1;
std::string szWorkspace = ""; // empty means any
};
class CWindow {
@@ -226,9 +227,10 @@ class CWindow {
bool m_bNoFocus = false;
bool m_bNoInitialFocus = false;
// initial fullscreen and fullscreen disabled
// Fullscreen and Maximize
bool m_bWantsInitialFullscreen = false;
bool m_bNoFullscreenRequest = false;
bool m_bNoMaximizeRequest = false;
SSurfaceTreeNode* m_pSurfaceTree = nullptr;
@@ -326,6 +328,7 @@ class CWindow {
SWindowDecorationExtents getFullWindowReservedArea();
Vector2D middle();
bool opaque();
float rounding();
void onBorderAngleAnimEnd(void* ptr);
bool isInCurvedCorner(double x, double y);

View File

@@ -85,6 +85,7 @@ void CConfigManager::setDefaultVars() {
configValues["misc:disable_hyprland_logo"].intValue = 0;
configValues["misc:disable_splash_rendering"].intValue = 0;
configValues["misc:force_hypr_chan"].intValue = 0;
configValues["misc:vfr"].intValue = 1;
configValues["misc:vrr"].intValue = 0;
configValues["misc:mouse_move_enables_dpms"].intValue = 0;
@@ -99,6 +100,7 @@ void CConfigManager::setDefaultVars() {
configValues["misc:swallow_exception_regex"].strValue = STRVAL_EMPTY;
configValues["misc:focus_on_activate"].intValue = 0;
configValues["misc:no_direct_scanout"].intValue = 1;
configValues["misc:moveintogroup_lock_check"].intValue = 0;
configValues["misc:hide_cursor_on_touch"].intValue = 1;
configValues["misc:mouse_move_focuses_monitor"].intValue = 1;
configValues["misc:suppress_portal_warnings"].intValue = 0;
@@ -107,6 +109,7 @@ void CConfigManager::setDefaultVars() {
configValues["misc:cursor_zoom_factor"].floatValue = 1.f;
configValues["misc:cursor_zoom_rigid"].intValue = 0;
configValues["misc:allow_session_lock_restore"].intValue = 0;
configValues["misc:group_insert_after_current"].intValue = 1;
configValues["misc:render_titles_in_groupbar"].intValue = 1;
configValues["misc:groupbar_titles_font_size"].intValue = 8;
configValues["misc:groupbar_gradients"].intValue = 1;
@@ -123,12 +126,15 @@ void CConfigManager::setDefaultVars() {
configValues["debug:manual_crash"].intValue = 0;
configValues["decoration:rounding"].intValue = 0;
configValues["decoration:blur"].intValue = 1;
configValues["decoration:blur_size"].intValue = 8;
configValues["decoration:blur_passes"].intValue = 1;
configValues["decoration:blur_ignore_opacity"].intValue = 0;
configValues["decoration:blur_new_optimizations"].intValue = 1;
configValues["decoration:blur_xray"].intValue = 0;
configValues["decoration:blur:enabled"].intValue = 1;
configValues["decoration:blur:size"].intValue = 8;
configValues["decoration:blur:passes"].intValue = 1;
configValues["decoration:blur:ignore_opacity"].intValue = 0;
configValues["decoration:blur:new_optimizations"].intValue = 1;
configValues["decoration:blur:xray"].intValue = 0;
configValues["decoration:blur:noise"].floatValue = 0.0117;
configValues["decoration:blur:contrast"].floatValue = 0.8916;
configValues["decoration:blur:brightness"].floatValue = 0.8172;
configValues["decoration:active_opacity"].floatValue = 1;
configValues["decoration:inactive_opacity"].floatValue = 1;
configValues["decoration:fullscreen_opacity"].floatValue = 1;
@@ -158,6 +164,7 @@ void CConfigManager::setDefaultVars() {
configValues["dwindle:use_active_for_splits"].intValue = 1;
configValues["dwindle:default_split_ratio"].floatValue = 1.f;
configValues["dwindle:smart_split"].intValue = 0;
configValues["dwindle:smart_resizing"].intValue = 1;
configValues["master:special_scale_factor"].floatValue = 0.8f;
configValues["master:mfact"].floatValue = 0.55f;
@@ -878,8 +885,8 @@ bool windowRuleValid(const std::string& RULE) {
return !(RULE != "float" && RULE != "tile" && RULE.find("opacity") != 0 && RULE.find("move") != 0 && RULE.find("size") != 0 && RULE.find("minsize") != 0 &&
RULE.find("maxsize") != 0 && RULE.find("pseudo") != 0 && RULE.find("monitor") != 0 && RULE.find("idleinhibit") != 0 && RULE != "nofocus" && RULE != "noblur" &&
RULE != "noshadow" && RULE != "nodim" && RULE != "noborder" && RULE != "center" && RULE != "opaque" && RULE != "forceinput" && RULE != "fullscreen" &&
RULE != "nofullscreenrequest" && RULE != "fakefullscreen" && RULE != "nomaxsize" && RULE != "pin" && RULE != "noanim" && RULE != "dimaround" &&
RULE != "windowdance" && RULE != "maximize" && RULE.find("animation") != 0 && RULE.find("rounding") != 0 && RULE.find("workspace") != 0 &&
RULE != "nofullscreenrequest" && RULE != "nomaximizerequest" && RULE != "fakefullscreen" && RULE != "nomaxsize" && RULE != "pin" && RULE != "noanim" &&
RULE != "dimaround" && RULE != "windowdance" && RULE != "maximize" && RULE.find("animation") != 0 && RULE.find("rounding") != 0 && RULE.find("workspace") != 0 &&
RULE.find("bordercolor") != 0 && RULE != "forcergbx" && RULE != "noinitialfocus" && RULE != "stayfocused" && RULE.find("bordersize") != 0);
}
@@ -960,9 +967,10 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s
const auto FLOATPOS = VALUE.find("floating:");
const auto FULLSCREENPOS = VALUE.find("fullscreen:");
const auto PINNEDPOS = VALUE.find("pinned:");
const auto WORKSPACEPOS = VALUE.find("workspace:");
if (TITLEPOS == std::string::npos && CLASSPOS == std::string::npos && X11POS == std::string::npos && FLOATPOS == std::string::npos && FULLSCREENPOS == std::string::npos &&
PINNEDPOS == std::string::npos) {
PINNEDPOS == std::string::npos && WORKSPACEPOS == std::string::npos) {
Debug::log(ERR, "Invalid rulev2 syntax: %s", VALUE.c_str());
parseError = "Invalid rulev2 syntax: " + VALUE;
return;
@@ -985,6 +993,8 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s
min = FULLSCREENPOS;
if (PINNEDPOS > pos && PINNEDPOS < min)
min = PINNEDPOS;
if (WORKSPACEPOS > pos && WORKSPACEPOS < min)
min = PINNEDPOS;
result = result.substr(0, min - pos);
@@ -996,58 +1006,52 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s
return result;
};
if (CLASSPOS != std::string::npos) {
if (CLASSPOS != std::string::npos)
rule.szClass = extract(CLASSPOS + 6);
}
if (TITLEPOS != std::string::npos) {
if (TITLEPOS != std::string::npos)
rule.szTitle = extract(TITLEPOS + 6);
}
if (X11POS != std::string::npos) {
if (X11POS != std::string::npos)
rule.bX11 = extract(X11POS + 9) == "1" ? 1 : 0;
}
if (FLOATPOS != std::string::npos) {
if (FLOATPOS != std::string::npos)
rule.bFloating = extract(FLOATPOS + 9) == "1" ? 1 : 0;
}
if (FULLSCREENPOS != std::string::npos) {
if (FULLSCREENPOS != std::string::npos)
rule.bFullscreen = extract(FULLSCREENPOS + 11) == "1" ? 1 : 0;
}
if (PINNEDPOS != std::string::npos) {
if (PINNEDPOS != std::string::npos)
rule.bPinned = extract(PINNEDPOS + 7) == "1" ? 1 : 0;
}
if (WORKSPACEPOS != std::string::npos)
rule.szWorkspace = extract(WORKSPACEPOS + 10);
if (RULE == "unset") {
std::erase_if(m_dWindowRules, [&](const SWindowRule& other) {
if (!other.v2) {
return other.szClass == rule.szClass && !rule.szClass.empty();
} else {
if (!rule.szClass.empty() && rule.szClass != other.szClass) {
if (!rule.szClass.empty() && rule.szClass != other.szClass)
return false;
}
if (!rule.szTitle.empty() && rule.szTitle != other.szTitle) {
if (!rule.szTitle.empty() && rule.szTitle != other.szTitle)
return false;
}
if (rule.bX11 != -1 && rule.bX11 != other.bX11) {
if (rule.bX11 != -1 && rule.bX11 != other.bX11)
return false;
}
if (rule.bFloating != -1 && rule.bFloating != other.bFloating) {
if (rule.bFloating != -1 && rule.bFloating != other.bFloating)
return false;
}
if (rule.bFullscreen != -1 && rule.bFullscreen != other.bFullscreen) {
if (rule.bFullscreen != -1 && rule.bFullscreen != other.bFullscreen)
return false;
}
if (rule.bPinned != -1 && rule.bPinned != other.bPinned) {
if (rule.bPinned != -1 && rule.bPinned != other.bPinned)
return false;
if (!rule.szWorkspace.empty() && rule.szWorkspace != other.szWorkspace)
return false;
}
return true;
}
@@ -1604,6 +1608,8 @@ void CConfigManager::loadConfigLoadVars() {
// mark blur dirty
g_pHyprOpenGL->markBlurDirtyForMonitor(m.get());
g_pCompositor->scheduleFrameForMonitor(m.get());
// Force the compositor to fully re-render all monitors
m->forceFullFrames = 2;
}
@@ -1841,8 +1847,29 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(CWindow* pWindow) {
if (pWindow->m_bPinned != rule.bPinned)
continue;
}
} catch (...) {
Debug::log(ERR, "Regex error at %s", rule.szValue.c_str());
if (!rule.szWorkspace.empty()) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
if (!PWORKSPACE)
continue;
if (rule.szWorkspace.find("name:") == 0) {
if (PWORKSPACE->m_szName != rule.szWorkspace.substr(5))
continue;
} else {
// number
if (!isNumber(rule.szWorkspace))
throw std::runtime_error("szWorkspace not name: or number");
const int64_t ID = std::stoll(rule.szWorkspace);
if (PWORKSPACE->m_iID != ID)
continue;
}
}
} catch (std::exception& e) {
Debug::log(ERR, "Regex error at %s (%s)", rule.szValue.c_str(), e.what());
continue;
}
}

View File

@@ -64,10 +64,12 @@ decoration {
# See https://wiki.hyprland.org/Configuring/Variables/ for more
rounding = 10
blur = yes
blur_size = 3
blur_passes = 1
blur_new_optimizations = on
blur {
enabled = true
size = 3
passes = 1
}
drop_shadow = yes
shadow_range = 4

View File

@@ -630,9 +630,12 @@ std::string bindsRequest(HyprCtl::eHyprCtlOutputFormat format) {
std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) {
auto commitMsg = removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE);
std::replace(commitMsg.begin(), commitMsg.end(), '#', ' ');
if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) {
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" +
removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE).c_str() + ").\nTag: " + GIT_TAG + "\n\nflags: (if any)\n";
std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg +
").\nTag: " + GIT_TAG + "\n\nflags: (if any)\n";
#ifdef LEGACY_RENDERER
result += "legacyrenderer\n";
@@ -655,8 +658,9 @@ std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) {
"commit": "%s",
"dirty": %s,
"commit_message": "%s",
"tag": "%s",
"flags": [)#",
GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), removeBeginEndSpacesTabs(GIT_COMMIT_MESSAGE).c_str());
GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg).c_str(), GIT_TAG);
#ifdef LEGACY_RENDERER
result += "\"legacyrenderer\",";
@@ -686,11 +690,10 @@ std::string dispatchRequest(std::string in) {
in = in.substr(in.find_first_of(' ') + 1);
const auto DISPATCHSTR = in.substr(0, in.find_first_of(' '));
auto DISPATCHARG = std::string();
if ((int) in.find_first_of(' ') != -1)
DISPATCHARG = in.substr(in.find_first_of(' ') + 1);
auto DISPATCHARG = std::string();
if ((int)in.find_first_of(' ') != -1)
DISPATCHARG = in.substr(in.find_first_of(' ') + 1);
const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find(DISPATCHSTR);
if (DISPATCHER == g_pKeybindManager->m_mDispatchers.end())
@@ -736,7 +739,7 @@ std::string dispatchKeyword(std::string in) {
}
// decorations will probably need a repaint
if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace") {
if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("cursor_zoom_factor")) {
for (auto& m : g_pCompositor->m_vMonitors) {
g_pHyprRenderer->damageMonitor(m.get());
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
@@ -1312,7 +1315,18 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
char readBuffer[1024];
auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024);
fd_set fdset;
FD_ZERO(&fdset);
FD_SET(ACCEPTEDCONNECTION, &fdset);
timeval timeout = {.tv_sec = 0, .tv_usec = 5000};
auto success = select(ACCEPTEDCONNECTION + 1, &fdset, nullptr, nullptr, &timeout);
if (success <= 0) {
close(ACCEPTEDCONNECTION);
return 0;
}
auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024);
readBuffer[messageSize == 1024 ? 1023 : messageSize] = '\0';
std::string request(readBuffer);

View File

@@ -0,0 +1,35 @@
#pragma once
#ifdef USE_TRACY_GPU
#include "Log.hpp"
#include <GL/gl.h>
#include <GLES2/gl2ext.h>
inline PFNGLQUERYCOUNTEREXTPROC glQueryCounter;
inline PFNGLGETQUERYOBJECTIVEXTPROC glGetQueryObjectiv;
inline PFNGLGETQUERYOBJECTUI64VEXTPROC glGetQueryObjectui64v;
#include "../../subprojects/tracy/public/tracy/TracyOpenGL.hpp"
inline void loadGLProc(void* pProc, const char* name) {
void* proc = (void*)eglGetProcAddress(name);
if (proc == NULL) {
Debug::log(CRIT, "[Tracy GPU Profiling] eglGetProcAddress(%s) failed", name);
abort();
}
*(void**)pProc = proc;
}
#define TRACY_GPU_CONTEXT TracyGpuContext
#define TRACY_GPU_ZONE(e) TracyGpuZone(e)
#define TRACY_GPU_COLLECT TracyGpuCollect
#else
#define TRACY_GPU_CONTEXT
#define TRACY_GPU_ZONE(e)
#define TRACY_GPU_COLLECT
#endif

View File

@@ -27,13 +27,6 @@
#define DELTALESSTHAN(a, b, delta) (abs((a) - (b)) < (delta))
#define PIXMAN_DAMAGE_FOREACH(region) \
int rectsNum = 0; \
const auto RECTSARR = pixman_region32_rectangles(region, &rectsNum); \
for (int i = 0; i < rectsNum; ++i)
#define PIXMAN_REGION_FOREACH(region) PIXMAN_DAMAGE_FOREACH(region)
#define interface class
#define STICKS(a, b) abs((a) - (b)) < 2

View File

@@ -170,4 +170,7 @@ namespace Events {
// Gamma control
LISTENER(setGamma);
// Cursor shape
LISTENER(setCursorShape);
};

View File

@@ -231,3 +231,9 @@ void Events::listener_setGamma(wl_listener* listener, void* data) {
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
}
void Events::listener_setCursorShape(wl_listener* listener, void* data) {
const auto E = (wlr_cursor_shape_manager_v1_request_set_shape_event*)data;
g_pInputManager->processMouseRequest(E);
}

View File

@@ -217,8 +217,10 @@ void Events::listener_monitorCommit(void* owner, void* data) {
const auto E = (wlr_output_event_commit*)data;
if (E->committed & WLR_OUTPUT_STATE_BUFFER)
if (E->committed & WLR_OUTPUT_STATE_BUFFER) {
g_pProtocolManager->m_pScreencopyProtocolManager->onOutputCommit(PMONITOR, E);
g_pProtocolManager->m_pToplevelExportProtocolManager->onOutputCommit(PMONITOR, E);
}
}
void Events::listener_monitorBind(void* owner, void* data) {

View File

@@ -109,6 +109,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
(PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xwayland->fullscreen);
bool requestsFakeFullscreen = false;
bool requestsMaximize = false;
bool overridingNoFullscreen = false;
bool overridingNoMaximize = false;
bool shouldFocus = true;
bool workspaceSpecial = false;
@@ -176,8 +178,11 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_bNoInitialFocus = true;
} else if (r.szRule.find("nofullscreenrequest") == 0) {
PWINDOW->m_bNoFullscreenRequest = true;
} else if (r.szRule.find("nomaximizerequest") == 0) {
PWINDOW->m_bNoMaximizeRequest = true;
} else if (r.szRule == "fullscreen") {
requestsFullscreen = true;
requestsFullscreen = true;
overridingNoFullscreen = true;
} else if (r.szRule == "fakefullscreen") {
requestsFakeFullscreen = true;
} else if (r.szRule == "windowdance") {
@@ -189,7 +194,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
} else if (r.szRule == "pin") {
PWINDOW->m_bPinned = true;
} else if (r.szRule == "maximize") {
requestsMaximize = true;
requestsMaximize = true;
overridingNoMaximize = true;
} else if (r.szRule == "stayfocused") {
PWINDOW->m_bStayFocused = true;
} else if (r.szRule.find("idleinhibit") == 0) {
@@ -485,7 +491,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_vRealPosition.setCallbackOnEnd(setAnimToMove);
PWINDOW->m_vRealSize.setCallbackOnEnd(setAnimToMove);
if ((requestsFullscreen || requestsMaximize || requestsFakeFullscreen) && !PWINDOW->m_bNoFullscreenRequest) {
if ((requestsFullscreen && (!PWINDOW->m_bNoFullscreenRequest || overridingNoFullscreen)) || (requestsMaximize && (!PWINDOW->m_bNoMaximizeRequest || overridingNoMaximize)) ||
requestsFakeFullscreen) {
// fix fullscreen on requested (basically do a switcheroo)
if (PWORKSPACE->m_bHasFullscreenWindow) {
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
@@ -496,6 +503,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_bFakeFullscreenState = !PWINDOW->m_bFakeFullscreenState;
g_pXWaylandManager->setWindowFullscreen(PWINDOW, true);
} else {
overridingNoFullscreen = false;
overridingNoMaximize = false;
PWINDOW->m_vRealPosition.warp();
PWINDOW->m_vRealSize.warp();
g_pCompositor->setWindowFullscreen(PWINDOW, true, requestsFullscreen ? FULLSCREEN_FULL : FULLSCREEN_MAXIMIZED);
@@ -1125,7 +1134,7 @@ void Events::listener_NewXDGDeco(wl_listener* listener, void* data) {
void Events::listener_requestMaximize(void* owner, void* data) {
const auto PWINDOW = (CWindow*)owner;
if (PWINDOW->m_bNoFullscreenRequest)
if (PWINDOW->m_bNoMaximizeRequest)
return;
Debug::log(LOG, "Maximize request for %lx", PWINDOW);

View File

@@ -51,13 +51,14 @@ CAnimatedVariable::~CAnimatedVariable() {
}
void CAnimatedVariable::unregister() {
g_pAnimationManager->m_lAnimatedVariables.remove(this);
std::erase_if(g_pAnimationManager->m_vAnimatedVariables, [&](const auto& other) { return other == this; });
m_bIsRegistered = false;
disconnectFromActive();
}
void CAnimatedVariable::registerVar() {
if (!m_bIsRegistered)
g_pAnimationManager->m_lAnimatedVariables.push_back(this);
g_pAnimationManager->m_vAnimatedVariables.push_back(this);
m_bIsRegistered = true;
}
@@ -78,4 +79,15 @@ float CAnimatedVariable::getCurveValue() {
return 1.f;
return g_pAnimationManager->getBezier(m_pConfig->pValues->internalBezier)->getYForPoint(SPENT);
}
void CAnimatedVariable::connectToActive() {
if (!m_bIsConnectedToActive)
g_pAnimationManager->m_vActiveAnimatedVariables.push_back(this);
m_bIsConnectedToActive = true;
}
void CAnimatedVariable::disconnectFromActive() {
std::erase_if(g_pAnimationManager->m_vActiveAnimatedVariables, [&](const auto& other) { return other == this; });
m_bIsConnectedToActive = false;
}

View File

@@ -148,17 +148,8 @@ class CAnimatedVariable {
}
// checks if an animation is in progress
bool isBeingAnimated() {
switch (m_eVarType) {
case AVARTYPE_FLOAT: return m_fValue != m_fGoal;
case AVARTYPE_VECTOR: return m_vValue != m_vGoal;
case AVARTYPE_COLOR: return m_cValue != m_cGoal;
default: UNREACHABLE();
}
UNREACHABLE();
return false; // just so that the warning is suppressed
inline bool isBeingAnimated() {
return m_bIsBeingAnimated;
}
void warp(bool endCallback = true) {
@@ -178,6 +169,8 @@ class CAnimatedVariable {
default: UNREACHABLE();
}
m_bIsBeingAnimated = false;
if (endCallback)
onAnimationEnd();
}
@@ -251,8 +244,9 @@ class CAnimatedVariable {
SAnimationPropertyConfig* m_pConfig = nullptr;
bool m_bDummy = true;
bool m_bIsRegistered = false;
bool m_bDummy = true;
bool m_bIsRegistered = false;
bool m_bIsBeingAnimated = false;
std::chrono::system_clock::time_point animationBegin;
@@ -265,8 +259,15 @@ class CAnimatedVariable {
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;
@@ -277,6 +278,9 @@ class CAnimatedVariable {
}
void onAnimationBegin() {
m_bIsBeingAnimated = true;
connectToActive();
if (m_fBeginCallback) {
m_fBeginCallback(this);
if (m_bRemoveBeginAfterRan)

View File

@@ -10,12 +10,10 @@ int ratHandler(void* data) {
CMonitor::CMonitor() {
wlr_damage_ring_init(&damage);
pixman_region32_init(&lastFrameDamage);
}
CMonitor::~CMonitor() {
wlr_damage_ring_finish(&damage);
pixman_region32_fini(&lastFrameDamage);
hyprListener_monitorDestroy.removeCallback();
hyprListener_monitorFrame.removeCallback();
@@ -331,6 +329,10 @@ void CMonitor::addDamage(const pixman_region32_t* rg) {
g_pCompositor->scheduleFrameForMonitor(this);
}
void CMonitor::addDamage(const CRegion* rg) {
addDamage(const_cast<CRegion*>(rg)->pixman());
}
void CMonitor::addDamage(const wlr_box* box) {
static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue;
if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {

View File

@@ -8,6 +8,7 @@
#include <memory>
#include <xf86drmMode.h>
#include "Timer.hpp"
#include "Region.hpp"
struct SMonitorRule;
@@ -61,7 +62,7 @@ class CMonitor {
CMonitor* pMirrorOf = nullptr;
std::vector<CMonitor*> mirrors;
pixman_region32_t lastFrameDamage; // stores last frame damage
CRegion lastFrameDamage; // stores last frame damage
// for the special workspace. 0 means not open.
int specialWorkspaceID = 0;
@@ -84,6 +85,7 @@ class CMonitor {
void onConnect(bool noRule);
void onDisconnect();
void addDamage(const pixman_region32_t* rg);
void addDamage(const CRegion* rg);
void addDamage(const wlr_box* box);
void setMirror(const std::string&);
bool isMirror();

97
src/helpers/Region.cpp Normal file
View File

@@ -0,0 +1,97 @@
#include "Region.hpp"
#include <wlr/util/box.h>
CRegion::CRegion() {
pixman_region32_init(&m_rRegion);
}
CRegion::CRegion(pixman_region32_t* ref) {
pixman_region32_init(&m_rRegion);
pixman_region32_copy(&m_rRegion, ref);
}
CRegion::CRegion(double x, double y, double w, double h) {
pixman_region32_init_rect(&m_rRegion, x, y, w, h);
}
CRegion::CRegion(wlr_box* box) {
pixman_region32_init_rect(&m_rRegion, box->x, box->y, box->width, box->height);
}
CRegion::CRegion(pixman_box32_t* box) {
pixman_region32_init_rect(&m_rRegion, box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1);
}
CRegion::CRegion(const CRegion& other) {
pixman_region32_init(&m_rRegion);
pixman_region32_copy(&m_rRegion, const_cast<CRegion*>(&other)->pixman());
}
CRegion::CRegion(CRegion&& other) {
pixman_region32_init(&m_rRegion);
pixman_region32_copy(&m_rRegion, other.pixman());
}
CRegion::~CRegion() {
pixman_region32_fini(&m_rRegion);
}
CRegion& CRegion::clear() {
pixman_region32_clear(&m_rRegion);
return *this;
}
CRegion& CRegion::set(const CRegion& other) {
pixman_region32_copy(&m_rRegion, const_cast<CRegion*>(&other)->pixman());
return *this;
}
CRegion& CRegion::add(const CRegion& other) {
pixman_region32_union(&m_rRegion, &m_rRegion, const_cast<CRegion*>(&other)->pixman());
return *this;
}
CRegion& CRegion::add(double x, double y, double w, double h) {
pixman_region32_union_rect(&m_rRegion, &m_rRegion, x, y, w, h);
return *this;
}
CRegion& CRegion::subtract(const CRegion& other) {
pixman_region32_subtract(&m_rRegion, &m_rRegion, const_cast<CRegion*>(&other)->pixman());
return *this;
}
CRegion& CRegion::intersect(const CRegion& other) {
pixman_region32_intersect(&m_rRegion, &m_rRegion, const_cast<CRegion*>(&other)->pixman());
return *this;
}
CRegion& CRegion::intersect(double x, double y, double w, double h) {
pixman_region32_intersect_rect(&m_rRegion, &m_rRegion, x, y, w, h);
return *this;
}
CRegion& CRegion::invert(pixman_box32_t* box) {
pixman_region32_inverse(&m_rRegion, &m_rRegion, box);
return *this;
}
CRegion& CRegion::translate(const Vector2D& vec) {
pixman_region32_translate(&m_rRegion, vec.x, vec.y);
return *this;
}
std::vector<pixman_box32_t> CRegion::getRects() const {
std::vector<pixman_box32_t> result;
int rectsNum = 0;
const auto RECTSARR = pixman_region32_rectangles(&m_rRegion, &rectsNum);
result.assign(RECTSARR, RECTSARR + rectsNum);
return result;
}
bool CRegion::empty() {
return !pixman_region32_not_empty(&m_rRegion);
}

55
src/helpers/Region.hpp Normal file
View File

@@ -0,0 +1,55 @@
#pragma once
#include <pixman.h>
#include <vector>
#include "Vector2D.hpp"
struct wlr_box;
class CRegion {
public:
/* Create an empty region */
CRegion();
/* Create from a reference. Copies, does not own. */
CRegion(pixman_region32_t* ref);
/* Create from a box */
CRegion(double x, double y, double w, double h);
/* Create from a wlr_box */
CRegion(wlr_box* box);
/* Create from a pixman_box32_t */
CRegion(pixman_box32_t* box);
CRegion(const CRegion&);
CRegion(CRegion&&);
~CRegion();
CRegion& operator=(CRegion&& other) {
pixman_region32_copy(&m_rRegion, other.pixman());
return *this;
}
CRegion& operator=(CRegion& other) {
pixman_region32_copy(&m_rRegion, other.pixman());
return *this;
}
CRegion& clear();
CRegion& set(const CRegion& other);
CRegion& add(const CRegion& other);
CRegion& add(double x, double y, double w, double h);
CRegion& subtract(const CRegion& other);
CRegion& intersect(const CRegion& other);
CRegion& intersect(double x, double y, double w, double h);
CRegion& translate(const Vector2D& vec);
CRegion& invert(pixman_box32_t* box);
bool empty();
std::vector<pixman_box32_t> getRects() const;
pixman_region32_t* pixman() {
return &m_rRegion;
}
private:
pixman_region32_t m_rRegion;
};

View File

@@ -7,6 +7,7 @@
#include "SubsurfaceTree.hpp"
#include "AnimatedVariable.hpp"
#include "WLSurface.hpp"
#include "Region.hpp"
struct SLayerRule {
std::string targetNamespace = "";
@@ -144,7 +145,7 @@ struct SMouse {
wlr_pointer_constraint_v1* currentConstraint = nullptr;
bool constraintActive = false;
pixman_region32_t confinedTo;
CRegion confinedTo;
std::string name = "";

View File

@@ -28,7 +28,8 @@ typedef struct {
} xcb_size_hints_t;
typedef unsigned int xcb_window_t;
typedef enum xcb_stack_mode_t {
typedef enum xcb_stack_mode_t
{
XCB_STACK_MODE_ABOVE = 0,
XCB_STACK_MODE_BELOW = 1,
XCB_STACK_MODE_TOP_IF = 2,

View File

@@ -104,6 +104,7 @@ extern "C" {
#include <wlr/types/wlr_session_lock_v1.h>
#include <wlr/types/wlr_single_pixel_buffer_v1.h>
#include <wlr/types/wlr_idle_notify_v1.h>
#include <wlr/types/wlr_cursor_shape_v1.h>
#include <libdrm/drm_fourcc.h>

View File

@@ -3,3 +3,27 @@
bool Init::isSudo() {
return getuid() != geteuid() || !geteuid();
}
void Init::gainRealTime() {
const int minPrio = sched_get_priority_min(SCHED_RR);
int old_policy;
struct sched_param param;
if (pthread_getschedparam(pthread_self(), &old_policy, &param)) {
Debug::log(WARN, "Failed to get old pthread scheduling priority");
return;
}
param.sched_priority = minPrio;
if (pthread_setschedparam(pthread_self(), SCHED_RR, &param)) {
Debug::log(WARN, "Failed to change process scheduling strategy");
return;
}
pthread_atfork(NULL, NULL, []() {
const struct sched_param param = {.sched_priority = 0};
if (pthread_setschedparam(pthread_self(), SCHED_OTHER, &param))
Debug::log(WARN, "Failed to reset process scheduling strategy");
});
}

View File

@@ -4,4 +4,5 @@
namespace Init {
bool isSudo();
void gainRealTime();
};

View File

@@ -127,9 +127,12 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT);
auto borderSize =
PWINDOW->m_sSpecialRenderData.borderSize.toUnderlying() != -1 ? PWINDOW->m_sSpecialRenderData.borderSize.toUnderlying() : WORKSPACERULE.borderSize.value_or(*PBORDERSIZE);
if (PWINDOW->m_sAdditionalConfigData.borderSize.toUnderlying() != -1)
borderSize = PWINDOW->m_sAdditionalConfigData.borderSize.toUnderlying();
borderSize *= PWINDOW->m_sSpecialRenderData.border && !PWINDOW->m_sAdditionalConfigData.forceNoBorder;
if (!g_pCompositor->windowExists(PWINDOW) || !PWINDOW->m_bIsMapped) {
Debug::log(ERR, "Node %lx holding invalid window %lx!!", pNode, PWINDOW);
onWindowRemovedTiling(PWINDOW);
@@ -141,21 +144,23 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
static auto* const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("dwindle:no_gaps_when_only")->intValue;
auto calcPos = PWINDOW->m_vPosition + Vector2D(borderSize, borderSize);
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * borderSize, 2 * borderSize);
const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->m_iWorkspaceID);
if (*PNOGAPSWHENONLY && !WORKSPACERULE.border && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) &&
if (*PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) &&
(NODESONWORKSPACE == 1 || (PWINDOW->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) {
PWINDOW->m_vRealPosition = calcPos - Vector2D(borderSize, borderSize);
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * borderSize, 2 * borderSize);
PWINDOW->updateWindowDecos();
PWINDOW->m_sSpecialRenderData.rounding = false;
PWINDOW->m_sSpecialRenderData.border = false;
PWINDOW->m_sSpecialRenderData.decorate = false;
PWINDOW->m_sSpecialRenderData.decorate = WORKSPACERULE.decorate.value_or(true);
PWINDOW->m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(*PNOGAPSWHENONLY == 2);
const auto RESERVED = PWINDOW->getFullWindowReservedArea();
borderSize *= PWINDOW->m_sSpecialRenderData.border;
PWINDOW->m_vRealPosition = PWINDOW->m_vPosition + Vector2D(borderSize, borderSize) + RESERVED.topLeft;
PWINDOW->m_vRealSize = PWINDOW->m_vSize - Vector2D(2 * borderSize, 2 * borderSize) - (RESERVED.topLeft + RESERVED.bottomRight);
PWINDOW->updateWindowDecos();
return;
}
@@ -165,6 +170,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
PWINDOW->m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(true);
PWINDOW->m_sSpecialRenderData.borderSize = WORKSPACERULE.borderSize.value_or(-1);
auto calcPos = PWINDOW->m_vPosition + Vector2D(borderSize, borderSize);
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * borderSize, 2 * borderSize);
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut : gapsIn, DISPLAYTOP ? gapsOut : gapsIn);
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? gapsOut : gapsIn, DISPLAYBOTTOM ? gapsOut : gapsIn);
@@ -603,7 +611,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
return;
}
const auto PANIMATE = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
const auto PANIMATE = &g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes")->intValue;
const auto PSMARTRESIZING = &g_pConfigManager->getConfigValuePtr("dwindle:smart_resizing")->intValue;
// get some data about our window
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
@@ -658,63 +667,121 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
if (DISPLAYBOTTOM && DISPLAYTOP)
allowedMovement.y = 0;
// Identify inner and outer nodes for both directions.
if (*PSMARTRESIZING == 1) {
// Identify inner and outer nodes for both directions
SDwindleNodeData* PVOUTER = nullptr;
SDwindleNodeData* PVINNER = nullptr;
SDwindleNodeData* PHOUTER = nullptr;
SDwindleNodeData* PHINNER = nullptr;
SDwindleNodeData* PVOUTER = nullptr;
SDwindleNodeData* PVINNER = nullptr;
SDwindleNodeData* PHOUTER = nullptr;
SDwindleNodeData* PHINNER = nullptr;
const auto LEFT = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT;
const auto TOP = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT;
const auto RIGHT = corner == CORNER_TOPRIGHT || corner == CORNER_BOTTOMRIGHT;
const auto BOTTOM = corner == CORNER_BOTTOMLEFT || corner == CORNER_BOTTOMRIGHT;
const auto NONE = corner == CORNER_NONE;
const auto LEFT = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT;
const auto TOP = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT;
const auto RIGHT = corner == CORNER_TOPRIGHT || corner == CORNER_BOTTOMRIGHT;
const auto BOTTOM = corner == CORNER_BOTTOMLEFT || corner == CORNER_BOTTOMRIGHT;
const auto NONE = corner == CORNER_NONE;
for (auto PCURRENT = PNODE; PCURRENT && PCURRENT->pParent; PCURRENT = PCURRENT->pParent) {
const auto PPARENT = PCURRENT->pParent;
for (auto PCURRENT = PNODE; PCURRENT && PCURRENT->pParent; PCURRENT = PCURRENT->pParent) {
const auto PPARENT = PCURRENT->pParent;
if (!PVOUTER && PPARENT->splitTop && (NONE || (TOP && PPARENT->children[1] == PCURRENT) || (BOTTOM && PPARENT->children[0] == PCURRENT)))
PVOUTER = PCURRENT;
else if (!PVOUTER && !PVINNER && PPARENT->splitTop)
PVINNER = PCURRENT;
else if (!PHOUTER && !PPARENT->splitTop && (NONE || (LEFT && PPARENT->children[1] == PCURRENT) || (RIGHT && PPARENT->children[0] == PCURRENT)))
PHOUTER = PCURRENT;
else if (!PHOUTER && !PHINNER && !PPARENT->splitTop)
PHINNER = PCURRENT;
if (!PVOUTER && PPARENT->splitTop && (NONE || (TOP && PPARENT->children[1] == PCURRENT) || (BOTTOM && PPARENT->children[0] == PCURRENT)))
PVOUTER = PCURRENT;
else if (!PVOUTER && !PVINNER && PPARENT->splitTop)
PVINNER = PCURRENT;
else if (!PHOUTER && !PPARENT->splitTop && (NONE || (LEFT && PPARENT->children[1] == PCURRENT) || (RIGHT && PPARENT->children[0] == PCURRENT)))
PHOUTER = PCURRENT;
else if (!PHOUTER && !PHINNER && !PPARENT->splitTop)
PHINNER = PCURRENT;
if (PVOUTER && PHOUTER)
break;
}
if (PVOUTER && PHOUTER)
break;
}
if (PHOUTER) {
PHOUTER->pParent->splitRatio = std::clamp(PHOUTER->pParent->splitRatio + allowedMovement.x * 2.f / PHOUTER->pParent->size.x, 0.1, 1.9);
if (PHOUTER) {
PHOUTER->pParent->splitRatio = std::clamp(PHOUTER->pParent->splitRatio + allowedMovement.x * 2.f / PHOUTER->pParent->size.x, 0.1, 1.9);
if (PHINNER) {
const auto ORIGINAL = PHINNER->size.x;
PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
if (PHINNER->pParent->children[0] == PHINNER)
PHINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.x) / PHINNER->pParent->size.x * 2.f, 0.1, 1.9);
else
PHINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.x) / PHINNER->pParent->size.x * 2.f, 0.1, 1.9);
PHINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
} else
PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
}
if (PHINNER) {
const auto ORIGINAL = PHINNER->size.x;
PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
if (PHINNER->pParent->children[0] == PHINNER)
PHINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.x) / PHINNER->pParent->size.x * 2.f, 0.1, 1.9);
else
PHINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.x) / PHINNER->pParent->size.x * 2.f, 0.1, 1.9);
PHINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
} else
PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
}
if (PVOUTER) {
PVOUTER->pParent->splitRatio = std::clamp(PVOUTER->pParent->splitRatio + allowedMovement.y * 2.f / PVOUTER->pParent->size.y, 0.1, 1.9);
if (PVOUTER) {
PVOUTER->pParent->splitRatio = std::clamp(PVOUTER->pParent->splitRatio + allowedMovement.y * 2.f / PVOUTER->pParent->size.y, 0.1, 1.9);
if (PVINNER) {
const auto ORIGINAL = PVINNER->size.y;
PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
if (PVINNER->pParent->children[0] == PVINNER)
PVINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.y) / PVINNER->pParent->size.y * 2.f, 0.1, 1.9);
else
PVINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.y) / PVINNER->pParent->size.y * 2.f, 0.1, 1.9);
PVINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
} else
PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
}
} else {
// get the correct containers to apply splitratio to
const auto PPARENT = PNODE->pParent;
if (PVINNER) {
const auto ORIGINAL = PVINNER->size.y;
PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
if (PVINNER->pParent->children[0] == PVINNER)
PVINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.y) / PVINNER->pParent->size.y * 2.f, 0.1, 1.9);
else
PVINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.y) / PVINNER->pParent->size.y * 2.f, 0.1, 1.9);
PVINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
} else
PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
if (!PPARENT)
return; // the only window on a workspace, ignore
const bool PARENTSIDEBYSIDE = !PPARENT->splitTop;
// Get the parent's parent
auto PPARENT2 = PPARENT->pParent;
// No parent means we have only 2 windows, and thus one axis of freedom
if (!PPARENT2) {
if (PARENTSIDEBYSIDE) {
allowedMovement.x *= 2.f / PPARENT->size.x;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
} else {
allowedMovement.y *= 2.f / PPARENT->size.y;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
}
return;
}
// Get first parent with other split
while (PPARENT2 && PPARENT2->splitTop == !PARENTSIDEBYSIDE)
PPARENT2 = PPARENT2->pParent;
// no parent, one axis of freedom
if (!PPARENT2) {
if (PARENTSIDEBYSIDE) {
allowedMovement.x *= 2.f / PPARENT->size.x;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
} else {
allowedMovement.y *= 2.f / PPARENT->size.y;
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
}
return;
}
// 2 axes of freedom
const auto SIDECONTAINER = PARENTSIDEBYSIDE ? PPARENT : PPARENT2;
const auto TOPCONTAINER = PARENTSIDEBYSIDE ? PPARENT2 : PPARENT;
allowedMovement.x *= 2.f / SIDECONTAINER->size.x;
allowedMovement.y *= 2.f / TOPCONTAINER->size.y;
SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, 0.1, 1.9);
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, 0.1, 1.9);
SIDECONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
TOPCONTAINER->recalcSizePosRecursive(*PANIMATE == 0);
}
}

View File

@@ -159,8 +159,8 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
}
if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->m_uSurface.xwayland->override_redirect)) {
pWindow->m_vRealPosition.setValue(pWindow->m_vRealPosition.goalv());
pWindow->m_vRealSize.setValue(pWindow->m_vRealSize.goalv());
pWindow->m_vRealPosition.warp();
pWindow->m_vRealSize.warp();
}
if (pWindow->m_iX11Type != 2) {
@@ -519,4 +519,13 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) {
return PWINDOWCANDIDATE;
}
void IHyprLayout::requestFocusForWindow(CWindow* pWindow) {
if (pWindow->isHidden() && pWindow->m_sGroupData.pNextWindow) {
// grouped, change the current to this window
pWindow->setGroupCurrent(pWindow);
}
g_pCompositor->focusWindow(pWindow);
}
IHyprLayout::~IHyprLayout() {}

View File

@@ -148,6 +148,13 @@ interface IHyprLayout {
*/
virtual void replaceWindowDataWith(CWindow* from, CWindow* to) = 0;
/*
Called via the foreign toplevel activation protocol.
Focuses a window, bringing it to the top of its group if applicable.
May be ignored.
*/
virtual void requestFocusForWindow(CWindow*);
private:
Vector2D m_vBeginDragXY;
Vector2D m_vLastDragXY;

View File

@@ -294,7 +294,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) {
if ((WINDOWS < 2) && !centerMasterWindow) {
PMASTERNODE->position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition;
PMASTERNODE->size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x,
PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y);
PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y);
applyNodeDataToWindow(PMASTERNODE);
return;
} else if (orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT || (orientation == ORIENTATION_CENTER && STACKWINDOWS <= 1)) {
@@ -518,6 +518,8 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
if (PWINDOW->m_sAdditionalConfigData.borderSize.toUnderlying() != -1)
borderSize = PWINDOW->m_sAdditionalConfigData.borderSize.toUnderlying();
borderSize *= PWINDOW->m_sSpecialRenderData.border && !PWINDOW->m_sAdditionalConfigData.forceNoBorder;
if (!g_pCompositor->windowValidMapped(PWINDOW)) {
Debug::log(ERR, "Node %lx holding invalid window %lx!!", pNode, PWINDOW);
return;
@@ -528,20 +530,22 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
PWINDOW->m_vSize = pNode->size;
PWINDOW->m_vPosition = pNode->position;
auto calcPos = PWINDOW->m_vPosition + Vector2D(borderSize, borderSize);
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * borderSize, 2 * borderSize);
if (*PNOGAPSWHENONLY && !WORKSPACERULE.border && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) &&
if (*PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) &&
(getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1 ||
(PWINDOW->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) {
PWINDOW->m_vRealPosition = calcPos - Vector2D(borderSize, borderSize);
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * borderSize, 2 * borderSize);
PWINDOW->updateWindowDecos();
PWINDOW->m_sSpecialRenderData.rounding = false;
PWINDOW->m_sSpecialRenderData.border = false;
PWINDOW->m_sSpecialRenderData.decorate = false;
PWINDOW->m_sSpecialRenderData.decorate = WORKSPACERULE.decorate.value_or(true);
PWINDOW->m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(*PNOGAPSWHENONLY == 2);
const auto RESERVED = PWINDOW->getFullWindowReservedArea();
borderSize *= PWINDOW->m_sSpecialRenderData.border;
PWINDOW->m_vRealPosition = PWINDOW->m_vPosition + Vector2D(borderSize, borderSize) + RESERVED.topLeft;
PWINDOW->m_vRealSize = PWINDOW->m_vSize - Vector2D(2 * borderSize, 2 * borderSize) - (RESERVED.topLeft + RESERVED.bottomRight);
PWINDOW->updateWindowDecos();
return;
}
@@ -551,6 +555,9 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
PWINDOW->m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(true);
PWINDOW->m_sSpecialRenderData.borderSize = WORKSPACERULE.borderSize.value_or(-1);
auto calcPos = PWINDOW->m_vPosition + Vector2D(borderSize, borderSize);
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * borderSize, 2 * borderSize);
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut : gapsIn, DISPLAYTOP ? gapsOut : gapsIn);
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? gapsOut : gapsIn, DISPLAYBOTTOM ? gapsOut : gapsIn);

View File

@@ -97,6 +97,8 @@ int main(int argc, char** argv) {
g_pCompositor->initServer();
Init::gainRealTime();
Debug::log(LOG, "Hyprland init finished.");
// If all's good to go, start.

View File

@@ -8,7 +8,8 @@ int wlTick(void* data) {
wl_event_source_timer_update(g_pAnimationManager->m_pAnimationTick, 1000 / refreshRate);
if (g_pCompositor->m_bSessionActive && std::ranges::any_of(g_pCompositor->m_vMonitors, [](const auto& mon) { return mon->m_bEnabled && mon->output; })) {
if (g_pCompositor->m_bSessionActive && g_pAnimationManager && g_pHookSystem &&
std::ranges::any_of(g_pCompositor->m_vMonitors, [](const auto& mon) { return mon->m_bEnabled && mon->output; })) {
g_pAnimationManager->tick();
EMIT_HOOK_EVENT("tick", nullptr);
}
@@ -57,11 +58,7 @@ void CAnimationManager::tick() {
std::vector<CAnimatedVariable*> animationEndedVars;
for (auto& av : m_lAnimatedVariables) {
// first of all, check if we need to update it at all
if (!av->isBeingAnimated())
continue;
for (auto& av : m_vActiveAnimatedVariables) {
if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW && !*PSHADOWSENABLED) {
av->warp(false);
@@ -254,15 +251,12 @@ void CAnimationManager::tick() {
// easy, damage the entire box
g_pHyprRenderer->damageBox(&dmg);
} else {
pixman_region32_t rg;
pixman_region32_init_rect(&rg, dmg.x, dmg.y, dmg.width, dmg.height);
pixman_region32_t wb;
pixman_region32_init_rect(&wb, PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x,
PWINDOW->m_vRealSize.vec().y);
pixman_region32_subtract(&rg, &rg, &wb);
g_pHyprRenderer->damageRegion(&rg);
pixman_region32_fini(&rg);
pixman_region32_fini(&wb);
CRegion rg{dmg.x, dmg.y, dmg.width, dmg.height};
CRegion wb{PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealSize.vec().y};
rg.subtract(wb);
g_pHyprRenderer->damageRegion(rg);
}
}

View File

@@ -25,7 +25,8 @@ class CAnimationManager {
std::unordered_map<std::string, CBezierCurve> getAllBeziers();
std::list<CAnimatedVariable*> m_lAnimatedVariables;
std::vector<CAnimatedVariable*> m_vAnimatedVariables;
std::vector<CAnimatedVariable*> m_vActiveAnimatedVariables;
wl_event_source* m_pAnimationTick;

View File

@@ -1013,11 +1013,9 @@ void CKeybindManager::moveFocusTo(std::string args) {
}
};
const auto PWINDOWTOCHANGETO = PLASTWINDOW->m_bIsFullscreen
? (arg == 'd' || arg == 'b' || arg == 'r'
? g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true)
: g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW, true))
: g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
const auto PWINDOWTOCHANGETO = PLASTWINDOW->m_bIsFullscreen ?
(arg == 'd' || arg == 'b' || arg == 'r' ? g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true) : g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW, true)) :
g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
// Found window in direction, switch to it
if (PWINDOWTOCHANGETO) {
@@ -1839,6 +1837,9 @@ void CKeybindManager::dpms(std::string arg) {
bool enable = arg.find("on") == 0;
std::string port = "";
if (arg.find("toggle") == 0)
enable = !std::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](const auto& other) { return !other->dpmsStatus; }); // enable if any is off
if (arg.find_first_of(' ') != std::string::npos)
port = arg.substr(arg.find_first_of(' ') + 1);
@@ -2020,7 +2021,9 @@ void CKeybindManager::lockActiveGroup(std::string args) {
}
void CKeybindManager::moveIntoGroup(std::string args) {
char arg = args[0];
char arg = args[0];
static auto* const GROUPLOCKCHECK = &g_pConfigManager->getConfigValuePtr("misc:moveintogroup_lock_check")->intValue;
if (!isDirection(args)) {
Debug::log(ERR, "Cannot move into group in direction %c, unsupported direction. Supported: l,r,u/t,d/b", arg);
@@ -2037,14 +2040,14 @@ void CKeybindManager::moveIntoGroup(std::string args) {
if (!PWINDOWINDIR || !PWINDOWINDIR->m_sGroupData.pNextWindow)
return;
if (*GROUPLOCKCHECK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || (PWINDOW->m_sGroupData.pNextWindow && PWINDOW->m_sGroupData.locked)))
return;
if (!PWINDOW->m_sGroupData.pNextWindow)
PWINDOW->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(PWINDOW));
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW); // This removes groupped property!
PWINDOW->m_sGroupData.locked = false;
PWINDOW->m_sGroupData.head = false;
PWINDOWINDIR->insertWindowToGroup(PWINDOW);
PWINDOWINDIR->setGroupCurrent(PWINDOW);
PWINDOW->updateWindowDecos();
@@ -2088,6 +2091,11 @@ void CKeybindManager::moveGroupWindow(std::string args) {
if (!g_pCompositor->m_pLastWindow || !g_pCompositor->m_pLastWindow->m_sGroupData.pNextWindow)
return;
g_pCompositor->m_pLastWindow->switchWithWindowInGroup(BACK ? g_pCompositor->m_pLastWindow->getGroupPrevious() : g_pCompositor->m_pLastWindow->m_sGroupData.pNextWindow);
if ((!BACK && g_pCompositor->m_pLastWindow->m_sGroupData.pNextWindow->m_sGroupData.head) || (BACK && g_pCompositor->m_pLastWindow->m_sGroupData.head)) {
std::swap(g_pCompositor->m_pLastWindow->m_sGroupData.head, g_pCompositor->m_pLastWindow->m_sGroupData.pNextWindow->m_sGroupData.head);
std::swap(g_pCompositor->m_pLastWindow->m_sGroupData.locked, g_pCompositor->m_pLastWindow->m_sGroupData.pNextWindow->m_sGroupData.locked);
} else
g_pCompositor->m_pLastWindow->switchWithWindowInGroup(BACK ? g_pCompositor->m_pLastWindow->getGroupPrevious() : g_pCompositor->m_pLastWindow->m_sGroupData.pNextWindow);
g_pCompositor->m_pLastWindow->updateWindowDecos();
}

View File

@@ -464,23 +464,14 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
}
void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_event* e) {
if (!g_pHyprRenderer->shouldRenderCursor())
return;
if (!e->surface) {
if (!e->surface)
g_pHyprRenderer->m_bWindowRequestedCursorHide = true;
} else {
else
g_pHyprRenderer->m_bWindowRequestedCursorHide = false;
}
if (m_bCursorImageOverridden) {
if (!cursorImageUnlocked())
return;
}
if (m_ecbClickBehavior == CLICKMODE_KILL) {
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "crosshair");
return;
}
// cursorSurfaceInfo.pSurface = e->surface;
@@ -495,6 +486,34 @@ void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_even
wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, e->surface, e->hotspot_x, e->hotspot_y);
}
void CInputManager::processMouseRequest(wlr_cursor_shape_manager_v1_request_set_shape_event* e) {
if (!g_pHyprRenderer->shouldRenderCursor())
return;
if (!g_pCompositor->m_pLastFocus)
return;
if (wl_resource_get_client(g_pCompositor->m_pLastFocus->resource) != e->seat_client->client) {
Debug::log(ERR, "Disallowing cursor shape request from unfocused");
return;
}
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, wlr_cursor_shape_v1_name(e->shape));
}
bool CInputManager::cursorImageUnlocked() {
if (!g_pHyprRenderer->shouldRenderCursor())
return false;
if (m_ecbClickBehavior == CLICKMODE_KILL)
return false;
if (m_bCursorImageOverridden)
return false;
return true;
}
eClickBehaviorMode CInputManager::getClickMode() {
return m_ecbClickBehavior;
}
@@ -609,9 +628,8 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
g_pCompositor->notifyIdleActivity();
if (passEvent) {
if (passEvent)
wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, factor * e->delta, std::round(factor * e->delta_discrete), e->source);
}
}
Vector2D CInputManager::getMouseCoordsInternal() {
@@ -773,16 +791,14 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
if (!FILEPATH.empty()) {
auto path = absolutePath(FILEPATH, g_pConfigManager->configCurrentPath);
if (!std::filesystem::exists(path)) {
if (!std::filesystem::exists(path))
Debug::log(ERR, "input:kb_file= file doesnt exist");
} else {
else
KEYMAP = xkb_keymap_new_from_file(CONTEXT, fopen(path.c_str(), "r"), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
}
}
if (!KEYMAP) {
if (!KEYMAP)
KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
}
if (!KEYMAP) {
g_pConfigManager->addParseError("Invalid keyboard layout passed. ( rules: " + RULES + ", model: " + MODEL + ", variant: " + VARIANT + ", options: " + OPTIONS +
@@ -813,9 +829,8 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
wlrMods.locked |= (uint32_t)1 << IDX;
}
if (wlrMods.locked != 0) {
if (wlrMods.locked != 0)
wlr_keyboard_notify_modifiers(wlr_keyboard_from_input_device(pKeyboard->keyboard), 0, 0, wlrMods.locked, 0);
}
xkb_keymap_unref(KEYMAP);
xkb_context_unref(CONTEXT);
@@ -1042,9 +1057,8 @@ void CInputManager::updateKeyboardsLeds(wlr_input_device* pKeyboard) {
uint32_t leds = 0;
for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) {
if (xkb_state_led_index_is_active(keyboard->xkb_state, keyboard->led_indexes[i])) {
if (xkb_state_led_index_is_active(keyboard->xkb_state, keyboard->led_indexes[i]))
leds |= (1 << i);
}
}
for (auto& kb : m_lKeyboards) {
@@ -1150,11 +1164,10 @@ void CInputManager::recheckConstraint(SMouse* pMouse) {
const auto PREGION = &pMouse->currentConstraint->region;
if (pMouse->currentConstraint->type == WLR_POINTER_CONSTRAINT_V1_CONFINED) {
pixman_region32_copy(&pMouse->confinedTo, PREGION);
} else {
pixman_region32_clear(&pMouse->confinedTo);
}
if (pMouse->currentConstraint->type == WLR_POINTER_CONSTRAINT_V1_CONFINED)
pMouse->confinedTo.set(PREGION);
else
pMouse->confinedTo.clear();
}
void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* constraint) {
@@ -1175,7 +1188,7 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co
if (PWINDOW) {
if (PWINDOW->m_bIsX11) {
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, constraint->current.cursor_hint.x + PWINDOW->m_uSurface.xwayland->x,
PWINDOW->m_uSurface.xwayland->y + PWINDOW->m_vRealPosition.vec().y);
constraint->current.cursor_hint.y + PWINDOW->m_uSurface.xwayland->y);
wlr_seat_pointer_warp(constraint->seat, constraint->current.cursor_hint.x, constraint->current.cursor_hint.y);
} else {
@@ -1200,11 +1213,10 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co
pMouse->currentConstraint = constraint;
pMouse->constraintActive = true;
if (pixman_region32_not_empty(&constraint->current.region)) {
if (pixman_region32_not_empty(&constraint->current.region))
pixman_region32_intersect(&constraint->region, &constraint->surface->input_region, &constraint->current.region);
} else {
else
pixman_region32_copy(&constraint->region, &constraint->surface->input_region);
}
// warp to the constraint
recheckConstraint(pMouse);
@@ -1222,9 +1234,8 @@ void CInputManager::unconstrainMouse() {
const auto CONSTRAINTWINDOW = g_pCompositor->getConstraintWindow(g_pCompositor->m_sSeat.mouse);
if (CONSTRAINTWINDOW) {
if (CONSTRAINTWINDOW)
g_pXWaylandManager->activateSurface(CONSTRAINTWINDOW->m_pWLSurface.wlr(), false);
}
wlr_pointer_constraint_v1_send_deactivated(g_pCompositor->m_sSeat.mouse->currentConstraint);
g_pCompositor->m_sSeat.mouse->constraintActive = false;
@@ -1247,11 +1258,10 @@ void Events::listener_commitConstraint(void* owner, void* data) {
}
if (PMOUSE->currentConstraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_REGION) {
if (pixman_region32_not_empty(&PMOUSE->currentConstraint->current.region)) {
if (pixman_region32_not_empty(&PMOUSE->currentConstraint->current.region))
pixman_region32_intersect(&PMOUSE->currentConstraint->region, &PMOUSE->currentConstraint->surface->input_region, &PMOUSE->currentConstraint->current.region);
} else {
else
pixman_region32_copy(&PMOUSE->currentConstraint->region, &PMOUSE->currentConstraint->surface->input_region);
}
g_pInputManager->recheckConstraint(PMOUSE);
}

View File

@@ -7,18 +7,21 @@
#include "../../helpers/Timer.hpp"
#include "InputMethodRelay.hpp"
enum eClickBehaviorMode {
enum eClickBehaviorMode
{
CLICKMODE_DEFAULT = 0,
CLICKMODE_KILL
};
enum eMouseBindMode {
enum eMouseBindMode
{
MBIND_INVALID = -1,
MBIND_MOVE = 0,
MBIND_RESIZE
};
enum eBorderIconDirection {
enum eBorderIconDirection
{
BORDERICON_NONE,
BORDERICON_UP,
BORDERICON_DOWN,
@@ -96,7 +99,8 @@ class CInputManager {
void setClickMode(eClickBehaviorMode);
eClickBehaviorMode getClickMode();
void processMouseRequest(wlr_seat_pointer_request_set_cursor_event*);
void processMouseRequest(wlr_seat_pointer_request_set_cursor_event* e);
void processMouseRequest(wlr_cursor_shape_manager_v1_request_set_shape_event* e);
void onTouchDown(wlr_touch_down_event*);
void onTouchUp(wlr_touch_up_event*);
@@ -190,6 +194,8 @@ class CInputManager {
void processMouseDownNormal(wlr_pointer_button_event* e);
void processMouseDownKill(wlr_pointer_button_event* e);
bool cursorImageUnlocked();
void disableAllKeyboards(bool virt = false);
uint32_t m_uiCapabilities = 0;

View File

@@ -326,15 +326,11 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou
void CScreencopyProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e) {
m_pLastMonitorBackBuffer = e->buffer;
shareAllFrames(pMonitor, true);
shareAllFrames(pMonitor);
m_pLastMonitorBackBuffer = nullptr;
}
void CScreencopyProtocolManager::onRenderEnd(CMonitor* pMonitor) {
shareAllFrames(pMonitor, false);
}
void CScreencopyProtocolManager::shareAllFrames(CMonitor* pMonitor, bool dmabuf) {
void CScreencopyProtocolManager::shareAllFrames(CMonitor* pMonitor) {
if (m_vFramesAwaitingWrite.empty())
return; // nothing to share
@@ -347,7 +343,7 @@ void CScreencopyProtocolManager::shareAllFrames(CMonitor* pMonitor, bool dmabuf)
continue;
}
if (f->pMonitor != pMonitor || dmabuf != (f->bufferCap == WLR_BUFFER_CAP_DMABUF))
if (f->pMonitor != pMonitor)
continue;
shareFrame(f);
@@ -407,11 +403,15 @@ void CScreencopyProtocolManager::sendFrameDamage(SScreencopyFrame* frame) {
if (!frame->withDamage)
return;
PIXMAN_DAMAGE_FOREACH(&frame->pMonitor->lastFrameDamage) {
const auto RECT = &RECTSARR[i];
zwlr_screencopy_frame_v1_send_damage(frame->resource, std::clamp(RECT->x1, 0, frame->buffer->width), std::clamp(RECT->y1, 0, frame->buffer->height),
std::clamp(RECT->x2 - RECT->x1, 0, frame->buffer->width - RECT->x1),
std::clamp(RECT->y2 - RECT->y1, 0, frame->buffer->height - RECT->y1));
for (auto& RECT : frame->pMonitor->lastFrameDamage.getRects()) {
if (frame->buffer->width < 1 || frame->buffer->height < 1 || frame->buffer->width - RECT.x1 < 1 || frame->buffer->height - RECT.y1 < 1) {
Debug::log(ERR, "[sc] Failed to send damage");
break;
}
zwlr_screencopy_frame_v1_send_damage(frame->resource, std::clamp(RECT.x1, 0, frame->buffer->width), std::clamp(RECT.y1, 0, frame->buffer->height),
std::clamp(RECT.x2 - RECT.x1, 0, frame->buffer->width - RECT.x1), std::clamp(RECT.y2 - RECT.y1, 0, frame->buffer->height - RECT.y1));
}
}
@@ -422,47 +422,16 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec*
if (!wlr_buffer_begin_data_ptr_access(frame->buffer, WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &data, &format, &stride))
return false;
// render the client
const auto PMONITOR = frame->pMonitor;
pixman_region32_t fakeDamage;
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecPixelSize.x * 10, PMONITOR->vecPixelSize.y * 10);
if (!wlr_output_attach_render(PMONITOR->output, nullptr)) {
Debug::log(ERR, "[screencopy] Couldn't attach render");
pixman_region32_fini(&fakeDamage);
if (!wlr_renderer_begin_with_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer)) {
wlr_buffer_end_data_ptr_access(frame->buffer);
return false;
}
const auto PFORMAT = get_gles2_format_from_drm(format);
if (!PFORMAT) {
Debug::log(ERR, "[screencopy] Cannot read pixels, unsupported format %lx", PFORMAT);
wlr_output_rollback(PMONITOR->output);
pixman_region32_fini(&fakeDamage);
wlr_buffer_end_data_ptr_access(frame->buffer);
return false;
}
g_pHyprOpenGL->begin(PMONITOR, &fakeDamage, true);
// we should still have the last frame by this point in the original fb
glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_RenderData.pCurrentMonData->primaryFB.m_iFb);
glFinish(); // flush
glReadPixels(frame->box.x, frame->box.y, frame->box.width, frame->box.height, PFORMAT->gl_format, PFORMAT->gl_type, data);
glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_iWLROutputFb);
g_pHyprOpenGL->end();
wlr_output_rollback(PMONITOR->output);
pixman_region32_fini(&fakeDamage);
bool success = wlr_renderer_read_pixels(g_pCompositor->m_sWLRRenderer, format, stride, frame->box.width, frame->box.height, frame->box.x, frame->box.y, 0, 0, data);
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
wlr_buffer_end_data_ptr_access(frame->buffer);
return true;
return success;
}
bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
@@ -482,6 +451,7 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
float color[] = {0, 0, 0, 0};
wlr_renderer_clear(g_pCompositor->m_sWLRRenderer, color);
// TODO: use hl render methods to use damage
wlr_render_texture_with_matrix(g_pCompositor->m_sWLRRenderer, sourceTex, glMatrix, 1.0f);
wlr_texture_destroy(sourceTex);

View File

@@ -77,7 +77,6 @@ class CScreencopyProtocolManager {
void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer);
void onRenderEnd(CMonitor* pMonitor);
void onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e);
private:
@@ -91,7 +90,7 @@ class CScreencopyProtocolManager {
wlr_buffer* m_pLastMonitorBackBuffer = nullptr;
void shareAllFrames(CMonitor* pMonitor, bool dmabuf);
void shareAllFrames(CMonitor* pMonitor);
void shareFrame(SScreencopyFrame* frame);
void sendFrameDamage(SScreencopyFrame* frame);
bool copyFrameDmabuf(SScreencopyFrame* frame);

View File

@@ -36,8 +36,6 @@ CToplevelExportProtocolManager::CToplevelExportProtocolManager() {
m_liDisplayDestroy.notify = handleDisplayDestroy;
wl_display_add_destroy_listener(g_pCompositor->m_sWLDisplay, &m_liDisplayDestroy);
g_pHookSystem->hookDynamic("preRender", [&](void* self, std::any data) { onMonitorRender(std::any_cast<CMonitor*>(data)); });
Debug::log(LOG, "ToplevelExportManager started successfully!");
}
@@ -207,6 +205,12 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou
PFRAME->shmStride = (PSHMINFO->bpp / 8) * PFRAME->box.width;
hyprland_toplevel_export_frame_v1_send_buffer(PFRAME->resource, convert_drm_format_to_wl_shm(PFRAME->shmFormat), PFRAME->box.width, PFRAME->box.height, PFRAME->shmStride);
if (PFRAME->dmabufFormat != DRM_FORMAT_INVALID) {
hyprland_toplevel_export_frame_v1_send_linux_dmabuf(PFRAME->resource, PFRAME->dmabufFormat, PFRAME->box.width, PFRAME->box.height);
}
hyprland_toplevel_export_frame_v1_send_buffer_done(PFRAME->resource);
}
void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer, int32_t ignore_damage) {
@@ -278,11 +282,12 @@ void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* r
m_vFramesAwaitingWrite.emplace_back(PFRAME);
}
void CToplevelExportProtocolManager::onMonitorRender(CMonitor* pMonitor) {
void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e) {
if (m_vFramesAwaitingWrite.empty())
return; // nothing to share
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(e->output);
std::vector<SScreencopyFrame*> framesToRemove;
// share frame if correct output
@@ -292,6 +297,9 @@ void CToplevelExportProtocolManager::onMonitorRender(CMonitor* pMonitor) {
continue;
}
if (PMONITOR != g_pCompositor->getMonitorFromID(f->pWindow->m_iMonitorID))
continue;
wlr_box geometry = {f->pWindow->m_vRealPosition.vec().x, f->pWindow->m_vRealPosition.vec().y, f->pWindow->m_vRealSize.vec().x, f->pWindow->m_vRealSize.vec().y};
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, &geometry))
@@ -314,14 +322,12 @@ void CToplevelExportProtocolManager::shareFrame(SScreencopyFrame* frame) {
if (!frame->buffer || !g_pCompositor->windowValidMapped(frame->pWindow))
return;
// TODO: damage
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
uint32_t flags = 0;
if (frame->bufferCap == WLR_BUFFER_CAP_DMABUF) {
if (!copyFrameDmabuf(frame)) {
if (!copyFrameDmabuf(frame, &now)) {
hyprland_toplevel_export_frame_v1_send_failed(frame->resource);
return;
}
@@ -333,12 +339,17 @@ void CToplevelExportProtocolManager::shareFrame(SScreencopyFrame* frame) {
}
hyprland_toplevel_export_frame_v1_send_flags(frame->resource, flags);
// todo: send damage
sendDamage(frame);
uint32_t tvSecHi = (sizeof(now.tv_sec) > 4) ? now.tv_sec >> 32 : 0;
uint32_t tvSecLo = now.tv_sec & 0xFFFFFFFF;
hyprland_toplevel_export_frame_v1_send_ready(frame->resource, tvSecHi, tvSecLo, now.tv_nsec);
}
void CToplevelExportProtocolManager::sendDamage(SScreencopyFrame* frame) {
// TODO: send proper dmg
hyprland_toplevel_export_frame_v1_send_damage(frame->resource, 0, 0, frame->box.width, frame->box.height);
}
bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* now) {
void* data;
uint32_t format;
@@ -347,16 +358,14 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times
return false;
// render the client
const auto PMONITOR = g_pCompositor->getMonitorFromID(frame->pWindow->m_iMonitorID);
pixman_region32_t fakeDamage;
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecPixelSize.x * 10, PMONITOR->vecPixelSize.y * 10);
const auto PMONITOR = g_pCompositor->getMonitorFromID(frame->pWindow->m_iMonitorID);
CRegion fakeDamage{0, 0, PMONITOR->vecPixelSize.x * 10, PMONITOR->vecPixelSize.y * 10};
if (frame->overlayCursor)
wlr_output_lock_software_cursors(PMONITOR->output, true);
if (!wlr_output_attach_render(PMONITOR->output, nullptr)) {
Debug::log(ERR, "[toplevel_export] Couldn't attach render");
pixman_region32_fini(&fakeDamage);
wlr_buffer_end_data_ptr_access(frame->buffer);
if (frame->overlayCursor)
wlr_output_lock_software_cursors(PMONITOR->output, false);
@@ -398,7 +407,6 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times
if (!PFORMAT) {
Debug::log(ERR, "[toplevel_export] Cannot read pixels, unsupported format %lx", PFORMAT);
g_pHyprOpenGL->end();
pixman_region32_fini(&fakeDamage);
wlr_buffer_end_data_ptr_access(frame->buffer);
if (frame->overlayCursor)
wlr_output_lock_software_cursors(PMONITOR->output, false);
@@ -407,16 +415,12 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times
glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_RenderData.pCurrentMonData->primaryFB.m_iFb);
glFinish(); // flush
glReadPixels(0, 0, frame->box.width, frame->box.height, PFORMAT->gl_format, PFORMAT->gl_type, data);
g_pHyprOpenGL->end();
wlr_output_rollback(PMONITOR->output);
pixman_region32_fini(&fakeDamage);
wlr_buffer_end_data_ptr_access(frame->buffer);
if (frame->overlayCursor)
@@ -425,10 +429,31 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times
return true;
}
bool CToplevelExportProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
// todo
Debug::log(ERR, "DMABUF copying not impl'd!");
return false;
bool CToplevelExportProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame, timespec* now) {
if (!wlr_renderer_begin_with_buffer(g_pCompositor->m_sWLRRenderer, frame->buffer))
return false;
const auto PMONITOR = g_pCompositor->getMonitorFromID(frame->pWindow->m_iMonitorID);
CRegion fakeDamage{0, 0, INT16_MAX, INT16_MAX};
g_pHyprOpenGL->begin(PMONITOR, &fakeDamage, true);
g_pHyprOpenGL->clear(CColor(17.0 / 255.0, 17.0 / 255.0, 17.0 / 255.0, 1.0));
g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(frame->pWindow); // block the feedback to avoid spamming the surface if it's visible
g_pHyprRenderer->renderWindow(frame->pWindow, PMONITOR, now, false, RENDER_PASS_ALL, true, true);
g_pHyprRenderer->m_bBlockSurfaceFeedback = false;
g_pHyprOpenGL->bindWlrOutputFb();
wlr_box monbox = {0, 0, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 1.f);
g_pHyprOpenGL->end();
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
return true;
}
void CToplevelExportProtocolManager::onWindowUnmap(CWindow* pWindow) {

View File

@@ -22,6 +22,7 @@ class CToplevelExportProtocolManager {
void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer, int32_t ignore_damage);
void displayDestroy();
void onWindowUnmap(CWindow* pWindow);
void onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e);
private:
wl_global* m_pGlobal = nullptr;
@@ -33,10 +34,9 @@ class CToplevelExportProtocolManager {
std::vector<SScreencopyFrame*> m_vFramesAwaitingWrite;
void shareFrame(SScreencopyFrame* frame);
bool copyFrameDmabuf(SScreencopyFrame* frame);
bool copyFrameDmabuf(SScreencopyFrame* frame, timespec* now);
bool copyFrameShm(SScreencopyFrame* frame, timespec* now);
void onMonitorRender(CMonitor* pMonitor);
void sendDamage(SScreencopyFrame* frame);
friend class CScreencopyClient;
};

View File

@@ -77,7 +77,7 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(wl_client* client, wl_resource* r
SXDGOutput* pXDGOutput = m_vXDGOutputs.emplace_back(std::make_unique<SXDGOutput>(PMONITOR)).get();
#ifndef NO_XWAYLAND
if (g_pXWaylandManager->m_sWLRXWayland->server->client == client)
if (g_pXWaylandManager->m_sWLRXWayland && g_pXWaylandManager->m_sWLRXWayland->server && g_pXWaylandManager->m_sWLRXWayland->server->client == client)
pXDGOutput->isXWayland = true;
#endif
pXDGOutput->client = client;
@@ -124,4 +124,4 @@ void CXDGOutputProtocol::updateAllOutputs() {
wlr_output_schedule_done(o->monitor->output);
}
}
}

View File

@@ -20,7 +20,7 @@ bool CFramebuffer::alloc(int w, int h) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
if (firstAlloc || m_Size != Vector2D(w, h)) {
if (firstAlloc || m_vSize != Vector2D(w, h)) {
glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
@@ -48,7 +48,7 @@ bool CFramebuffer::alloc(int w, int h) {
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_iCurrentOutputFb);
m_Size = Vector2D(w, h);
m_vSize = Vector2D(w, h);
return true;
}
@@ -73,7 +73,7 @@ void CFramebuffer::release() {
m_cTex.m_iTexID = 0;
m_iFb = -1;
m_Size = Vector2D();
m_vSize = Vector2D();
}
CFramebuffer::~CFramebuffer() {

View File

@@ -7,20 +7,16 @@ class CFramebuffer {
public:
~CFramebuffer();
bool alloc(int w, int h);
void bind();
void release();
void reset();
bool isAllocated();
bool alloc(int w, int h);
void bind();
void release();
void reset();
bool isAllocated();
Vector2D m_Position;
Vector2D m_Size;
float m_fScale = 1;
Vector2D m_vSize;
CTexture m_cTex;
GLuint m_iFb = -1;
CTexture m_cTex;
GLuint m_iFb = -1;
CTexture* m_pStencilTex = nullptr;
wl_output_transform m_tTransform; // for saving state
CTexture* m_pStencilTex = nullptr;
};

View File

@@ -23,6 +23,16 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
Debug::log(LOG, "Renderer: %s", glGetString(GL_RENDERER));
Debug::log(LOG, "Supported extensions size: %d", std::count(m_szExtensions.begin(), m_szExtensions.end(), ' '));
#ifdef USE_TRACY_GPU
loadGLProc(&glQueryCounter, "glQueryCounterEXT");
loadGLProc(&glGetQueryObjectiv, "glGetQueryObjectivEXT");
loadGLProc(&glGetQueryObjectui64v, "glGetQueryObjectui64vEXT");
#endif
TRACY_GPU_CONTEXT;
#ifdef GLES2
Debug::log(WARN, "!RENDERER: Using the legacy GLES2 renderer!");
#endif
@@ -93,9 +103,11 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool
return shader;
}
void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool fake) {
void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) {
m_RenderData.pMonitor = pMonitor;
TRACY_GPU_ZONE("RenderBegin");
if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL)) {
eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL));
}
@@ -112,7 +124,7 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool
m_iWLROutputFb = m_iCurrentOutputFb;
// ensure a framebuffer for the monitor exists
if (m_mMonitorRenderResources.find(pMonitor) == m_mMonitorRenderResources.end() || m_RenderData.pCurrentMonData->primaryFB.m_Size != pMonitor->vecPixelSize) {
if (m_mMonitorRenderResources.find(pMonitor) == m_mMonitorRenderResources.end() || m_RenderData.pCurrentMonData->primaryFB.m_vSize != pMonitor->vecPixelSize) {
m_RenderData.pCurrentMonData->stencilTex.allocate();
m_RenderData.pCurrentMonData->primaryFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
@@ -122,18 +134,20 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool
m_RenderData.pCurrentMonData->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
m_RenderData.pCurrentMonData->monitorMirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
createBGTextureForMonitor(pMonitor);
}
if (m_RenderData.pCurrentMonData->monitorMirrorFB.isAllocated() && m_RenderData.pMonitor->mirrors.empty())
m_RenderData.pCurrentMonData->monitorMirrorFB.release();
if (!m_RenderData.pCurrentMonData->m_bShadersInitialized)
initShaders();
// bind the primary Hypr Framebuffer
m_RenderData.pCurrentMonData->primaryFB.bind();
m_RenderData.pDamage = pDamage;
m_RenderData.damage.set(*pDamage);
m_bFakeFrame = fake;
@@ -146,12 +160,14 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, pixman_region32_t* pDamage, bool
void CHyprOpenGLImpl::end() {
static auto* const PZOOMRIGID = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_rigid")->intValue;
TRACY_GPU_ZONE("RenderEnd");
// end the render, copy the data to the WLR framebuffer
if (!m_bFakeFrame) {
pixman_region32_copy(m_RenderData.pDamage, &m_RenderData.pMonitor->lastFrameDamage);
m_RenderData.damage = m_RenderData.pMonitor->lastFrameDamage;
if (!m_RenderData.pMonitor->mirrors.empty())
g_pHyprOpenGL->saveBufferForMirror(); // save with original damage region
saveBufferForMirror(); // save with original damage region
glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb);
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
@@ -176,14 +192,19 @@ void CHyprOpenGLImpl::end() {
monbox.y = m_RenderData.pMonitor->vecTransformedSize.y - monbox.height;
}
clear(CColor(11.0 / 255.0, 11.0 / 255.0, 11.0 / 255.0, 1.0));
m_bEndFrame = true;
m_bApplyFinalShader = true;
if (m_RenderData.mouseZoomUseMouse)
m_RenderData.useNearestNeighbor = true;
renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 1.f, 0);
blend(false);
if (m_sFinalScreenShader.program < 1)
renderTexturePrimitive(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox);
else
renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 1.f);
blend(true);
m_RenderData.useNearestNeighbor = false;
m_bApplyFinalShader = false;
@@ -197,6 +218,10 @@ void CHyprOpenGLImpl::end() {
m_RenderData.mouseZoomUseMouse = true;
}
void CHyprOpenGLImpl::bindWlrOutputFb() {
glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb);
}
void CHyprOpenGLImpl::initShaders() {
GLuint prog = createProgram(QUADVERTSRC, QUADFRAGSRC);
m_RenderData.pCurrentMonData->m_shQUAD.program = prog;
@@ -296,6 +321,16 @@ void CHyprOpenGLImpl::initShaders() {
m_RenderData.pCurrentMonData->m_shBLUR2.radius = glGetUniformLocation(prog, "radius");
m_RenderData.pCurrentMonData->m_shBLUR2.halfpixel = glGetUniformLocation(prog, "halfpixel");
prog = createProgram(TEXVERTSRC, FRAGBLURFINISH);
m_RenderData.pCurrentMonData->m_shBLURFINISH.program = prog;
m_RenderData.pCurrentMonData->m_shBLURFINISH.tex = glGetUniformLocation(prog, "tex");
m_RenderData.pCurrentMonData->m_shBLURFINISH.proj = glGetUniformLocation(prog, "proj");
m_RenderData.pCurrentMonData->m_shBLURFINISH.posAttrib = glGetAttribLocation(prog, "pos");
m_RenderData.pCurrentMonData->m_shBLURFINISH.texAttrib = glGetAttribLocation(prog, "texcoord");
m_RenderData.pCurrentMonData->m_shBLURFINISH.noise = glGetUniformLocation(prog, "noise");
m_RenderData.pCurrentMonData->m_shBLURFINISH.contrast = glGetUniformLocation(prog, "contrast");
m_RenderData.pCurrentMonData->m_shBLURFINISH.brightness = glGetUniformLocation(prog, "brightness");
prog = createProgram(QUADVERTSRC, FRAGSHADOW);
m_RenderData.pCurrentMonData->m_shSHADOW.program = prog;
m_RenderData.pCurrentMonData->m_shSHADOW.proj = glGetUniformLocation(prog, "proj");
@@ -371,13 +406,13 @@ void CHyprOpenGLImpl::applyScreenShader(const std::string& path) {
void CHyprOpenGLImpl::clear(const CColor& color) {
RASSERT(m_RenderData.pMonitor, "Tried to render without begin()!");
TRACY_GPU_ZONE("RenderClear");
glClearColor(color.r, color.g, color.b, color.a);
if (pixman_region32_not_empty(m_RenderData.pDamage)) {
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
const auto RECT = RECTSARR[i];
if (!m_RenderData.damage.empty()) {
for (auto& RECT : m_RenderData.damage.getRects()) {
scissor(&RECT);
glClear(GL_COLOR_BUFFER_BIT);
}
}
@@ -385,6 +420,15 @@ void CHyprOpenGLImpl::clear(const CColor& color) {
scissor((wlr_box*)nullptr);
}
void CHyprOpenGLImpl::blend(bool enabled) {
if (enabled)
glEnable(GL_BLEND);
else
glDisable(GL_BLEND);
m_bBlend = enabled;
}
void CHyprOpenGLImpl::scissor(const wlr_box* pBox, bool transform) {
RASSERT(m_RenderData.pMonitor, "Tried to scissor without begin()!");
@@ -426,14 +470,16 @@ void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h
}
void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) {
if (pixman_region32_not_empty(m_RenderData.pDamage))
renderRectWithDamage(box, col, m_RenderData.pDamage, round);
if (!m_RenderData.damage.empty())
renderRectWithDamage(box, col, &m_RenderData.damage, round);
}
void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixman_region32_t* damage, int round) {
void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, CRegion* damage, int round) {
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()!");
TRACY_GPU_ZONE("RenderRectWithDamage");
wlr_box newBox = *box;
scaleBox(&newBox, m_RenderData.renderModif.scale);
newBox.x += m_RenderData.renderModif.translate.x;
@@ -448,7 +494,6 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
float glMatrix[9];
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(m_RenderData.pCurrentMonData->m_shQUAD.program);
@@ -481,22 +526,17 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib);
if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) {
pixman_region32_t damageClip;
pixman_region32_init(&damageClip);
pixman_region32_intersect_rect(&damageClip, damage, m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height);
CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height};
damageClip.intersect(*damage);
if (pixman_region32_not_empty(&damageClip)) {
PIXMAN_DAMAGE_FOREACH(&damageClip) {
const auto RECT = RECTSARR[i];
if (!damageClip.empty()) {
for (auto& RECT : damageClip.getRects()) {
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
pixman_region32_fini(&damageClip);
} else {
PIXMAN_DAMAGE_FOREACH(damage) {
const auto RECT = RECTSARR[i];
for (auto& RECT : damage->getRects()) {
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
@@ -516,19 +556,21 @@ void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha
void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardActive, bool allowCustomUV) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardActive, false, allowCustomUV, true);
renderTextureInternalWithDamage(tex, pBox, alpha, &m_RenderData.damage, round, discardActive, false, allowCustomUV, true);
scissor((wlr_box*)nullptr);
}
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardActive, bool noAA,
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA,
bool allowCustomUV, bool allowDim) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
TRACY_GPU_ZONE("RenderTextureInternalWithDamage");
alpha = std::clamp(alpha, 0.f, 1.f);
if (!pixman_region32_not_empty(m_RenderData.pDamage))
if (m_RenderData.damage.empty())
return;
wlr_box newBox = *pBox;
@@ -548,7 +590,6 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
CShader* shader = nullptr;
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
bool usingFinalShader = false;
@@ -670,22 +711,17 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
glEnableVertexAttribArray(shader->texAttrib);
if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) {
pixman_region32_t damageClip;
pixman_region32_init(&damageClip);
pixman_region32_intersect_rect(&damageClip, damage, m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height);
CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height};
damageClip.intersect(*damage);
if (pixman_region32_not_empty(&damageClip)) {
PIXMAN_DAMAGE_FOREACH(&damageClip) {
const auto RECT = RECTSARR[i];
if (!damageClip.empty()) {
for (auto& RECT : damageClip.getRects()) {
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
pixman_region32_fini(&damageClip);
} else {
PIXMAN_DAMAGE_FOREACH(damage) {
const auto RECT = RECTSARR[i];
for (auto& RECT : damage->getRects()) {
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
@@ -697,13 +733,72 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
glBindTexture(tex.m_iTarget, 0);
}
void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, wlr_box* pBox) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
TRACY_GPU_ZONE("RenderTexturePrimitive");
if (m_RenderData.damage.empty())
return;
wlr_box newBox = *pBox;
scaleBox(&newBox, m_RenderData.renderModif.scale);
newBox.x += m_RenderData.renderModif.translate.x;
newBox.y += m_RenderData.renderModif.translate.y;
// get transform
const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform);
float matrix[9];
wlr_matrix_project_box(matrix, &newBox, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
float glMatrix[9];
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
CShader* shader = &m_RenderData.pCurrentMonData->m_shPASSTHRURGBA;
glActiveTexture(GL_TEXTURE0);
glBindTexture(tex.m_iTarget, tex.m_iTexID);
glUseProgram(shader->program);
#ifndef GLES2
glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix);
#else
wlr_matrix_transpose(glMatrix, glMatrix);
glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix);
#endif
glUniform1i(shader->tex, 0);
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(shader->posAttrib);
glEnableVertexAttribArray(shader->texAttrib);
for (auto& RECT : m_RenderData.damage.getRects()) {
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
scissor((wlr_box*)nullptr);
glDisableVertexAttribArray(shader->posAttrib);
glDisableVertexAttribArray(shader->texAttrib);
glBindTexture(tex.m_iTarget, 0);
}
// This probably isn't the fastest
// but it works... well, I guess?
//
// Dual (or more) kawase blur
CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* originalDamage) {
CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* pBox, CRegion* originalDamage) {
glDisable(GL_BLEND);
TRACY_GPU_ZONE("RenderBlurMainFramebufferWithDamage");
const auto BLENDBEFORE = m_bBlend;
blend(false);
glDisable(GL_STENCIL_TEST);
// get transforms for the full monitor
@@ -716,16 +811,14 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
// get the config settings
static auto* const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_size")->intValue;
static auto* const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur_passes")->intValue;
static auto* const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur:size")->intValue;
static auto* const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur:passes")->intValue;
// prep damage
pixman_region32_t damage;
pixman_region32_init(&damage);
pixman_region32_copy(&damage, originalDamage);
wlr_region_transform(&damage, &damage, wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x,
CRegion damage{*originalDamage};
wlr_region_transform(damage.pixman(), damage.pixman(), wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x,
m_RenderData.pMonitor->vecTransformedSize.y);
wlr_region_expand(&damage, &damage, *PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES));
wlr_region_expand(damage.pixman(), damage.pixman(), *PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES));
// helper
const auto PMIRRORFB = &m_RenderData.pCurrentMonData->mirrorFB;
@@ -734,7 +827,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
CFramebuffer* currentRenderToFB = &m_RenderData.pCurrentMonData->primaryFB;
// declare the draw func
auto drawPass = [&](CShader* pShader, pixman_region32_t* pDamage) {
auto drawPass = [&](CShader* pShader, CRegion* pDamage) {
if (currentRenderToFB == PMIRRORFB)
PMIRRORSWAPFB->bind();
else
@@ -770,11 +863,9 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
glEnableVertexAttribArray(pShader->posAttrib);
glEnableVertexAttribArray(pShader->texAttrib);
if (pixman_region32_not_empty(pDamage)) {
PIXMAN_DAMAGE_FOREACH(pDamage) {
const auto RECT = RECTSARR[i];
if (!pDamage->empty()) {
for (auto& RECT : pDamage->getRects()) {
scissor(&RECT, false /* this region is already transformed */);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
@@ -794,32 +885,83 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
glBindTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTarget, m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTexID);
// damage region will be scaled, make a temp
pixman_region32_t tempDamage;
pixman_region32_init(&tempDamage);
wlr_region_scale(&tempDamage, &damage, 1.f / 2.f); // when DOWNscaling, we make the region twice as small because it's the TARGET
CRegion tempDamage{damage};
wlr_region_scale(tempDamage.pixman(), damage.pixman(), 1.f / 2.f); // when DOWNscaling, we make the region twice as small because it's the TARGET
drawPass(&m_RenderData.pCurrentMonData->m_shBLUR1, &tempDamage);
// and draw
for (int i = 1; i < *PBLURPASSES; ++i) {
wlr_region_scale(&tempDamage, &damage, 1.f / (1 << (i + 1)));
wlr_region_scale(tempDamage.pixman(), damage.pixman(), 1.f / (1 << (i + 1)));
drawPass(&m_RenderData.pCurrentMonData->m_shBLUR1, &tempDamage); // down
}
for (int i = *PBLURPASSES - 1; i >= 0; --i) {
wlr_region_scale(&tempDamage, &damage, 1.f / (1 << i)); // when upsampling we make the region twice as big
drawPass(&m_RenderData.pCurrentMonData->m_shBLUR2, &tempDamage); // up
wlr_region_scale(tempDamage.pixman(), damage.pixman(), 1.f / (1 << i)); // when upsampling we make the region twice as big
drawPass(&m_RenderData.pCurrentMonData->m_shBLUR2, &tempDamage); // up
}
// finalize with effects
{
static auto* const PBLURCONTRAST = &g_pConfigManager->getConfigValuePtr("decoration:blur:contrast")->floatValue;
static auto* const PBLURNOISE = &g_pConfigManager->getConfigValuePtr("decoration:blur:noise")->floatValue;
static auto* const PBLURBRIGHTNESS = &g_pConfigManager->getConfigValuePtr("decoration:blur:brightness")->floatValue;
if (currentRenderToFB == PMIRRORFB)
PMIRRORSWAPFB->bind();
else
PMIRRORFB->bind();
glActiveTexture(GL_TEXTURE0);
glBindTexture(currentRenderToFB->m_cTex.m_iTarget, currentRenderToFB->m_cTex.m_iTexID);
glTexParameteri(currentRenderToFB->m_cTex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glUseProgram(m_RenderData.pCurrentMonData->m_shBLURFINISH.program);
#ifndef GLES2
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_TRUE, glMatrix);
#else
wlr_matrix_transpose(glMatrix, glMatrix);
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_FALSE, glMatrix);
#endif
glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.contrast, *PBLURCONTRAST);
glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.noise, *PBLURNOISE);
glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.brightness, *PBLURBRIGHTNESS);
glUniform1i(m_RenderData.pCurrentMonData->m_shBLURFINISH.tex, 0);
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBLURFINISH.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBLURFINISH.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURFINISH.posAttrib);
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURFINISH.texAttrib);
if (!damage.empty()) {
for (auto& RECT : damage.getRects()) {
scissor(&RECT, false /* this region is already transformed */);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURFINISH.posAttrib);
glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURFINISH.texAttrib);
if (currentRenderToFB != PMIRRORFB)
currentRenderToFB = PMIRRORFB;
else
currentRenderToFB = PMIRRORSWAPFB;
}
// finish
pixman_region32_fini(&tempDamage);
pixman_region32_fini(&damage);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(PMIRRORFB->m_cTex.m_iTarget, 0);
blend(BLENDBEFORE);
return currentRenderToFB;
}
@@ -835,9 +977,9 @@ void CHyprOpenGLImpl::markBlurDirtyForMonitor(CMonitor* pMonitor) {
}
void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) {
static auto* const PBLURNEWOPTIMIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_new_optimizations")->intValue;
static auto* const PBLURXRAY = &g_pConfigManager->getConfigValuePtr("decoration:blur_xray")->intValue;
static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
static auto* const PBLURNEWOPTIMIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur:new_optimizations")->intValue;
static auto* const PBLURXRAY = &g_pConfigManager->getConfigValuePtr("decoration:blur:xray")->intValue;
static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue;
if (!*PBLURNEWOPTIMIZE || !m_mMonitorRenderResources[pMonitor].blurFBDirty || !*PBLUR)
return;
@@ -862,20 +1004,14 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) {
if (PSURFACE->opaque)
return false;
pixman_region32_t inverseOpaque;
pixman_region32_init(&inverseOpaque);
CRegion inverseOpaque;
pixman_box32_t surfbox = {0, 0, PSURFACE->current.width, PSURFACE->current.height};
pixman_region32_copy(&inverseOpaque, &PSURFACE->current.opaque);
pixman_region32_inverse(&inverseOpaque, &inverseOpaque, &surfbox);
pixman_region32_intersect_rect(&inverseOpaque, &inverseOpaque, 0, 0, PSURFACE->current.width, PSURFACE->current.height);
CRegion opaqueRegion{&PSURFACE->current.opaque};
inverseOpaque.set(opaqueRegion).invert(&surfbox).intersect(0, 0, PSURFACE->current.width, PSURFACE->current.height);
if (!pixman_region32_not_empty(&inverseOpaque)) {
pixman_region32_fini(&inverseOpaque);
if (inverseOpaque.empty())
return false;
}
pixman_region32_fini(&inverseOpaque);
}
return true;
@@ -903,12 +1039,13 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) {
void CHyprOpenGLImpl::preBlurForCurrentMonitor() {
TRACY_GPU_ZONE("RenderPreBlurForCurrentMonitor");
const auto SAVEDRENDERMODIF = m_RenderData.renderModif;
m_RenderData.renderModif = {}; // fix shit
// make the fake dmg
pixman_region32_t fakeDamage;
pixman_region32_init_rect(&fakeDamage, 0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y);
CRegion fakeDamage{0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
wlr_box wholeMonitor = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
const auto POUTFB = blurMainFramebufferWithDamage(1, &wholeMonitor, &fakeDamage);
@@ -922,8 +1059,6 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() {
renderTextureInternalWithDamage(POUTFB->m_cTex, &wholeMonitor, 1, &fakeDamage, 0, false, true, false);
m_bEndFrame = false;
pixman_region32_fini(&fakeDamage);
m_RenderData.pCurrentMonData->primaryFB.bind();
m_RenderData.pCurrentMonData->blurFBDirty = false;
@@ -932,30 +1067,35 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() {
}
void CHyprOpenGLImpl::preWindowPass() {
static auto* const PBLURNEWOPTIMIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_new_optimizations")->intValue;
static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
if (!m_RenderData.pCurrentMonData->blurFBDirty || !*PBLURNEWOPTIMIZE || !*PBLUR || !m_RenderData.pCurrentMonData->blurFBShouldRender)
if (!preBlurQueued())
return;
// blur the main FB, it will be rendered onto the mirror
preBlurForCurrentMonitor();
}
bool CHyprOpenGLImpl::preBlurQueued() {
static auto* const PBLURNEWOPTIMIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur:new_optimizations")->intValue;
static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue;
return !(!m_RenderData.pCurrentMonData->blurFBDirty || !*PBLURNEWOPTIMIZE || !*PBLUR || !m_RenderData.pCurrentMonData->blurFBShouldRender);
}
void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, wlr_surface* pSurface, int round, bool blockBlurOptimization) {
RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!");
static auto* const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
static auto* const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue;
static auto* const PNOBLUROVERSIZED = &g_pConfigManager->getConfigValuePtr("decoration:no_blur_on_oversized")->intValue;
static auto* const PBLURNEWOPTIMIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_new_optimizations")->intValue;
static auto* const PBLURXRAY = &g_pConfigManager->getConfigValuePtr("decoration:blur_xray")->intValue;
static auto* const PBLURNEWOPTIMIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur:new_optimizations")->intValue;
static auto* const PBLURXRAY = &g_pConfigManager->getConfigValuePtr("decoration:blur:xray")->intValue;
TRACY_GPU_ZONE("RenderTextureWithBlur");
// make a damage region for this window
pixman_region32_t damage;
pixman_region32_init(&damage);
pixman_region32_intersect_rect(&damage, m_RenderData.pDamage, pBox->x, pBox->y, pBox->width, pBox->height); // clip it to the box
CRegion texDamage{m_RenderData.damage};
texDamage.intersect(pBox->x, pBox->y, pBox->width, pBox->height);
if (!pixman_region32_not_empty(&damage))
if (texDamage.empty())
return;
if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) ||
@@ -965,24 +1105,21 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
}
// amazing hack: the surface has an opaque region!
pixman_region32_t inverseOpaque;
pixman_region32_init(&inverseOpaque);
CRegion inverseOpaque;
if (a >= 1.f) {
pixman_box32_t surfbox = {0, 0, pSurface->current.width * pSurface->current.scale, pSurface->current.height * pSurface->current.scale};
pixman_region32_copy(&inverseOpaque, &pSurface->current.opaque);
pixman_region32_inverse(&inverseOpaque, &inverseOpaque, &surfbox);
pixman_region32_intersect_rect(&inverseOpaque, &inverseOpaque, 0, 0, pSurface->current.width * pSurface->current.scale, pSurface->current.height * pSurface->current.scale);
inverseOpaque = &pSurface->current.opaque;
inverseOpaque.invert(&surfbox).intersect(0, 0, pSurface->current.width * pSurface->current.scale, pSurface->current.height * pSurface->current.scale);
if (!pixman_region32_not_empty(&inverseOpaque)) {
pixman_region32_fini(&inverseOpaque);
if (inverseOpaque.empty()) {
renderTexture(tex, pBox, a, round, false, true);
return;
}
} else {
pixman_region32_init_rect(&inverseOpaque, 0, 0, pBox->width, pBox->height);
inverseOpaque = {0, 0, pBox->width, pBox->height};
}
wlr_region_scale(&inverseOpaque, &inverseOpaque, m_RenderData.pMonitor->scale);
wlr_region_scale(inverseOpaque.pixman(), inverseOpaque.pixman(), m_RenderData.pMonitor->scale);
// vvv TODO: layered blur fbs?
const bool USENEWOPTIMIZE = (*PBLURNEWOPTIMIZE && !blockBlurOptimization &&
@@ -991,17 +1128,13 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
CFramebuffer* POUTFB = nullptr;
if (!USENEWOPTIMIZE) {
pixman_region32_translate(&inverseOpaque, pBox->x, pBox->y);
pixman_region32_intersect(&inverseOpaque, &inverseOpaque, &damage);
inverseOpaque.translate({pBox->x, pBox->y}).intersect(texDamage);
POUTFB = blurMainFramebufferWithDamage(a, pBox, &inverseOpaque);
} else {
POUTFB = &m_RenderData.pCurrentMonData->blurFB;
}
pixman_region32_fini(&inverseOpaque);
// bind primary
m_RenderData.pCurrentMonData->primaryFB.bind();
@@ -1028,11 +1161,11 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
// stencil done. Render everything.
wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
// render our great blurred FB
static auto* const PBLURIGNOREOPACITY = &g_pConfigManager->getConfigValuePtr("decoration:blur_ignore_opacity")->intValue;
static auto* const PBLURIGNOREOPACITY = &g_pConfigManager->getConfigValuePtr("decoration:blur:ignore_opacity")->intValue;
m_bEndFrame = true; // fix transformed
const auto SAVEDRENDERMODIF = m_RenderData.renderModif;
m_RenderData.renderModif = {}; // fix shit
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 1.f : a, &damage, 0, false, false, false);
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 1.f : a, &texDamage, 0, false, false, false);
m_bEndFrame = false;
m_RenderData.renderModif = SAVEDRENDERMODIF;
@@ -1042,11 +1175,10 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
// draw window
glDisable(GL_STENCIL_TEST);
renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true, true);
renderTextureInternalWithDamage(tex, pBox, a, &texDamage, round, false, false, true, true);
glStencilMask(-1);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
pixman_region32_fini(&damage);
scissor((wlr_box*)nullptr);
}
@@ -1061,7 +1193,9 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad,
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()!");
if (!pixman_region32_not_empty(m_RenderData.pDamage) || (m_pCurrentWindow && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBorder))
TRACY_GPU_ZONE("RenderBorder");
if (m_RenderData.damage.empty() || (m_pCurrentWindow && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBorder))
return;
static auto* const PMULTISAMPLE = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
@@ -1133,22 +1267,17 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad,
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib);
if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) {
pixman_region32_t damageClip;
pixman_region32_init(&damageClip);
pixman_region32_intersect_rect(&damageClip, m_RenderData.pDamage, m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height);
CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height};
damageClip.intersect(m_RenderData.damage);
if (pixman_region32_not_empty(&damageClip)) {
PIXMAN_DAMAGE_FOREACH(&damageClip) {
const auto RECT = RECTSARR[i];
if (!damageClip.empty()) {
for (auto& RECT : damageClip.getRects()) {
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
pixman_region32_fini(&damageClip);
} else {
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
const auto RECT = RECTSARR[i];
for (auto& RECT : m_RenderData.damage.getRects()) {
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
@@ -1172,9 +1301,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFra
// we need to "damage" the entire monitor
// so that we render the entire window
// this is temporary, doesnt mess with the actual wlr damage
pixman_region32_t fakeDamage;
pixman_region32_init(&fakeDamage);
pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y};
begin(PMONITOR, &fakeDamage, true);
@@ -1188,8 +1315,8 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFra
// will try to copy the bg to apply blur.
// this isn't entirely correct, but like, oh well.
// small todo: maybe make this correct? :P
const auto BLURVAL = g_pConfigManager->getInt("decoration:blur");
g_pConfigManager->setInt("decoration:blur", 0);
const auto BLURVAL = g_pConfigManager->getInt("decoration:blur:enabled");
g_pConfigManager->setInt("decoration:blur:enabled", 0);
// TODO: how can we make this the size of the window? setting it to window's size makes the entire screen render with the wrong res forever more. odd.
glViewport(0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
@@ -1204,7 +1331,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFra
g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, false, RENDER_PASS_ALL, true);
g_pConfigManager->setInt("decoration:blur", BLURVAL);
g_pConfigManager->setInt("decoration:blur:enabled", BLURVAL);
// restore original fb
#ifndef GLES2
@@ -1214,8 +1341,6 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFra
#endif
end();
pixman_region32_fini(&fakeDamage);
wlr_output_rollback(PMONITOR->output);
}
@@ -1231,9 +1356,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
// we need to "damage" the entire monitor
// so that we render the entire window
// this is temporary, doesnt mess with the actual wlr damage
pixman_region32_t fakeDamage;
pixman_region32_init(&fakeDamage);
pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y};
begin(PMONITOR, &fakeDamage, true);
@@ -1249,8 +1372,8 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
// will try to copy the bg to apply blur.
// this isn't entirely correct, but like, oh well.
// small todo: maybe make this correct? :P
const auto BLURVAL = g_pConfigManager->getInt("decoration:blur");
g_pConfigManager->setInt("decoration:blur", 0);
const auto BLURVAL = g_pConfigManager->getInt("decoration:blur:enabled");
g_pConfigManager->setInt("decoration:blur:enabled", 0);
glViewport(0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y);
@@ -1266,7 +1389,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders, RENDER_PASS_ALL);
g_pConfigManager->setInt("decoration:blur", BLURVAL);
g_pConfigManager->setInt("decoration:blur:enabled", BLURVAL);
// restore original fb
#ifndef GLES2
@@ -1276,8 +1399,6 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
#endif
end();
pixman_region32_fini(&fakeDamage);
g_pHyprRenderer->m_bRenderingSnapshot = false;
wlr_output_rollback(PMONITOR->output);
@@ -1295,9 +1416,7 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
// we need to "damage" the entire monitor
// so that we render the entire window
// this is temporary, doesnt mess with the actual wlr damage
pixman_region32_t fakeDamage;
pixman_region32_init(&fakeDamage);
pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y};
begin(PMONITOR, &fakeDamage, true);
@@ -1337,8 +1456,6 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
g_pHyprRenderer->m_bRenderingSnapshot = false;
pixman_region32_fini(&fakeDamage);
wlr_output_rollback(PMONITOR->output);
}
@@ -1371,8 +1488,7 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
windowBox.x = ((PWINDOW->m_vRealPosition.vec().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - ((PWINDOW->m_vOriginalClosedPos.x * PMONITOR->scale) * scaleXY.x);
windowBox.y = ((PWINDOW->m_vRealPosition.vec().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - ((PWINDOW->m_vOriginalClosedPos.y * PMONITOR->scale) * scaleXY.y);
pixman_region32_t fakeDamage;
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y);
CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
if (*PDIMAROUND && (*pWindow)->m_sAdditionalConfigData.dimAround) {
wlr_box monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y};
@@ -1385,8 +1501,6 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
renderTextureInternalWithDamage(it->second.m_cTex, &windowBox, PWINDOW->m_fAlpha.fl(), &fakeDamage, 0);
m_bEndFrame = false;
pixman_region32_fini(&fakeDamage);
}
void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) {
@@ -1403,20 +1517,17 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) {
if (it == m_mLayerFramebuffers.end() || !it->second.m_cTex.m_iTexID)
return;
const auto PMONITOR = g_pCompositor->getMonitorFromID(PLAYER->monitorID);
const auto PMONITOR = g_pCompositor->getMonitorFromID(PLAYER->monitorID);
wlr_box monbox = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
wlr_box monbox = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
pixman_region32_t fakeDamage;
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y);
CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
m_bEndFrame = true;
renderTextureInternalWithDamage(it->second.m_cTex, &monbox, PLAYER->alpha.fl(), &fakeDamage, 0);
m_bEndFrame = false;
pixman_region32_fini(&fakeDamage);
}
void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, float a) {
@@ -1424,9 +1535,11 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!");
RASSERT(m_pCurrentWindow, "Tried to render shadow without a window!");
if (!pixman_region32_not_empty(m_RenderData.pDamage))
if (m_RenderData.damage.empty())
return;
TRACY_GPU_ZONE("RenderShadow");
wlr_box newBox = *box;
scaleBox(&newBox, m_RenderData.renderModif.scale);
newBox.x += m_RenderData.renderModif.translate.x;
@@ -1479,22 +1592,17 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib);
if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) {
pixman_region32_t damageClip;
pixman_region32_init(&damageClip);
pixman_region32_intersect_rect(&damageClip, m_RenderData.pDamage, m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height);
CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height};
damageClip.intersect(m_RenderData.damage);
if (pixman_region32_not_empty(&damageClip)) {
PIXMAN_DAMAGE_FOREACH(&damageClip) {
const auto RECT = RECTSARR[i];
if (!damageClip.empty()) {
for (auto& RECT : damageClip.getRects()) {
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
}
pixman_region32_fini(&damageClip);
} else {
PIXMAN_DAMAGE_FOREACH(m_RenderData.pDamage) {
const auto RECT = RECTSARR[i];
for (auto& RECT : m_RenderData.damage.getRects()) {
scissor(&RECT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
@@ -1507,12 +1615,20 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
}
void CHyprOpenGLImpl::saveBufferForMirror() {
if (!m_RenderData.pCurrentMonData->monitorMirrorFB.isAllocated())
m_RenderData.pCurrentMonData->monitorMirrorFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y);
m_RenderData.pCurrentMonData->monitorMirrorFB.bind();
wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y};
blend(false);
renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 1.f, 0, false, false);
blend(true);
m_RenderData.pCurrentMonData->primaryFB.bind();
}
@@ -1521,7 +1637,7 @@ void CHyprOpenGLImpl::renderMirrored() {
const auto PFB = &m_mMonitorRenderResources[m_RenderData.pMonitor->pMirrorOf].monitorMirrorFB;
if (PFB->m_cTex.m_iTexID <= 0)
if (!PFB->isAllocated() || PFB->m_cTex.m_iTexID <= 0)
return;
renderTexture(PFB->m_cTex, &monbox, 1.f, 0, false, false);
@@ -1548,13 +1664,15 @@ void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const
void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!");
static auto* const PNOSPLASH = &g_pConfigManager->getConfigValuePtr("misc:disable_splash_rendering")->intValue;
static auto* const PNOSPLASH = &g_pConfigManager->getConfigValuePtr("misc:disable_splash_rendering")->intValue;
static auto* const PFORCEHYPRCHAN = &g_pConfigManager->getConfigValuePtr("misc:force_hypr_chan")->intValue;
std::random_device dev;
std::mt19937 engine(dev());
std::uniform_int_distribution<> distribution(0, 10);
std::uniform_int_distribution<> distribution(0, 2);
std::uniform_int_distribution<> distribution2(0, 1);
const bool USEANIME = distribution(engine) % 2 == 0; // about 50% I think
const bool USEANIME = *PFORCEHYPRCHAN || distribution(engine) == 0; // 66% for anime
// release the last tex if exists
const auto PTEX = &m_mMonitorBGTextures[pMonitor];
@@ -1568,7 +1686,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
// or configure the paths at build time
// get the adequate tex
std::string texPath = "/usr/share/hyprland/wall_" + std::string(USEANIME ? "anime_" : "");
std::string texPath = "/usr/share/hyprland/wall_" + std::string(USEANIME ? (distribution2(engine) == 0 ? "anime_" : "anime2_") : "");
// check if wallpapers exist
Vector2D textureSize;
@@ -1645,19 +1763,17 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) {
void CHyprOpenGLImpl::clearWithTex() {
RASSERT(m_RenderData.pMonitor, "Tried to render BGtex without begin()!");
static auto* const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue;
TRACY_GPU_ZONE("RenderClearWithTex");
if (!*PRENDERTEX) {
auto TEXIT = m_mMonitorBGTextures.find(m_RenderData.pMonitor);
auto TEXIT = m_mMonitorBGTextures.find(m_RenderData.pMonitor);
if (TEXIT == m_mMonitorBGTextures.end()) {
createBGTextureForMonitor(m_RenderData.pMonitor);
TEXIT = m_mMonitorBGTextures.find(m_RenderData.pMonitor);
}
if (TEXIT != m_mMonitorBGTextures.end())
renderTexture(TEXIT->second, &m_mMonitorRenderResources[m_RenderData.pMonitor].backgroundTexBox, 1.0, 0);
if (TEXIT == m_mMonitorBGTextures.end()) {
createBGTextureForMonitor(m_RenderData.pMonitor);
TEXIT = m_mMonitorBGTextures.find(m_RenderData.pMonitor);
}
if (TEXIT != m_mMonitorBGTextures.end())
renderTexturePrimitive(TEXIT->second, &m_mMonitorRenderResources[m_RenderData.pMonitor].backgroundTexBox);
}
void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) {

View File

@@ -4,6 +4,7 @@
#include "../helpers/Monitor.hpp"
#include "../helpers/Color.hpp"
#include "../helpers/Timer.hpp"
#include "../helpers/Region.hpp"
#include <list>
#include <unordered_map>
@@ -13,6 +14,8 @@
#include "Texture.hpp"
#include "Framebuffer.hpp"
#include "../debug/TracyDefines.hpp"
class CHyprRenderer;
inline const float fullVerts[] = {
@@ -23,7 +26,8 @@ inline const float fullVerts[] = {
};
inline const float fanVertsFull[] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f};
enum eDiscardMode {
enum eDiscardMode
{
DISCARD_OPAQUE = 1,
DISCARD_ALPHA = 1 << 1
};
@@ -35,8 +39,8 @@ struct SRenderModifData {
struct SMonitorRenderData {
CFramebuffer primaryFB;
CFramebuffer mirrorFB; // these are used for some effects,
CFramebuffer mirrorSwapFB; // etc
CFramebuffer mirrorFB; // these are used for some effects,
CFramebuffer mirrorSwapFB; // etc
CFramebuffer monitorMirrorFB; // used for mirroring outputs
@@ -57,6 +61,7 @@ struct SMonitorRenderData {
CShader m_shEXT;
CShader m_shBLUR1;
CShader m_shBLUR2;
CShader m_shBLURFINISH;
CShader m_shSHADOW;
CShader m_shBORDER1;
CShader m_shGLITCH;
@@ -71,7 +76,7 @@ struct SCurrentRenderData {
SMonitorRenderData* pCurrentMonData = nullptr;
pixman_region32_t* pDamage = nullptr;
CRegion damage;
SRenderModifData renderModif;
float mouseZoomFactor = 1.f;
@@ -93,11 +98,12 @@ class CHyprOpenGLImpl {
public:
CHyprOpenGLImpl();
void begin(CMonitor*, pixman_region32_t*, bool fake = false);
void begin(CMonitor*, CRegion*, bool fake = false);
void end();
void bindWlrOutputFb();
void renderRect(wlr_box*, const CColor&, int round = 0);
void renderRectWithDamage(wlr_box*, const CColor&, pixman_region32_t* damage, int round = 0);
void renderRectWithDamage(wlr_box*, const CColor&, CRegion* damage, int round = 0);
void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0, bool allowCustomUV = false);
void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false);
@@ -108,6 +114,8 @@ class CHyprOpenGLImpl {
void setMatrixScaleTranslate(const Vector2D& translate, const float& scale);
void restoreMatrix();
void blend(bool enabled);
void makeWindowSnapshot(CWindow*);
void makeRawWindowSnapshot(CWindow*, CFramebuffer*);
void makeLayerSnapshot(SLayerSurface*);
@@ -125,6 +133,7 @@ class CHyprOpenGLImpl {
void markBlurDirtyForMonitor(CMonitor*);
void preWindowPass();
bool preBlurQueued();
void preRender(CMonitor*);
void saveBufferForMirror();
@@ -139,7 +148,7 @@ class CHyprOpenGLImpl {
bool m_bReloadScreenShader = true; // at launch it can be set
CWindow* m_pCurrentWindow = nullptr; // hack to get the current rendered window
CWindow* m_pCurrentWindow = nullptr; // hack to get the current rendered window
std::unordered_map<CWindow*, CFramebuffer> m_mWindowFramebuffers;
std::unordered_map<SLayerSurface*, CFramebuffer> m_mLayerFramebuffers;
@@ -156,6 +165,7 @@ class CHyprOpenGLImpl {
bool m_bFakeFrame = false;
bool m_bEndFrame = false;
bool m_bApplyFinalShader = false;
bool m_bBlend = false;
CShader m_sFinalScreenShader;
CTimer m_tGlobalTimer;
@@ -166,10 +176,11 @@ class CHyprOpenGLImpl {
void initShaders();
// returns the out FB, can be either Mirror or MirrorSwap
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage);
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, CRegion* damage);
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false,
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false,
bool allowCustomUV = false, bool allowDim = false);
void renderTexturePrimitive(const CTexture& tex, wlr_box* pBox);
void renderSplash(cairo_t* const, cairo_surface_t* const, double);
void preBlurForCurrentMonitor();

View File

@@ -1,6 +1,7 @@
#include "Renderer.hpp"
#include "../Compositor.hpp"
#include "linux-dmabuf-unstable-v1-protocol.h"
#include "../helpers/Region.hpp"
void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
const auto TEXTURE = wlr_surface_get_texture(surface);
@@ -9,6 +10,8 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
if (!TEXTURE)
return;
TRACY_GPU_ZONE("RenderSurface");
double outputX = 0, outputY = 0;
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, RDATA->pMonitor->output, &outputX, &outputY);
@@ -35,13 +38,17 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
scaleBox(&windowBox, RDATA->pMonitor->scale);
static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? *PROUNDING : RDATA->rounding;
rounding *= RDATA->pMonitor->scale;
float rounding = RDATA->rounding;
rounding -= 1; // to fix a border issue
const bool CANDISABLEBLEND = RDATA->alpha >= 1.f && rounding == 0 && surface->opaque;
if (CANDISABLEBLEND)
g_pHyprOpenGL->blend(false);
else
g_pHyprOpenGL->blend(true);
if (RDATA->surface && surface == RDATA->surface) {
if (wlr_xwayland_surface_try_from_wlr_surface(surface) && !wlr_xwayland_surface_try_from_wlr_surface(surface)->has_alpha && RDATA->fadeAlpha * RDATA->alpha == 1.f) {
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true);
@@ -60,6 +67,8 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
wlr_presentation_surface_textured_on_output(g_pCompositor->m_sWLRPresentation, surface, RDATA->pMonitor->output);
}
g_pHyprOpenGL->blend(true);
// reset the UV, we might've set it above
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
@@ -250,6 +259,8 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
return;
}
TRACY_GPU_ZONE("RenderWindow");
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
const auto REALPOS = pWindow->m_vRealPosition.vec() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.vec());
static auto* const PNOFLOATINGBORDERS = &g_pConfigManager->getConfigValuePtr("general:no_border_on_floating")->intValue;
@@ -273,7 +284,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
renderdata.alpha = pWindow->m_fActiveInactiveAlpha.fl();
renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (pWindow->m_bIsFloating ? *PNOFLOATINGBORDERS == 0 : true) &&
(!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL);
renderdata.rounding = ignoreAllGeometry ? 0 : pWindow->m_sAdditionalConfigData.rounding.toUnderlying();
renderdata.rounding = ignoreAllGeometry || renderdata.dontRound ? 0 : pWindow->rounding() * pMonitor->scale;
renderdata.blur = !ignoreAllGeometry; // if it shouldn't, it will be ignored later
renderdata.pWindow = pWindow;
@@ -339,11 +350,6 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false;
if (renderdata.decorate && pWindow->m_sSpecialRenderData.border) {
static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
float rounding = renderdata.dontRound ? 0 : renderdata.rounding == -1 ? *PROUNDING : renderdata.rounding;
rounding *= pMonitor->scale;
auto grad = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor;
const bool ANIMATED = g_pHyprOpenGL->m_pCurrentWindow->m_fBorderFadeAnimationProgress.isBeingAnimated();
float a1 = renderdata.fadeAlpha * renderdata.alpha * (ANIMATED ? g_pHyprOpenGL->m_pCurrentWindow->m_fBorderFadeAnimationProgress.fl() : 1.f);
@@ -361,11 +367,11 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
if (pWindow->m_sAdditionalConfigData.borderSize.toUnderlying() != -1)
borderSize = pWindow->m_sAdditionalConfigData.borderSize.toUnderlying();
g_pHyprOpenGL->renderBorder(&windowBox, grad, rounding, borderSize, a1);
g_pHyprOpenGL->renderBorder(&windowBox, grad, renderdata.rounding, borderSize, a1);
if (ANIMATED) {
float a2 = renderdata.fadeAlpha * renderdata.alpha * (1.f - g_pHyprOpenGL->m_pCurrentWindow->m_fBorderFadeAnimationProgress.fl());
g_pHyprOpenGL->renderBorder(&windowBox, g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColorPrevious, rounding, borderSize, a2);
g_pHyprOpenGL->renderBorder(&windowBox, g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColorPrevious, renderdata.rounding, borderSize, a2);
}
}
}
@@ -397,6 +403,8 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, times
return;
}
TRACY_GPU_ZONE("RenderLayer");
SRenderData renderdata = {pMonitor, time, pLayer->geometry.x, pLayer->geometry.y};
renderdata.fadeAlpha = pLayer->alpha.fl();
renderdata.blur = pLayer->forceBlur;
@@ -462,18 +470,27 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace*
// g_pHyprOpenGL->setMatrixScaleTranslate(translate, scale);
g_pHyprOpenGL->m_RenderData.renderModif = RENDERMODIFDATA;
// for storing damage when we optimize for occlusion
CRegion preOccludedDamage{g_pHyprOpenGL->m_RenderData.damage};
// Render layer surfaces below windows for monitor
// if we have a fullscreen, opaque window that convers the screen, we can skip this.
// TODO: check better with solitary after MR for tearing.
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID);
if (!pWorkspace->m_bHasFullscreenWindow || pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL || !PFULLWINDOW || PFULLWINDOW->m_vRealSize.isBeingAnimated() ||
!PFULLWINDOW->opaque() || pWorkspace->m_vRenderOffset.isBeingAnimated() || PFULLWINDOW->m_fAlpha.fl() != 1.f || PFULLWINDOW->m_fActiveInactiveAlpha.fl() != 1.f) {
!PFULLWINDOW->opaque() || pWorkspace->m_vRenderOffset.vec() != Vector2D{}) {
if (!g_pHyprOpenGL->preBlurQueued())
setOccludedForBackLayers(g_pHyprOpenGL->m_RenderData.damage, pWorkspace);
for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) {
renderLayer(ls.get(), pMonitor, time);
}
for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) {
renderLayer(ls.get(), pMonitor, time);
}
g_pHyprOpenGL->m_RenderData.damage = preOccludedDamage;
}
// pre window pass
@@ -628,6 +645,8 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace*
}
void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now) {
TRACY_GPU_ZONE("RenderLockscreen");
if (g_pSessionLockManager->isSessionLocked()) {
const auto PSLS = g_pSessionLockManager->getSessionLockSurfaceForMonitor(pMonitor->ID);
@@ -805,6 +824,8 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
static auto* const PNODIRECTSCANOUT = &g_pConfigManager->getConfigValuePtr("misc:no_direct_scanout")->intValue;
static auto* const PVFR = &g_pConfigManager->getConfigValuePtr("misc:vfr")->intValue;
static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue;
static auto* const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue;
static auto* const PANIMENABLED = &g_pConfigManager->getConfigValuePtr("animations:enabled")->intValue;
static int damageBlinkCleanup = 0; // because double-buffered
@@ -822,8 +843,13 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
}
if (m_tRenderTimer.getSeconds() < 1.5f && firstLaunchAnimActive) { // TODO: make the animation system more damage-flexible so that this can be migrated to there
zoomInFactorFirstLaunch = 2.f - g_pAnimationManager->getBezier("default")->getYForPoint(m_tRenderTimer.getSeconds() / 1.5);
damageMonitor(pMonitor);
if (!*PANIMENABLED) {
zoomInFactorFirstLaunch = 1.f;
firstLaunchAnimActive = false;
} else {
zoomInFactorFirstLaunch = 2.f - g_pAnimationManager->getBezier("default")->getYForPoint(m_tRenderTimer.getSeconds() / 1.5);
damageMonitor(pMonitor);
}
} else {
firstLaunchAnimActive = false;
}
@@ -902,9 +928,9 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
clock_gettime(CLOCK_MONOTONIC, &now);
// check the damage
pixman_region32_t damage;
bool hasChanged = pMonitor->output->needs_frame || pixman_region32_not_empty(&pMonitor->damage.current);
int bufferAge;
CRegion damage;
bool hasChanged = pMonitor->output->needs_frame || pixman_region32_not_empty(&pMonitor->damage.current);
int bufferAge;
if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->forceFullFrames == 0 && damageBlinkCleanup == 0)
return;
@@ -929,8 +955,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
return;
}
pixman_region32_init(&damage);
wlr_damage_ring_get_buffer_damage(&pMonitor->damage, bufferAge, &damage);
wlr_damage_ring_get_buffer_damage(&pMonitor->damage, bufferAge, damage.pixman());
pMonitor->renderingActive = true;
@@ -940,28 +965,28 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
// if we have no tracking or full tracking, invalidate the entire monitor
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || pMonitor->forceFullFrames > 0 || damageBlinkCleanup > 0 ||
pMonitor->isMirror() /* why??? */) {
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)pMonitor->vecTransformedSize.x * 10, (int)pMonitor->vecTransformedSize.y * 10); // wot?
pixman_region32_copy(&pMonitor->lastFrameDamage, &damage);
damage = {0, 0, (int)pMonitor->vecTransformedSize.x * 10, (int)pMonitor->vecTransformedSize.y * 10};
pMonitor->lastFrameDamage = damage;
} else {
static auto* const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
static auto* const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue;
// if we use blur we need to expand the damage for proper blurring
if (*PBLURENABLED == 1) {
// TODO: can this be optimized?
static auto* const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_size")->intValue;
static auto* const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur_passes")->intValue;
static auto* const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur:size")->intValue;
static auto* const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur:passes")->intValue;
const auto BLURRADIUS =
*PBLURPASSES > 10 ? pow(2, 15) : std::clamp(*PBLURSIZE, (int64_t)1, (int64_t)40) * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think.
// now, prep the damage, get the extended damage region
wlr_region_expand(&damage, &damage, BLURRADIUS); // expand for proper blurring
wlr_region_expand(damage.pixman(), damage.pixman(), BLURRADIUS); // expand for proper blurring
pixman_region32_copy(&pMonitor->lastFrameDamage, &damage);
pMonitor->lastFrameDamage = damage;
wlr_region_expand(&damage, &damage, BLURRADIUS); // expand for proper blurring 2
wlr_region_expand(damage.pixman(), damage.pixman(), BLURRADIUS); // expand for proper blurring 2
} else {
pixman_region32_copy(&pMonitor->lastFrameDamage, &damage);
pMonitor->lastFrameDamage = damage;
}
}
@@ -974,16 +999,26 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
// TODO: this is getting called with extents being 0,0,0,0 should it be?
// potentially can save on resources.
TRACY_GPU_ZONE("Render");
g_pHyprOpenGL->begin(pMonitor, &damage);
EMIT_HOOK_EVENT("render", RENDER_BEGIN);
if (pMonitor->isMirror()) {
g_pHyprOpenGL->blend(false);
g_pHyprOpenGL->renderMirrored();
g_pHyprOpenGL->blend(true);
EMIT_HOOK_EVENT("render", RENDER_POST_MIRROR);
} else {
g_pHyprOpenGL->clear(CColor(17.0 / 255.0, 17.0 / 255.0, 17.0 / 255.0, 1.0));
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
g_pHyprOpenGL->blend(false);
if (!canSkipBackBufferClear(pMonitor)) {
if (*PRENDERTEX /* inverted cfg flag */)
g_pHyprOpenGL->clear(CColor(17.0 / 255.0, 17.0 / 255.0, 17.0 / 255.0, 1.0));
else
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
}
g_pHyprOpenGL->blend(true);
wlr_box renderBox = {0, 0, (int)pMonitor->vecPixelSize.x, (int)pMonitor->vecPixelSize.y};
renderWorkspace(pMonitor, g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace), &now, renderBox);
@@ -1013,6 +1048,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
}
if (wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y)) {
TRACY_GPU_ZONE("RenderCursor");
if (pMonitor == g_pCompositor->getMonitorFromCursor() && *PZOOMFACTOR != 1.f) {
wlr_output_lock_software_cursors(pMonitor->output, true);
wlr_output_render_software_cursors(pMonitor->output, NULL);
@@ -1038,43 +1074,37 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
g_pHyprOpenGL->end();
TRACY_GPU_COLLECT;
// calc frame damage
pixman_region32_t frameDamage;
pixman_region32_init(&frameDamage);
CRegion frameDamage{};
const auto TRANSFORM = wlr_output_transform_invert(pMonitor->output->transform);
wlr_region_transform(&frameDamage, &pMonitor->lastFrameDamage, TRANSFORM, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y);
wlr_region_transform(frameDamage.pixman(), pMonitor->lastFrameDamage.pixman(), TRANSFORM, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y);
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR)
pixman_region32_union_rect(&frameDamage, &frameDamage, 0, 0, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y);
frameDamage.add(0, 0, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y);
if (*PDAMAGEBLINK)
pixman_region32_union(&frameDamage, &frameDamage, &damage);
frameDamage.add(damage);
wlr_output_set_damage(pMonitor->output, &frameDamage);
//wlr_output_set_damage(pMonitor->output, frameDamage.pixman());
if (!pMonitor->mirrors.empty())
g_pHyprRenderer->damageMirrorsWith(pMonitor, &frameDamage);
pixman_region32_fini(&frameDamage);
g_pHyprRenderer->damageMirrorsWith(pMonitor, frameDamage);
pMonitor->renderingActive = false;
EMIT_HOOK_EVENT("render", RENDER_POST);
wlr_damage_ring_rotate(&pMonitor->damage);
if (!wlr_output_commit(pMonitor->output)) {
pixman_region32_fini(&damage);
if (UNLOCK_SC)
wlr_output_lock_software_cursors(pMonitor->output, false);
return;
}
g_pProtocolManager->m_pScreencopyProtocolManager->onRenderEnd(pMonitor);
pixman_region32_fini(&damage);
wlr_damage_ring_rotate(&pMonitor->damage);
if (UNLOCK_SC)
wlr_output_lock_software_cursors(pMonitor->output, false);
@@ -1101,6 +1131,8 @@ void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace,
Vector2D translate = {geometry.x, geometry.y};
float scale = (float)geometry.width / pMonitor->vecPixelSize.x;
TRACY_GPU_ZONE("RenderWorkspace");
if (!DELTALESSTHAN((double)geometry.width / (double)geometry.height, pMonitor->vecPixelSize.x / pMonitor->vecPixelSize.y, 0.01)) {
Debug::log(ERR, "Ignoring geometry in renderWorkspace: aspect ratio mismatch");
scale = 1.f;
@@ -1388,24 +1420,20 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y, dou
if (g_pCompositor->m_bUnsafeState)
return;
pixman_region32_t damageBox;
pixman_region32_init(&damageBox);
wlr_surface_get_effective_damage(pSurface, &damageBox);
CRegion damageBox;
wlr_surface_get_effective_damage(pSurface, damageBox.pixman());
if (scale != 1.0)
wlr_region_scale(&damageBox, &damageBox, scale);
wlr_region_scale(damageBox.pixman(), damageBox.pixman(), scale);
// schedule frame events
if (!wl_list_empty(&pSurface->current.frame_callback_list)) {
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->getMonitorFromVector(Vector2D(x, y)));
}
if (!pixman_region32_not_empty(&damageBox)) {
pixman_region32_fini(&damageBox);
if (damageBox.empty())
return;
}
pixman_region32_t damageBoxForEach;
pixman_region32_init(&damageBoxForEach);
CRegion damageBoxForEach;
for (auto& m : g_pCompositor->m_vMonitors) {
if (!m->output)
@@ -1414,23 +1442,19 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y, dou
double lx = 0, ly = 0;
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, m->output, &lx, &ly);
pixman_region32_copy(&damageBoxForEach, &damageBox);
pixman_region32_translate(&damageBoxForEach, x - m->vecPosition.x, y - m->vecPosition.y);
wlr_region_scale(&damageBoxForEach, &damageBoxForEach, m->scale);
pixman_region32_translate(&damageBoxForEach, lx + m->vecPosition.x, ly + m->vecPosition.y);
damageBoxForEach = damageBox;
damageBoxForEach.translate({x - m->vecPosition.x, y - m->vecPosition.y});
wlr_region_scale(damageBoxForEach.pixman(), damageBoxForEach.pixman(), m->scale);
damageBoxForEach.translate({lx + m->vecPosition.x, ly + m->vecPosition.y});
m->addDamage(&damageBoxForEach);
}
pixman_region32_fini(&damageBoxForEach);
static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
if (*PLOGDAMAGE)
Debug::log(LOG, "Damage: Surface (extents): xy: %d, %d wh: %d, %d", damageBox.extents.x1, damageBox.extents.y1, damageBox.extents.x2 - damageBox.extents.x1,
damageBox.extents.y2 - damageBox.extents.y1);
pixman_region32_fini(&damageBox);
Debug::log(LOG, "Damage: Surface (extents): xy: %d, %d wh: %d, %d", damageBox.pixman()->extents.x1, damageBox.pixman()->extents.y1,
damageBox.pixman()->extents.x2 - damageBox.pixman()->extents.x1, damageBox.pixman()->extents.y2 - damageBox.pixman()->extents.y1);
}
void CHyprRenderer::damageWindow(CWindow* pWindow) {
@@ -1490,23 +1514,19 @@ void CHyprRenderer::damageBox(const int& x, const int& y, const int& w, const in
damageBox(&box);
}
void CHyprRenderer::damageRegion(pixman_region32_t* rg) {
PIXMAN_DAMAGE_FOREACH(rg) {
const auto RECT = RECTSARR[i];
void CHyprRenderer::damageRegion(const CRegion& rg) {
for (auto& RECT : rg.getRects()) {
damageBox(RECT.x1, RECT.y1, RECT.x2 - RECT.x1, RECT.y2 - RECT.y1);
}
}
void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, pixman_region32_t* pRegion) {
void CHyprRenderer::damageMirrorsWith(CMonitor* pMonitor, const CRegion& pRegion) {
for (auto& mirror : pMonitor->mirrors) {
Vector2D scale = {mirror->vecSize.x / pMonitor->vecSize.x, mirror->vecSize.y / pMonitor->vecSize.y};
Vector2D scale = {mirror->vecSize.x / pMonitor->vecSize.x, mirror->vecSize.y / pMonitor->vecSize.y};
pixman_region32_t rg;
pixman_region32_init(&rg);
pixman_region32_copy(&rg, pRegion);
wlr_region_scale_xy(&rg, &rg, scale.x, scale.y);
CRegion rg{pRegion};
wlr_region_scale_xy(rg.pixman(), rg.pixman(), scale.x, scale.y);
pMonitor->addDamage(&rg);
pixman_region32_fini(&rg);
g_pCompositor->scheduleFrameForMonitor(mirror);
}
@@ -1588,6 +1608,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
wlr_output_set_transform(pMonitor->output, pMonitorRule->transform);
pMonitor->transform = pMonitorRule->transform;
const auto WLRREFRESHRATE = (wlr_backend_is_wl(pMonitor->output->backend) || wlr_backend_is_x11(pMonitor->output->backend)) ? 0 : pMonitorRule->refreshRate * 1000;
// loop over modes and choose an appropriate one.
if (pMonitorRule->resolution != Vector2D() && pMonitorRule->resolution != Vector2D(-1, -1) && pMonitorRule->resolution != Vector2D(-1, -2)) {
if (!wl_list_empty(&pMonitor->output->modes) && pMonitorRule->drmMode.type != DRM_MODE_TYPE_USERDEF) {
@@ -1619,7 +1641,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
}
if (!found) {
wlr_output_set_custom_mode(pMonitor->output, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (int)pMonitorRule->refreshRate * 1000);
wlr_output_set_custom_mode(pMonitor->output, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, WLRREFRESHRATE);
pMonitor->vecSize = pMonitorRule->resolution;
pMonitor->refreshRate = pMonitorRule->refreshRate;
@@ -1667,7 +1689,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
}
}
} else {
wlr_output_set_custom_mode(pMonitor->output, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (int)pMonitorRule->refreshRate * 1000);
wlr_output_set_custom_mode(pMonitor->output, (int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, WLRREFRESHRATE);
}
pMonitor->vecSize = pMonitorRule->resolution;
@@ -1980,3 +2002,50 @@ void CHyprRenderer::initiateManualCrash() {
g_pConfigManager->setInt("debug:damage_tracking", 0);
}
void CHyprRenderer::setOccludedForBackLayers(CRegion& region, CWorkspace* pWorkspace) {
CRegion rg;
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID);
for (auto& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped || w->isHidden() || w->m_iWorkspaceID != pWorkspace->m_iID)
continue;
if (!w->opaque())
continue;
const auto ROUNDING = w->rounding() * PMONITOR->scale;
const Vector2D POS = w->m_vRealPosition.vec() + Vector2D{ROUNDING, ROUNDING} - PMONITOR->vecPosition + pWorkspace->m_vRenderOffset.vec();
const Vector2D SIZE = w->m_vRealSize.vec() - Vector2D{ROUNDING * 2, ROUNDING * 2};
wlr_box box = {POS.x, POS.y, SIZE.x, SIZE.y};
scaleBox(&box, PMONITOR->scale);
rg.add(&box);
}
region.subtract(rg);
}
bool CHyprRenderer::canSkipBackBufferClear(CMonitor* pMonitor) {
for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) {
if (!ls->layerSurface)
continue;
if (ls->alpha.fl() < 1.f)
continue;
if (ls->geometry.x != pMonitor->vecPosition.x || ls->geometry.y != pMonitor->vecPosition.y || ls->geometry.width != pMonitor->vecSize.x ||
ls->geometry.height != pMonitor->vecSize.y)
continue;
if (!ls->layerSurface->surface->opaque)
continue;
return true;
}
return false;
}

View File

@@ -7,18 +7,21 @@
#include "../Window.hpp"
#include "OpenGL.hpp"
#include "../helpers/Timer.hpp"
#include "../helpers/Region.hpp"
struct SMonitorRule;
// TODO: add fuller damage tracking for updating only parts of a window
enum DAMAGETRACKINGMODES {
enum DAMAGETRACKINGMODES
{
DAMAGE_TRACKING_INVALID = -1,
DAMAGE_TRACKING_NONE = 0,
DAMAGE_TRACKING_MONITOR,
DAMAGE_TRACKING_FULL
};
enum eRenderPassMode {
enum eRenderPassMode
{
RENDER_PASS_ALL = 0,
RENDER_PASS_MAIN,
RENDER_PASS_POPUP
@@ -37,9 +40,9 @@ class CHyprRenderer {
void damageWindow(CWindow*);
void damageBox(wlr_box*);
void damageBox(const int& x, const int& y, const int& w, const int& h);
void damageRegion(pixman_region32_t*);
void damageRegion(const CRegion&);
void damageMonitor(CMonitor*);
void damageMirrorsWith(CMonitor*, pixman_region32_t*);
void damageMirrorsWith(CMonitor*, const CRegion&);
bool applyMonitorRule(CMonitor*, SMonitorRule*, bool force = false);
bool shouldRenderWindow(CWindow*, CMonitor*, CWorkspace*);
bool shouldRenderWindow(CWindow*);
@@ -48,6 +51,8 @@ class CHyprRenderer {
void calculateUVForSurface(CWindow*, wlr_surface*, bool main = false);
std::tuple<float, float, float> getRenderTimes(CMonitor* pMonitor); // avg max min
void renderLockscreen(CMonitor* pMonitor, timespec* now);
void setOccludedForBackLayers(CRegion& region, CWorkspace* pWorkspace);
bool canSkipBackBufferClear(CMonitor* pMonitor);
bool m_bWindowRequestedCursorHide = false;
bool m_bBlockSurfaceFeedback = false;

View File

@@ -43,6 +43,10 @@ class CShader {
GLint distort = -1;
GLint output = -1;
GLint noise = -1;
GLint contrast = -1;
GLint brightness = -1;
GLint getUniformLocation(const std::string&);
void destroy();

View File

@@ -41,7 +41,16 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
// we draw 3px above the window's border with 3px
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
m_seExtents.topLeft = Vector2D(0, *PBORDERSIZE + BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2);
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID));
auto borderSize = pWindow->m_sSpecialRenderData.borderSize.toUnderlying() != -1 ? pWindow->m_sSpecialRenderData.borderSize.toUnderlying() :
WORKSPACERULE.borderSize.value_or(*PBORDERSIZE);
if (pWindow->m_sAdditionalConfigData.borderSize.toUnderlying() != -1)
borderSize = pWindow->m_sAdditionalConfigData.borderSize.toUnderlying();
borderSize *= pWindow->m_sSpecialRenderData.border && !pWindow->m_sAdditionalConfigData.forceNoBorder;
m_seExtents.topLeft = Vector2D(0, borderSize + BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2);
m_seExtents.bottomRight = Vector2D();
m_vLastWindowPos = pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET;
@@ -93,8 +102,14 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D&
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("misc:groupbar_gradients")->intValue;
if (barsToDraw < 1 || m_pWindow->isHidden() || !g_pCompositor->windowValidMapped(m_pWindow))
return;
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(m_pWindow->m_iWorkspaceID));
auto borderSize = m_pWindow->m_sSpecialRenderData.borderSize.toUnderlying() != -1 ? m_pWindow->m_sSpecialRenderData.borderSize.toUnderlying() :
WORKSPACERULE.borderSize.value_or(*PBORDERSIZE);
if (m_pWindow->m_sAdditionalConfigData.borderSize.toUnderlying() != -1)
borderSize = m_pWindow->m_sAdditionalConfigData.borderSize.toUnderlying();
borderSize *= m_pWindow->m_sSpecialRenderData.border && !m_pWindow->m_sAdditionalConfigData.forceNoBorder;
if (!m_pWindow->m_sSpecialRenderData.decorate)
return;
@@ -107,7 +122,7 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D&
for (int i = 0; i < barsToDraw; ++i) {
wlr_box rect = {m_vLastWindowPos.x + xoff - pMonitor->vecPosition.x + offset.x,
m_vLastWindowPos.y - BAR_PADDING_OUTER_VERT - *PBORDERSIZE - BAR_INDICATOR_HEIGHT - pMonitor->vecPosition.y + offset.y, BARW, BAR_INDICATOR_HEIGHT};
m_vLastWindowPos.y - BAR_PADDING_OUTER_VERT - borderSize - BAR_INDICATOR_HEIGHT - pMonitor->vecPosition.y + offset.y, BARW, BAR_INDICATOR_HEIGHT};
if (rect.width <= 0 || rect.height <= 0)
break;
@@ -306,4 +321,4 @@ void CHyprGroupBarDecoration::refreshGradients() {
renderGradientTo(m_tGradientActive, ((CGradientValueData*)PCOLACTIVE->get())->m_vColors[0]);
renderGradientTo(m_tGradientInactive, ((CGradientValueData*)PCOLINACTIVE->get())->m_vColors[0]);
}
}

View File

@@ -120,8 +120,10 @@ void main() {
pixColor[2] = pixColor[2] * tint[2];
}
if (radius > 0.0) {
)#" +
ROUNDED_SHADER_FUNC("pixColor") + R"#(
}
gl_FragColor = pixColor * alpha;
})#";
@@ -167,8 +169,10 @@ void main() {
pixColor[2] = pixColor[2] * tint[2];
}
if (radius > 0.0) {
)#" +
ROUNDED_SHADER_FUNC("pixColor") + R"#(
}
gl_FragColor = pixColor * alpha;
})#";
@@ -221,6 +225,36 @@ void main() {
}
)#";
inline const std::string FRAGBLURFINISH = R"#(
precision mediump float;
varying vec2 v_texcoord; // is in 0-1
uniform sampler2D tex;
uniform float contrast;
uniform float noise;
uniform float brightness;
float hash(vec2 p) {
return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453);
}
void main() {
vec4 pixColor = texture2D(tex, v_texcoord);
// contrast
pixColor.rgb = (pixColor.rgb - 0.5) * contrast + 0.5;
// brightness
pixColor.rgb *= brightness;
// noise
float noiseHash = hash(v_texcoord);
float noiseAmount = (mod(noiseHash, 1.0) - 0.5);
pixColor.rgb += noiseAmount * noise;
gl_FragColor = pixColor;
})#";
inline const std::string TEXFRAGSRCEXT = R"#(
#extension GL_OES_EGL_image_external : require
@@ -255,8 +289,10 @@ void main() {
pixColor[2] = pixColor[2] * tint[2];
}
if (radius > 0.0) {
)#" +
ROUNDED_SHADER_FUNC("pixColor") + R"#(
}
gl_FragColor = pixColor * alpha;
}

1
subprojects/tracy Submodule

Submodule subprojects/tracy added at 897aec5b06

View File

@@ -1,7 +1,7 @@
[wrap-git]
directory = wlroots
url = https://gitlab.freedesktop.org/wlroots/wlroots.git
revision = 7791ffe0584c4ac13c170e1661ce33bdbd4a9b9e
revision = e8d545a9770a2473db32e0a0bfa757b05d2af4f3
depth = 1
diff_files = wlroots-meson-build.patch