mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-07-27 18:21:54 -07:00
Compare commits
77 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
9654749244 | ||
|
da46e01b97 | ||
|
d96f8ff0fe | ||
|
5c50fac907 | ||
|
51cda87fe4 | ||
|
da0c74cdf0 | ||
|
08651736ad | ||
|
bf0d8ab4a3 | ||
|
a805905a49 | ||
|
f61a714320 | ||
|
77818e3457 | ||
|
2ea7d10d04 | ||
|
ef26f711c9 | ||
|
c36c30c17b | ||
|
a9b8e2159c | ||
|
4173d2ccf6 | ||
|
427321c5ab | ||
|
f5913135c6 | ||
|
76d4a50af3 | ||
|
603de16f9a | ||
|
f6b340cc19 | ||
|
76c6e09e39 | ||
|
9bad2a8180 | ||
|
6db3c4ef5e | ||
|
2bbe3aa122 | ||
|
9fc5f4c48b | ||
|
50e6f368ff | ||
|
975c4175b2 | ||
|
af395a8f55 | ||
|
90f69782ee | ||
|
5a64c73e05 | ||
|
9845f99b60 | ||
|
d3bba2489d | ||
|
b21644b611 | ||
|
b70553cf46 | ||
|
1a7fb1572a | ||
|
375e8385ee | ||
|
27dd07f1b8 | ||
|
263b9c6e39 | ||
|
d7e9eb65e2 | ||
|
0af97636fa | ||
|
1ec0b7b59a | ||
|
f864b15427 | ||
|
61dc0909ae | ||
|
ca54ceff6f | ||
|
6c1f4faff2 | ||
|
7940f779e9 | ||
|
a3f6a72a51 | ||
|
d2a8b8c2de | ||
|
833d73df09 | ||
|
23eda1411b | ||
|
ff598b0827 | ||
|
e5dd133808 | ||
|
a3e1e5e8ba | ||
|
a921c5b89e | ||
|
948855a984 | ||
|
547305c7ed | ||
|
b65adf8d4a | ||
|
3a1496b4eb | ||
|
a58b70ca07 | ||
|
91e3c654d3 | ||
|
7091d4e597 | ||
|
80cd2ef3d7 | ||
|
2c2314faa0 | ||
|
88c2a02773 | ||
|
89b87158db | ||
|
ce9896204a | ||
|
f4f0f35c5b | ||
|
b08b72358a | ||
|
aac75ddcbf | ||
|
5cd5631fb2 | ||
|
b8a7b09092 | ||
|
81f4a4f471 | ||
|
2623364dbd | ||
|
3b03597784 | ||
|
ce9c5fd722 | ||
|
f2999e84b9 |
1
.github/ISSUE_TEMPLATE/bug.yml
vendored
1
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -1,5 +1,6 @@
|
||||
name: Bug Report
|
||||
description: Something is not working right
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
1
.github/ISSUE_TEMPLATE/feature.yml
vendored
1
.github/ISSUE_TEMPLATE/feature.yml
vendored
@@ -1,5 +1,6 @@
|
||||
name: Feature Request
|
||||
description: I'd like to request additional functionality
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -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
|
||||
|
@@ -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)
|
||||
|
7
Makefile
7
Makefile
@@ -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
|
||||
|
@@ -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
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
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
BIN
assets/wall_anime2_8K.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 MiB |
@@ -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
13
flake.lock
generated
@@ -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"
|
||||
}
|
||||
},
|
||||
|
@@ -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
|
||||
|
@@ -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 = ''
|
||||
|
@@ -11,6 +11,8 @@ self: {
|
||||
inherit (cfg) nvidiaPatches;
|
||||
};
|
||||
in {
|
||||
disabledModules = ["services/window-managers/hyprland.nix"];
|
||||
|
||||
meta.maintainers = [lib.maintainers.fufexan];
|
||||
|
||||
options.wayland.windowManager.hyprland = {
|
||||
|
@@ -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 = {
|
||||
|
@@ -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"];
|
||||
});
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"version": "0.27.1"
|
||||
"version": "0.28.0"
|
||||
}
|
@@ -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'],
|
||||
|
@@ -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");
|
||||
|
@@ -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();
|
||||
|
135
src/Window.cpp
135
src/Window.cpp
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
35
src/debug/TracyDefines.hpp
Normal file
35
src/debug/TracyDefines.hpp
Normal 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
|
@@ -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
|
||||
|
@@ -170,4 +170,7 @@ namespace Events {
|
||||
|
||||
// Gamma control
|
||||
LISTENER(setGamma);
|
||||
|
||||
// Cursor shape
|
||||
LISTENER(setCursorShape);
|
||||
};
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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) {
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
@@ -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)
|
||||
|
@@ -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) {
|
||||
|
@@ -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
97
src/helpers/Region.cpp
Normal 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
55
src/helpers/Region.hpp
Normal 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;
|
||||
};
|
@@ -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 = "";
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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>
|
||||
|
||||
|
@@ -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, ¶m)) {
|
||||
Debug::log(WARN, "Failed to get old pthread scheduling priority");
|
||||
return;
|
||||
}
|
||||
|
||||
param.sched_priority = minPrio;
|
||||
|
||||
if (pthread_setschedparam(pthread_self(), SCHED_RR, ¶m)) {
|
||||
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, ¶m))
|
||||
Debug::log(WARN, "Failed to reset process scheduling strategy");
|
||||
});
|
||||
}
|
@@ -4,4 +4,5 @@
|
||||
|
||||
namespace Init {
|
||||
bool isSudo();
|
||||
void gainRealTime();
|
||||
};
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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() {}
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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.
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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) {
|
||||
|
@@ -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;
|
||||
};
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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() {
|
||||
|
@@ -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;
|
||||
};
|
@@ -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) {
|
||||
|
@@ -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();
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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();
|
||||
|
@@ -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]);
|
||||
}
|
||||
}
|
||||
|
@@ -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
1
subprojects/tracy
Submodule
Submodule subprojects/tracy added at 897aec5b06
Submodule subprojects/wlroots updated: 7791ffe058...e8d545a977
@@ -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
|
||||
|
Reference in New Issue
Block a user