mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-13 19:15:45 -07:00
Compare commits
128 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d74607e414 | ||
|
c4bd91ec8a | ||
|
03c6f4506a | ||
|
13b4c6de86 | ||
|
8bd86cf37e | ||
|
cfd94c5b30 | ||
|
ab66fa430e | ||
|
37d7a8c64d | ||
|
da863459c4 | ||
|
83248b6936 | ||
|
3bb9c7c5cf | ||
|
2d04cb1cc6 | ||
|
c6804ccaab | ||
|
aa46aaed04 | ||
|
68783d904d | ||
|
5d100bdcbb | ||
|
45d3fbb8d8 | ||
|
9a9528d093 | ||
|
e496b0f250 | ||
|
dc2082b00a | ||
|
59cb0e20de | ||
|
80b9b21f9f | ||
|
758cf90ea1 | ||
|
6e8b9ef7d8 | ||
|
9c09f2a847 | ||
|
8440a30231 | ||
|
ab40f240c3 | ||
|
b394c1695c | ||
|
0a4c4da5f0 | ||
|
b2f3623131 | ||
|
5513eed64d | ||
|
29970228c5 | ||
|
12ec549a18 | ||
|
9f2027be4b | ||
|
b9937484f4 | ||
|
776f944619 | ||
|
1fc1e4e9cb | ||
|
e1258707ad | ||
|
d2c3b23ace | ||
|
b80c72c7dd | ||
|
3caaa483d4 | ||
|
e2f18f8c7f | ||
|
99ca26d4eb | ||
|
e416ab740d | ||
|
7a0a5666d5 | ||
|
1778fb77e2 | ||
|
adeb20ea11 | ||
|
68e57b7ee3 | ||
|
408d96668d | ||
|
75e5799310 | ||
|
9e2b939024 | ||
|
cd96ceecc5 | ||
|
ad3f688648 | ||
|
98c7ba4782 | ||
|
a5f64b48ca | ||
|
b281d8647a | ||
|
15b282ee0c | ||
|
6f733292bf | ||
|
3fe6162af1 | ||
|
2ce4b94a22 | ||
|
de95e956a0 | ||
|
929c44e361 | ||
|
512a59731b | ||
|
a6eba91935 | ||
|
745b998587 | ||
|
1a2a2da6aa | ||
|
822775aa8c | ||
|
d79cf0afe2 | ||
|
334d0ae31b | ||
|
be3d635265 | ||
|
f9ba5a0551 | ||
|
258c83f3bb | ||
|
aedcade68d | ||
|
802ab58f8a | ||
|
af5d06593f | ||
|
2ebfd0c745 | ||
|
e40e486f61 | ||
|
e55c5a916a | ||
|
45ebe0df8f | ||
|
812a3f6d78 | ||
|
44accacff9 | ||
|
d417370bb7 | ||
|
4729265284 | ||
|
572fd554b8 | ||
|
7d1c8d827a | ||
|
6d26199e1c | ||
|
646f4bc638 | ||
|
7e0c90b92c | ||
|
add23a9ba2 | ||
|
3d89654254 | ||
|
6ad5f26cfe | ||
|
89f6457a99 | ||
|
8b57a1973e | ||
|
483302a2cd | ||
|
a903dba858 | ||
|
395985f815 | ||
|
51282f964f | ||
|
db8f13291a | ||
|
30ad71ff36 | ||
|
84bc0a73f6 | ||
|
1d9bfa60a1 | ||
|
a34e192433 | ||
|
4868d4dfd3 | ||
|
859841f4d1 | ||
|
28ef18a921 | ||
|
91d6be1f09 | ||
|
9e3dccca76 | ||
|
81598b3dbd | ||
|
e195e51c1b | ||
|
e8469f8b1b | ||
|
49597688e9 | ||
|
5edb4e4a30 | ||
|
4d6fa6ed0c | ||
|
016a7a9c9b | ||
|
2e26542e3b | ||
|
68935ba9dc | ||
|
ba5bc5871f | ||
|
824ccd957b | ||
|
45e86d4fdf | ||
|
0ba2e68704 | ||
|
e974d1fe98 | ||
|
47d46aa56c | ||
|
65efde32c9 | ||
|
69e314207d | ||
|
1bfd4a2bff | ||
|
91cbe93cf8 | ||
|
9afdd61ade | ||
|
f39a6ca17c |
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
cp ./LICENSE hyprland/
|
||||
cp build/Hyprland hyprland/
|
||||
cp build/hyprctl/hyprctl hyprland/
|
||||
cp subprojects/wlroots/build/libwlroots.so.12032 hyprland/
|
||||
cp subprojects/wlroots/build/libwlroots.so.13032 hyprland/
|
||||
cp build/Hyprland hyprland/
|
||||
cp -r example/ hyprland/
|
||||
cp -r assets/ hyprland/
|
||||
|
1
.github/workflows/nix-build.yml
vendored
1
.github/workflows/nix-build.yml
vendored
@@ -10,7 +10,6 @@ jobs:
|
||||
matrix:
|
||||
package:
|
||||
- hyprland
|
||||
- hyprland-nvidia
|
||||
- xdg-desktop-portal-hyprland
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
@@ -57,12 +57,12 @@ ExternalProject_Add(
|
||||
wlroots
|
||||
PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots
|
||||
SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots
|
||||
PATCH_COMMAND sed -E -i -e "s/(soversion = 12)([^032]|$$)/soversion = 12032/g" meson.build
|
||||
PATCH_COMMAND sed -E -i -e "s/(soversion = 13)([^032]|$$)/soversion = 13032/g" meson.build
|
||||
CONFIGURE_COMMAND meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none> && meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $<IF:$<BOOL:${WITH_ASAN}>,-Db_sanitize=address,-Db_sanitize=none> --reconfigure
|
||||
BUILD_COMMAND ninja -C build
|
||||
BUILD_ALWAYS true
|
||||
BUILD_IN_SOURCE true
|
||||
BUILD_BYPRODUCTS ${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.12032
|
||||
BUILD_BYPRODUCTS ${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.13032
|
||||
INSTALL_COMMAND echo "wlroots: install not needed"
|
||||
)
|
||||
|
||||
@@ -99,14 +99,19 @@ set(CMAKE_ENABLE_EXPORTS TRUE)
|
||||
message(STATUS "Checking deps...")
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(OpenGL REQUIRED)
|
||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo libdrm xkbcommon libinput pango pangocairo pixman-1) # we do not check for wlroots, as we provide it ourselves
|
||||
|
||||
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
||||
|
||||
add_executable(Hyprland ${SRCFILES})
|
||||
set(TRACY_CPP_FILES "")
|
||||
if(USE_TRACY)
|
||||
set(TRACY_CPP_FILES "subprojects/tracy/public/TracyClient.cpp")
|
||||
message(STATUS "Tracy enabled, TRACY_CPP_FILES: " ${TRACY_CPP_FILES})
|
||||
endif()
|
||||
|
||||
add_executable(Hyprland ${SRCFILES} ${TRACY_CPP_FILES})
|
||||
add_dependencies(Hyprland wlroots)
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
@@ -216,7 +221,7 @@ function(protocol protoPath protoName external)
|
||||
endfunction()
|
||||
|
||||
target_link_libraries(Hyprland
|
||||
${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.12032 # wlroots is provided by us
|
||||
${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.13032 # wlroots is provided by us
|
||||
OpenGL::EGL
|
||||
OpenGL::GL
|
||||
Threads::Threads
|
||||
|
6
Makefile
6
Makefile
@@ -50,7 +50,7 @@ install:
|
||||
install -m644 ./docs/*.1 ${PREFIX}/share/man/man1
|
||||
|
||||
mkdir -p ${PREFIX}/lib/
|
||||
cp ./subprojects/wlroots/build/libwlroots.so.12032 ${PREFIX}/lib/
|
||||
cp ./subprojects/wlroots/build/libwlroots.so.13032 ${PREFIX}/lib/
|
||||
|
||||
$(MAKE) installheaders
|
||||
|
||||
@@ -58,7 +58,7 @@ uninstall:
|
||||
rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop
|
||||
rm -f ${PREFIX}/bin/Hyprland
|
||||
rm -f ${PREFIX}/bin/hyprctl
|
||||
rm -f ${PREFIX}/lib/libwlroots.so.12032
|
||||
rm -f ${PREFIX}/lib/libwlroots.so.13032
|
||||
rm -rf ${PREFIX}/share/hyprland
|
||||
rm -f ${PREFIX}/share/man/man1/Hyprland.1
|
||||
rm -f ${PREFIX}/share/man/man1/hyprctl.1
|
||||
@@ -68,7 +68,7 @@ pluginenv:
|
||||
@exit 1
|
||||
|
||||
installheaders:
|
||||
@if [ ! -f ./build/Hyprland ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi
|
||||
@if [ ! -f ./src/version.h ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi
|
||||
|
||||
mkdir -p ${PREFIX}/include/hyprland
|
||||
mkdir -p ${PREFIX}/include/hyprland/protocols
|
||||
|
@@ -128,8 +128,8 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more...
|
||||
<!----------------------------------{ Images }--------------------------------->
|
||||
|
||||
[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg
|
||||
[Preview A]: https://cdn.discordapp.com/attachments/1091569872535814185/1107675866101723277/screenshot-summer.png
|
||||
[Preview B]: https://i.ibb.co/SX7GbYR/winter-rice.png
|
||||
[Preview A]: https://i.ibb.co/C1yTb0r/falf.png
|
||||
[Preview B]: https://cdn.discordapp.com/attachments/1091569872535814185/1107675866101723277/screenshot-summer.png
|
||||
[Preview C]: https://i.ibb.co/B3GJg28/20221126-20h53m26s-grim.png
|
||||
|
||||
|
||||
|
@@ -19,6 +19,10 @@ monitor=,preferred,auto,auto
|
||||
# Source a file (multi-file configs)
|
||||
# source = ~/.config/hypr/myColors.conf
|
||||
|
||||
# Set programs that you use
|
||||
$terminal = kitty
|
||||
$fileManager = dolphin
|
||||
$menu = wofi --show drun
|
||||
# Some default env vars.
|
||||
env = XCURSOR_SIZE,24
|
||||
|
||||
@@ -120,18 +124,19 @@ device:epic-mouse-v1 {
|
||||
# Example windowrule v2
|
||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
||||
windowrulev2 = nomaximizerequest, class:.* # You'll probably like this.
|
||||
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||
$mainMod = SUPER
|
||||
|
||||
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
|
||||
bind = $mainMod, Q, exec, kitty
|
||||
bind = $mainMod, Q, exec, $terminal
|
||||
bind = $mainMod, C, killactive,
|
||||
bind = $mainMod, M, exit,
|
||||
bind = $mainMod, E, exec, dolphin
|
||||
bind = $mainMod, E, exec, $fileManager
|
||||
bind = $mainMod, V, togglefloating,
|
||||
bind = $mainMod, R, exec, wofi --show drun
|
||||
bind = $mainMod, R, exec, $menu
|
||||
bind = $mainMod, P, pseudo, # dwindle
|
||||
bind = $mainMod, J, togglesplit, # dwindle
|
||||
|
||||
|
20
flake.lock
generated
20
flake.lock
generated
@@ -25,11 +25,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1698134075,
|
||||
"narHash": "sha256-foCD+nuKzfh49bIoiCBur4+Fx1nozo+4C/6k8BYk4sg=",
|
||||
"lastModified": 1700612854,
|
||||
"narHash": "sha256-yrQ8osMD+vDLGFX7pcwsY/Qr5PUd6OmDMYJZzZi0+zc=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "8efd5d1e283604f75a808a20e6cde0ef313d07d4",
|
||||
"rev": "19cbff58383a4ae384dea4d1d0c823d72b49d614",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -67,18 +67,18 @@
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"lastModified": 1699292815,
|
||||
"narHash": "sha256-HXu98PyBMKEWLqiTb8viuLDznud/SdkdJsx5A5CWx7I=",
|
||||
"lastModified": 1701368958,
|
||||
"narHash": "sha256-7kvyoA91etzVEl9mkA/EJfB6z/PltxX7Xc4gcr7/xlo=",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "5de9e1a99d6642c2d09d589aa37ff0a8945dcee1",
|
||||
"rev": "5d639394f3e83b01596dcd166a44a9a1a2583350",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "5de9e1a99d6642c2d09d589aa37ff0a8945dcee1",
|
||||
"rev": "5d639394f3e83b01596dcd166a44a9a1a2583350",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
@@ -95,11 +95,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1697981233,
|
||||
"narHash": "sha256-y8q4XUwx+gVK7i2eLjfR32lVo7TYvEslyzrmzYEaPZU=",
|
||||
"lastModified": 1700508250,
|
||||
"narHash": "sha256-X4o/mifI7Nhu0UKYlxx53wIC+gYDo3pVM9L2u3PE2bE=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "22e7a65ff9633e1dedfa5317fdffc49f68de2ff2",
|
||||
"rev": "eb120ff25265ecacd0fc13d7dab12131b60d0f47",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@@ -12,7 +12,7 @@
|
||||
host = "gitlab.freedesktop.org";
|
||||
owner = "wlroots";
|
||||
repo = "wlroots";
|
||||
rev = "5de9e1a99d6642c2d09d589aa37ff0a8945dcee1";
|
||||
rev = "5d639394f3e83b01596dcd166a44a9a1a2583350";
|
||||
flake = false;
|
||||
};
|
||||
|
||||
@@ -65,7 +65,6 @@
|
||||
hyprland
|
||||
hyprland-unwrapped
|
||||
hyprland-debug
|
||||
hyprland-nvidia
|
||||
# hyprland-extras
|
||||
xdg-desktop-portal-hyprland
|
||||
# dependencies
|
||||
|
@@ -1,4 +1,4 @@
|
||||
all:
|
||||
$(CXX) -std=c++2b ./main.cpp -o ./hyprctl
|
||||
$(CXX) $(CXXFLAGS) -std=c++2b ./main.cpp -o ./hyprctl
|
||||
clean:
|
||||
rm ./hyprctl
|
||||
|
@@ -26,32 +26,33 @@
|
||||
const std::string USAGE = R"#(usage: hyprctl [(opt)flags] [command] [(opt)args]
|
||||
|
||||
commands:
|
||||
monitors
|
||||
workspaces
|
||||
activeworkspace
|
||||
workspacerules
|
||||
clients
|
||||
activewindow
|
||||
layers
|
||||
devices
|
||||
activeworkspace
|
||||
binds
|
||||
clients
|
||||
cursorpos
|
||||
devices
|
||||
dispatch
|
||||
keyword
|
||||
version
|
||||
kill
|
||||
splash
|
||||
getoption
|
||||
globalshortcuts
|
||||
hyprpaper
|
||||
instances
|
||||
keyword
|
||||
kill
|
||||
layers
|
||||
layouts
|
||||
monitors
|
||||
notify
|
||||
plugin
|
||||
reload
|
||||
setcursor
|
||||
getoption
|
||||
cursorpos
|
||||
switchxkblayout
|
||||
seterror
|
||||
setprop
|
||||
plugin
|
||||
notify
|
||||
globalshortcuts
|
||||
instances
|
||||
splash
|
||||
switchxkblayout
|
||||
version
|
||||
workspacerules
|
||||
workspaces
|
||||
|
||||
flags:
|
||||
-j -> output in JSON
|
||||
@@ -396,6 +397,8 @@ int main(int argc, char** argv) {
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/globalshortcuts"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/rollinglog"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/instances"))
|
||||
instancesRequest(json);
|
||||
else if (fullRequest.contains("/switchxkblayout"))
|
||||
@@ -418,6 +421,8 @@ int main(int argc, char** argv) {
|
||||
request(fullRequest, 2);
|
||||
else if (fullRequest.contains("/hyprpaper"))
|
||||
requestHyprpaper(fullRequest);
|
||||
else if (fullRequest.contains("/layouts"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/--help"))
|
||||
printf("%s", USAGE.c_str());
|
||||
else {
|
||||
|
@@ -1,5 +1,6 @@
|
||||
{
|
||||
lib,
|
||||
fetchurl,
|
||||
stdenv,
|
||||
pkg-config,
|
||||
makeWrapper,
|
||||
@@ -10,6 +11,7 @@
|
||||
git,
|
||||
hyprland-protocols,
|
||||
jq,
|
||||
libGL,
|
||||
libdrm,
|
||||
libinput,
|
||||
libxcb,
|
||||
@@ -26,7 +28,6 @@
|
||||
xcbutilwm,
|
||||
xwayland,
|
||||
debug ? false,
|
||||
enableNvidiaPatches ? false,
|
||||
enableXWayland ? true,
|
||||
legacyRenderer ? false,
|
||||
withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd,
|
||||
@@ -34,13 +35,25 @@
|
||||
version ? "git",
|
||||
commit,
|
||||
# deprecated flags
|
||||
enableNvidiaPatches ? false,
|
||||
nvidiaPatches ? false,
|
||||
hidpiXWayland ? false,
|
||||
}:
|
||||
assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been renamed `enableNvidiaPatches`";
|
||||
let
|
||||
# NOTE: remove after https://github.com/NixOS/nixpkgs/pull/271096 reaches nixos-unstable
|
||||
libdrm_2_4_118 = libdrm.overrideAttrs(attrs: rec {
|
||||
version = "2.4.118";
|
||||
src = fetchurl {
|
||||
url = "https://dri.freedesktop.org/${attrs.pname}/${attrs.pname}-${version}.tar.xz";
|
||||
hash = "sha256-p3e9hfK1/JxX+IbIIFgwBXgxfK/bx30Kdp1+mpVnq4g=";
|
||||
};
|
||||
});
|
||||
in
|
||||
assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed.";
|
||||
assert lib.assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed.";
|
||||
assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland";
|
||||
stdenv.mkDerivation {
|
||||
pname = "hyprland${lib.optionalString enableNvidiaPatches "-nvidia"}${lib.optionalString debug "-debug"}";
|
||||
pname = "hyprland${lib.optionalString debug "-debug"}";
|
||||
inherit version;
|
||||
|
||||
src = lib.cleanSourceWith {
|
||||
@@ -71,7 +84,8 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
||||
git
|
||||
cairo
|
||||
hyprland-protocols
|
||||
libdrm
|
||||
libGL
|
||||
libdrm_2_4_118
|
||||
libinput
|
||||
libxkbcommon
|
||||
mesa
|
||||
@@ -80,7 +94,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
||||
wayland
|
||||
wayland-protocols
|
||||
pciutils
|
||||
(wlroots.override {inherit enableNvidiaPatches;})
|
||||
wlroots
|
||||
]
|
||||
++ lib.optionals enableXWayland [libxcb xcbutilwm xwayland]
|
||||
++ lib.optionals withSystemd [systemd];
|
||||
|
@@ -7,7 +7,6 @@ self: {
|
||||
cfg = config.wayland.windowManager.hyprland;
|
||||
defaultHyprlandPackage = self.packages.${pkgs.stdenv.hostPlatform.system}.default.override {
|
||||
enableXWayland = cfg.xwayland.enable;
|
||||
inherit (cfg) enableNvidiaPatches;
|
||||
};
|
||||
in {
|
||||
disabledModules = ["services/window-managers/hyprland.nix"];
|
||||
@@ -35,12 +34,10 @@ in {
|
||||
defaultText = lib.literalExpression ''
|
||||
hyprland.packages.''${pkgs.stdenv.hostPlatform.system}.default.override {
|
||||
enableXWayland = config.wayland.windowManager.hyprland.xwayland.enable;
|
||||
inherit (config.wayland.windowManager.hyprland) enableNvidiaPatches;
|
||||
}
|
||||
'';
|
||||
description = lib.mdDoc ''
|
||||
Hyprland package to use. Will override the 'xwayland' and
|
||||
'enableNvidiaPatches' options.
|
||||
Hyprland package to use. Will override the 'xwayland' option.
|
||||
|
||||
Defaults to the one provided by the flake. Set it to
|
||||
{package}`pkgs.hyprland` to use the one provided by nixpkgs or
|
||||
@@ -86,8 +83,6 @@ in {
|
||||
|
||||
xwayland.enable = lib.mkEnableOption (lib.mdDoc "XWayland") // {default = true;};
|
||||
|
||||
enableNvidiaPatches = lib.mkEnableOption (lib.mdDoc "patching wlroots for better Nvidia support.");
|
||||
|
||||
extraConfig = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.lines;
|
||||
default = "";
|
||||
@@ -173,5 +168,7 @@ in {
|
||||
imports = [
|
||||
(lib.mkRemovedOptionModule ["wayland" "windowManager" "hyprland" "xwayland" "hidpi"]
|
||||
"Support for this option has been removed. Refer to https://wiki.hyprland.org/Configuring/XWayland for more info")
|
||||
(lib.mkRemovedOptionModule ["wayland" "windowManager" "hyprland" "xwayland" "enableNvidiaPatches"]
|
||||
"Nvidia patches are no longer needed for Hyprland")
|
||||
];
|
||||
}
|
||||
|
@@ -37,7 +37,6 @@ in {
|
||||
readOnly = true;
|
||||
default = cfg.package.override {
|
||||
enableXWayland = cfg.xwayland.enable;
|
||||
enableNvidiaPatches = cfg.enableNvidiaPatches;
|
||||
};
|
||||
defaultText =
|
||||
literalExpression
|
||||
@@ -50,12 +49,6 @@ in {
|
||||
portalPackage = mkPackageOptionMD inputs.xdph.packages.${system} "xdg-desktop-portal-hyprland" {};
|
||||
|
||||
xwayland.enable = mkEnableOption (mdDoc "support for XWayland") // {default = true;};
|
||||
|
||||
enableNvidiaPatches =
|
||||
mkEnableOption null
|
||||
// {
|
||||
description = mdDoc "Whether to apply patches to wlroots for better Nvidia support.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
@@ -91,9 +84,14 @@ in {
|
||||
"XWayland patches are deprecated. Refer to https://wiki.hyprland.org/Configuring/XWayland"
|
||||
)
|
||||
(
|
||||
mkRenamedOptionModule
|
||||
["programs" "hyprland" "nvidiaPatches"]
|
||||
mkRemovedOptionModule
|
||||
["programs" "hyprland" "enableNvidiaPatches"]
|
||||
"Nvidia patches are no longer needed"
|
||||
)
|
||||
(
|
||||
mkRemovedOptionModule
|
||||
["programs" "hyprland" "nvidiaPatches"]
|
||||
"Nvidia patches are no longer needed"
|
||||
)
|
||||
];
|
||||
}
|
||||
|
@@ -38,7 +38,12 @@ in {
|
||||
};
|
||||
hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;};
|
||||
hyprland-debug = final.hyprland.override {debug = true;};
|
||||
hyprland-nvidia = final.hyprland.override {enableNvidiaPatches = true;};
|
||||
hyprland-nvidia =
|
||||
builtins.trace ''
|
||||
hyprland-nvidia was removed. Please use the hyprland package.
|
||||
Nvidia patches are no longer needed.
|
||||
''
|
||||
final.hyprland;
|
||||
hyprland-hidpi =
|
||||
builtins.trace ''
|
||||
hyprland-hidpi was removed. Please use the hyprland package.
|
||||
|
@@ -1,41 +0,0 @@
|
||||
diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c
|
||||
index 9fe934f7..9662d4ee 100644
|
||||
--- a/render/gles2/renderer.c
|
||||
+++ b/render/gles2/renderer.c
|
||||
@@ -176,7 +176,7 @@ static bool gles2_bind_buffer(struct wlr_renderer *wlr_renderer,
|
||||
assert(wlr_egl_is_current(renderer->egl));
|
||||
|
||||
push_gles2_debug(renderer);
|
||||
- glFlush();
|
||||
+ glFinish();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
pop_gles2_debug(renderer);
|
||||
|
||||
diff --git a/types/output/render.c b/types/output/render.c
|
||||
index 2e38919a..97f78608 100644
|
||||
--- a/types/output/render.c
|
||||
+++ b/types/output/render.c
|
||||
@@ -240,22 +240,7 @@ bool output_pick_format(struct wlr_output *output,
|
||||
}
|
||||
|
||||
uint32_t wlr_output_preferred_read_format(struct wlr_output *output) {
|
||||
- struct wlr_renderer *renderer = output->renderer;
|
||||
- assert(renderer != NULL);
|
||||
-
|
||||
- if (!renderer->impl->preferred_read_format || !renderer->impl->read_pixels) {
|
||||
- return DRM_FORMAT_INVALID;
|
||||
- }
|
||||
-
|
||||
- if (!wlr_output_attach_render(output, NULL)) {
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- uint32_t fmt = renderer->impl->preferred_read_format(renderer);
|
||||
-
|
||||
- output_clear_back_buffer(output);
|
||||
-
|
||||
- return fmt;
|
||||
+ return DRM_FORMAT_XRGB8888;
|
||||
}
|
||||
|
||||
struct wlr_render_pass *wlr_output_begin_render_pass(struct wlr_output *output,
|
@@ -1,26 +1,31 @@
|
||||
{
|
||||
lib,
|
||||
fetchurl,
|
||||
version,
|
||||
src,
|
||||
wlroots,
|
||||
hwdata,
|
||||
libdisplay-info,
|
||||
libliftoff,
|
||||
libdrm,
|
||||
enableXWayland ? true,
|
||||
enableNvidiaPatches ? false,
|
||||
}:
|
||||
let
|
||||
# NOTE: remove after https://github.com/NixOS/nixpkgs/pull/271096 reaches nixos-unstable
|
||||
libdrm_2_4_118 = libdrm.overrideAttrs(old: rec {
|
||||
version = "2.4.118";
|
||||
src = fetchurl {
|
||||
url = "https://dri.freedesktop.org/${old.pname}/${old.pname}-${version}.tar.xz";
|
||||
hash = "sha256-p3e9hfK1/JxX+IbIIFgwBXgxfK/bx30Kdp1+mpVnq4g=";
|
||||
};
|
||||
});
|
||||
in
|
||||
wlroots.overrideAttrs (old: {
|
||||
inherit version src enableXWayland;
|
||||
|
||||
pname = "${old.pname}-hyprland${lib.optionalString enableNvidiaPatches "-nvidia"}";
|
||||
pname = "${old.pname}-hyprland";
|
||||
|
||||
patches =
|
||||
(old.patches or [])
|
||||
++ (lib.optionals enableNvidiaPatches [
|
||||
./patches/wlroots-nvidia.patch
|
||||
]);
|
||||
|
||||
buildInputs = old.buildInputs ++ [hwdata libliftoff libdisplay-info];
|
||||
# HACK: libdrm_2_4_118 is placed at the head of list to take precedence over libdrm in `old.buildInputs`
|
||||
buildInputs = [libdrm_2_4_118] ++ old.buildInputs ++ [hwdata libliftoff libdisplay-info];
|
||||
|
||||
NIX_CFLAGS_COMPILE = toString [
|
||||
"-Wno-error=maybe-uninitialized"
|
||||
|
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"version": "0.32.2"
|
||||
"version": "0.33.1"
|
||||
}
|
@@ -190,7 +190,7 @@ void CCompositor::initServer() {
|
||||
|
||||
m_sWLRGammaCtrlMgr = wlr_gamma_control_manager_v1_create(m_sWLDisplay);
|
||||
|
||||
m_sWLROutputLayout = wlr_output_layout_create();
|
||||
m_sWLROutputLayout = wlr_output_layout_create(m_sWLDisplay);
|
||||
|
||||
m_sWLROutputPowerMgr = wlr_output_power_manager_v1_create(m_sWLDisplay);
|
||||
|
||||
@@ -225,7 +225,6 @@ void CCompositor::initServer() {
|
||||
|
||||
m_sWLROutputMgr = wlr_output_manager_v1_create(m_sWLDisplay);
|
||||
|
||||
m_sWLRInhibitMgr = wlr_input_inhibit_manager_create(m_sWLDisplay);
|
||||
m_sWLRKbShInhibitMgr = wlr_keyboard_shortcuts_inhibit_v1_create(m_sWLDisplay);
|
||||
|
||||
m_sWLRPointerConstraints = wlr_pointer_constraints_v1_create(m_sWLDisplay);
|
||||
@@ -283,7 +282,7 @@ void CCompositor::initServer() {
|
||||
|
||||
void CCompositor::initAllSignals() {
|
||||
addWLSignal(&m_sWLRBackend->events.new_output, &Events::listen_newOutput, m_sWLRBackend, "Backend");
|
||||
addWLSignal(&m_sWLRXDGShell->events.new_surface, &Events::listen_newXDGSurface, m_sWLRXDGShell, "XDG Shell");
|
||||
addWLSignal(&m_sWLRXDGShell->events.new_toplevel, &Events::listen_newXDGToplevel, m_sWLRXDGShell, "XDG Shell");
|
||||
addWLSignal(&m_sWLRCursor->events.motion, &Events::listen_mouseMove, m_sWLRCursor, "WLRCursor");
|
||||
addWLSignal(&m_sWLRCursor->events.motion_absolute, &Events::listen_mouseMoveAbsolute, m_sWLRCursor, "WLRCursor");
|
||||
addWLSignal(&m_sWLRCursor->events.button, &Events::listen_mouseButton, m_sWLRCursor, "WLRCursor");
|
||||
@@ -312,8 +311,6 @@ void CCompositor::initAllSignals() {
|
||||
addWLSignal(&m_sWLROutputLayout->events.change, &Events::listen_change, m_sWLROutputLayout, "OutputLayout");
|
||||
addWLSignal(&m_sWLROutputMgr->events.apply, &Events::listen_outputMgrApply, m_sWLROutputMgr, "OutputMgr");
|
||||
addWLSignal(&m_sWLROutputMgr->events.test, &Events::listen_outputMgrTest, m_sWLROutputMgr, "OutputMgr");
|
||||
addWLSignal(&m_sWLRInhibitMgr->events.activate, &Events::listen_InhibitActivate, m_sWLRInhibitMgr, "InhibitMgr");
|
||||
addWLSignal(&m_sWLRInhibitMgr->events.deactivate, &Events::listen_InhibitDeactivate, m_sWLRInhibitMgr, "InhibitMgr");
|
||||
addWLSignal(&m_sWLRPointerConstraints->events.new_constraint, &Events::listen_newConstraint, m_sWLRPointerConstraints, "PointerConstraints");
|
||||
addWLSignal(&m_sWLRXDGDecoMgr->events.new_toplevel_decoration, &Events::listen_NewXDGDeco, m_sWLRXDGDecoMgr, "XDGDecoMgr");
|
||||
addWLSignal(&m_sWLRVirtPtrMgr->events.new_virtual_pointer, &Events::listen_newVirtPtr, m_sWLRVirtPtrMgr, "VirtPtrMgr");
|
||||
@@ -342,7 +339,8 @@ void CCompositor::cleanup() {
|
||||
|
||||
removeLockFile();
|
||||
|
||||
m_bIsShuttingDown = true;
|
||||
m_bIsShuttingDown = true;
|
||||
Debug::shuttingDown = true;
|
||||
|
||||
#ifdef USES_SYSTEMD
|
||||
if (sd_booted() > 0)
|
||||
@@ -577,7 +575,7 @@ CMonitor* CCompositor::getMonitorFromName(const std::string& name) {
|
||||
|
||||
CMonitor* CCompositor::getMonitorFromDesc(const std::string& desc) {
|
||||
for (auto& m : m_vMonitors) {
|
||||
if (m->output->description && std::string(m->output->description).starts_with(desc))
|
||||
if (m->szDescription.starts_with(desc))
|
||||
return m.get();
|
||||
}
|
||||
return nullptr;
|
||||
@@ -630,46 +628,6 @@ bool CCompositor::windowExists(CWindow* pWindow) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
|
||||
const auto PMONITOR = getMonitorFromVector(pos);
|
||||
|
||||
if (PMONITOR->specialWorkspaceID) {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
auto box = w->getWindowMainSurfaceBox();
|
||||
if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && box.containsPoint(pos) && !w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
auto box = w->getWindowMainSurfaceBox();
|
||||
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && box.containsPoint(pos) && w->m_bIsMapped && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
|
||||
// pinned
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
auto box = w->getWindowMainSurfaceBox();
|
||||
if (box.containsPoint(pos) && w->m_bIsMapped && w->m_bIsFloating && !w->isHidden() && w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
// first loop over floating cuz they're above, m_vWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
auto box = w->getWindowMainSurfaceBox();
|
||||
if (box.containsPoint(pos) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
auto box = w->getWindowMainSurfaceBox();
|
||||
if (box.containsPoint(pos) && w->m_bIsMapped && !w->m_bIsFloating && PMONITOR->activeWorkspace == w->m_iWorkspaceID && !w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
|
||||
const auto PMONITOR = getMonitorFromVector(pos);
|
||||
|
||||
@@ -690,36 +648,18 @@ CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos, CWindow* pIgnoreWindow) {
|
||||
const auto PMONITOR = getMonitorFromVector(pos);
|
||||
static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue;
|
||||
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
static auto* const PBORDERGRABEXTEND = &g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area")->intValue;
|
||||
const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0;
|
||||
|
||||
// special workspace
|
||||
if (PMONITOR->specialWorkspaceID) {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
const auto BB = w->getWindowInputBox();
|
||||
CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
||||
if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && box.containsPoint(pos) && !w->isHidden() && !w->m_bX11ShouldntFocus &&
|
||||
!w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (!w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && box.containsPoint(pos) && !w->isHidden() && !w->m_bX11ShouldntFocus &&
|
||||
!w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
|
||||
// pinned windows on top of floating regardless
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
const auto BB = w->getWindowInputBox();
|
||||
CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_bNoFocus) {
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_bNoFocus && w.get() != pIgnoreWindow) {
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}))
|
||||
return w.get();
|
||||
|
||||
@@ -730,48 +670,74 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
}
|
||||
}
|
||||
|
||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
const auto BB = w->getWindowInputBox();
|
||||
CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_bNoFocus) {
|
||||
// OR windows should add focus to parent
|
||||
if (w->m_bX11ShouldntFocus && w->m_iX11Type != 2)
|
||||
auto windowForWorkspace = [&](bool special) -> CWindow* {
|
||||
// first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter.
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
|
||||
if (special && !isWorkspaceSpecial(w->m_iWorkspaceID)) // because special floating may creep up into regular
|
||||
continue;
|
||||
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y})) {
|
||||
const auto BB = w->getWindowInputBox();
|
||||
CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
||||
if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_bNoFocus && w.get() != pIgnoreWindow) {
|
||||
// OR windows should add focus to parent
|
||||
if (w->m_bX11ShouldntFocus && w->m_iX11Type != 2)
|
||||
continue;
|
||||
|
||||
if (w->m_bIsX11 && w->m_iX11Type == 2 && !wlr_xwayland_or_surface_wants_focus(w->m_uSurface.xwayland)) {
|
||||
// Override Redirect
|
||||
return g_pCompositor->m_pLastWindow; // we kinda trick everything here.
|
||||
// TODO: this is wrong, we should focus the parent, but idk how to get it considering it's nullptr in most cases.
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y})) {
|
||||
|
||||
if (w->m_bIsX11 && w->m_iX11Type == 2 && !wlr_xwayland_or_surface_wants_focus(w->m_uSurface.xwayland)) {
|
||||
// Override Redirect
|
||||
return g_pCompositor->m_pLastWindow; // we kinda trick everything here.
|
||||
// TODO: this is wrong, we should focus the parent, but idk how to get it considering it's nullptr in most cases.
|
||||
}
|
||||
|
||||
return w.get();
|
||||
}
|
||||
|
||||
return w.get();
|
||||
if (!w->m_bIsX11) {
|
||||
if (w->hasPopupAt(pos))
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!w->m_bIsX11) {
|
||||
const int64_t WORKSPACEID = special ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace;
|
||||
const auto PWORKSPACE = getWorkspaceByID(WORKSPACEID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow)
|
||||
return getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
|
||||
// for windows, we need to check their extensions too, first.
|
||||
for (auto& w : m_vWindows) {
|
||||
if (special != isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus &&
|
||||
w.get() != pIgnoreWindow) {
|
||||
if (w->hasPopupAt(pos))
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for windows, we need to check their extensions too, first.
|
||||
for (auto& w : m_vWindows) {
|
||||
if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus) {
|
||||
if ((w)->hasPopupAt(pos))
|
||||
for (auto& w : m_vWindows) {
|
||||
if (special != isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
CBox box = {w->m_vPosition, w->m_vSize};
|
||||
if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus &&
|
||||
w.get() != pIgnoreWindow)
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
for (auto& w : m_vWindows) {
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->isHidden() && !w->m_bX11ShouldntFocus &&
|
||||
!w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
// special workspace
|
||||
if (PMONITOR->specialWorkspaceID)
|
||||
return windowForWorkspace(true);
|
||||
|
||||
return windowForWorkspace(false);
|
||||
}
|
||||
|
||||
CWindow* CCompositor::windowFromCursor() {
|
||||
@@ -1144,6 +1110,21 @@ wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SIMEPopup* CCompositor::vectorToIMEPopup(const Vector2D& pos, std::list<SIMEPopup>& popups) {
|
||||
for (auto& popup : popups) {
|
||||
auto surface = popup.pSurface->surface;
|
||||
CBox box{
|
||||
popup.realX,
|
||||
popup.realY,
|
||||
surface->current.width,
|
||||
surface->current.height,
|
||||
};
|
||||
if (box.containsPoint(pos))
|
||||
return &popup;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CWindow* CCompositor::getWindowFromSurface(wlr_surface* pSurface) {
|
||||
for (auto& w : m_vWindows) {
|
||||
if (!w->m_bIsMapped || w->m_bFadingOut || !w->m_bMappedX11)
|
||||
@@ -1415,14 +1396,11 @@ void CCompositor::cleanupFadingOut(const int& monid) {
|
||||
if (valid && !w->m_bReadyToDelete)
|
||||
continue;
|
||||
|
||||
std::erase_if(g_pHyprOpenGL->m_mWindowFramebuffers, [&](const auto& other) { return other.first == w; });
|
||||
w->m_bFadingOut = false;
|
||||
removeWindowFromVectorSafe(w);
|
||||
std::erase(m_vWindowsFadingOut, w);
|
||||
|
||||
Debug::log(LOG, "Cleanup: destroyed a window");
|
||||
|
||||
glFlush(); // to free mem NOW.
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1464,9 +1442,6 @@ void CCompositor::cleanupFadingOut(const int& monid) {
|
||||
g_pHyprOpenGL->markBlurDirtyForMonitor(getMonitorFromID(monid));
|
||||
|
||||
if (ls->fadingOut && ls->readyToDelete && !ls->alpha.isBeingAnimated()) {
|
||||
g_pHyprOpenGL->m_mLayerFramebuffers[ls].release();
|
||||
g_pHyprOpenGL->m_mLayerFramebuffers.erase(ls);
|
||||
|
||||
for (auto& m : m_vMonitors) {
|
||||
for (auto& lsl : m->m_aLayerSurfaceLayers) {
|
||||
if (!lsl.empty() && std::find_if(lsl.begin(), lsl.end(), [&](std::unique_ptr<SLayerSurface>& other) { return other.get() == ls; }) != lsl.end()) {
|
||||
@@ -2082,7 +2057,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
|
||||
if (!m->output)
|
||||
continue;
|
||||
|
||||
if (m->output->description && std::string(m->output->description).starts_with(DESCRIPTION)) {
|
||||
if (m->szDescription.starts_with(DESCRIPTION)) {
|
||||
return m.get();
|
||||
}
|
||||
}
|
||||
@@ -2561,6 +2536,8 @@ CWorkspace* CCompositor::createNewWorkspace(const int& id, const int& monid, con
|
||||
PWORKSPACE->m_iID = id;
|
||||
PWORKSPACE->m_iMonitorID = monID;
|
||||
|
||||
PWORKSPACE->m_fAlpha.setValueAndWarp(0);
|
||||
|
||||
return PWORKSPACE;
|
||||
}
|
||||
|
||||
@@ -2792,4 +2769,4 @@ void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scal
|
||||
|
||||
void CCompositor::setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform) {
|
||||
wlr_surface_set_preferred_buffer_transform(pSurface, transform);
|
||||
}
|
||||
}
|
||||
|
@@ -62,7 +62,6 @@ class CCompositor {
|
||||
wlr_virtual_keyboard_manager_v1* m_sWLRVKeyboardMgr;
|
||||
wlr_output_manager_v1* m_sWLROutputMgr;
|
||||
wlr_presentation* m_sWLRPresentation;
|
||||
wlr_input_inhibit_manager* m_sWLRInhibitMgr;
|
||||
wlr_keyboard_shortcuts_inhibit_manager_v1* m_sWLRKbShInhibitMgr;
|
||||
wlr_egl* m_sWLREGL;
|
||||
int m_iDRMFD;
|
||||
@@ -137,10 +136,10 @@ class CCompositor {
|
||||
void focusSurface(wlr_surface*, CWindow* pWindowOwner = nullptr);
|
||||
bool windowExists(CWindow*);
|
||||
bool windowValidMapped(CWindow*);
|
||||
CWindow* vectorToWindow(const Vector2D&);
|
||||
CWindow* vectorToWindowIdeal(const Vector2D&); // used only for finding a window to focus on, basically a "findFocusableWindow"
|
||||
CWindow* vectorToWindowIdeal(const Vector2D&, CWindow* pIgnoreWindow = nullptr); // used only for finding a window to focus on, basically a "findFocusableWindow"
|
||||
CWindow* vectorToWindowTiled(const Vector2D&);
|
||||
wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector<std::unique_ptr<SLayerSurface>>*, Vector2D*, SLayerSurface**);
|
||||
SIMEPopup* vectorToIMEPopup(const Vector2D& pos, std::list<SIMEPopup>& popups);
|
||||
wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
|
||||
Vector2D vectorToSurfaceLocal(const Vector2D&, CWindow*, wlr_surface*);
|
||||
CWindow* windowFromCursor();
|
||||
|
@@ -21,6 +21,12 @@ CWindow::~CWindow() {
|
||||
g_pCompositor->m_pLastFocus = nullptr;
|
||||
g_pCompositor->m_pLastWindow = nullptr;
|
||||
}
|
||||
|
||||
if (!g_pHyprOpenGL)
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
std::erase_if(g_pHyprOpenGL->m_mWindowFramebuffers, [&](const auto& other) { return other.first == this; });
|
||||
}
|
||||
|
||||
SWindowDecorationExtents CWindow::getFullWindowExtents() {
|
||||
@@ -202,12 +208,16 @@ void CWindow::updateWindowDecos() {
|
||||
|
||||
void CWindow::addWindowDeco(std::unique_ptr<IHyprWindowDecoration> deco) {
|
||||
m_dWindowDecorations.emplace_back(std::move(deco));
|
||||
g_pDecorationPositioner->forceRecalcFor(this);
|
||||
updateWindowDecos();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(this);
|
||||
}
|
||||
|
||||
void CWindow::removeWindowDeco(IHyprWindowDecoration* deco) {
|
||||
m_vDecosToRemove.push_back(deco);
|
||||
g_pDecorationPositioner->forceRecalcFor(this);
|
||||
updateWindowDecos();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(this);
|
||||
}
|
||||
|
||||
pid_t CWindow::getPID() {
|
||||
@@ -587,6 +597,19 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
try {
|
||||
m_sAdditionalConfigData.xray = configStringToInt(vars[1]);
|
||||
} catch (...) {}
|
||||
} else if (r.szRule.starts_with("idleinhibit")) {
|
||||
auto IDLERULE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
||||
|
||||
if (IDLERULE == "none")
|
||||
m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
||||
else if (IDLERULE == "always")
|
||||
m_eIdleInhibitMode = IDLEINHIBIT_ALWAYS;
|
||||
else if (IDLERULE == "focus")
|
||||
m_eIdleInhibitMode = IDLEINHIBIT_FOCUS;
|
||||
else if (IDLERULE == "fullscreen")
|
||||
m_eIdleInhibitMode = IDLEINHIBIT_FULLSCREEN;
|
||||
else
|
||||
Debug::log(ERR, "Rule idleinhibit: unknown mode {}", IDLERULE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -611,6 +634,7 @@ void CWindow::updateDynamicRules() {
|
||||
m_sAdditionalConfigData.xray = -1;
|
||||
m_sAdditionalConfigData.forceTearing = false;
|
||||
m_sAdditionalConfigData.nearestNeighbor = false;
|
||||
m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
||||
|
||||
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(this);
|
||||
for (auto& r : WINDOWRULES) {
|
||||
|
@@ -1,6 +1,8 @@
|
||||
#include "ConfigManager.hpp"
|
||||
#include "../managers/KeybindManager.hpp"
|
||||
|
||||
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
||||
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
@@ -31,6 +33,8 @@ CConfigManager::CConfigManager() {
|
||||
configValues["group:groupbar:col.locked_active"].data = std::make_shared<CGradientValueData>(0x66ff5500);
|
||||
configValues["group:groupbar:col.locked_inactive"].data = std::make_shared<CGradientValueData>(0x66775500);
|
||||
|
||||
Debug::log(LOG, "NOTE: further logs to stdout / logfile are disabled by default. Use debug:disable_logs and debug:enable_stdout_logs to override this.");
|
||||
|
||||
setDefaultVars();
|
||||
setDefaultAnimationVars();
|
||||
|
||||
@@ -44,12 +48,11 @@ CConfigManager::CConfigManager() {
|
||||
|
||||
std::string CConfigManager::getConfigDir() {
|
||||
static const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
|
||||
std::string configPath;
|
||||
if (!xdgConfigHome)
|
||||
configPath = getenv("HOME") + std::string("/.config");
|
||||
else
|
||||
configPath = xdgConfigHome;
|
||||
return configPath;
|
||||
|
||||
if (xdgConfigHome && std::filesystem::path(xdgConfigHome).is_absolute())
|
||||
return xdgConfigHome;
|
||||
|
||||
return getenv("HOME") + std::string("/.config");
|
||||
}
|
||||
|
||||
std::string CConfigManager::getMainConfigPath() {
|
||||
@@ -79,6 +82,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["general:no_border_on_floating"].intValue = 0;
|
||||
configValues["general:gaps_in"].intValue = 5;
|
||||
configValues["general:gaps_out"].intValue = 20;
|
||||
configValues["general:gaps_workspaces"].intValue = 0;
|
||||
((CGradientValueData*)configValues["general:col.active_border"].data.get())->reset(0xffffffff);
|
||||
((CGradientValueData*)configValues["general:col.inactive_border"].data.get())->reset(0xff444444);
|
||||
((CGradientValueData*)configValues["general:col.nogroup_border"].data.get())->reset(0xff444444);
|
||||
@@ -145,7 +149,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["debug:log_damage"].intValue = 0;
|
||||
configValues["debug:overlay"].intValue = 0;
|
||||
configValues["debug:damage_blink"].intValue = 0;
|
||||
configValues["debug:disable_logs"].intValue = 0;
|
||||
configValues["debug:disable_logs"].intValue = 1;
|
||||
configValues["debug:disable_time"].intValue = 1;
|
||||
configValues["debug:enable_stdout_logs"].intValue = 0;
|
||||
configValues["debug:damage_tracking"].intValue = DAMAGE_TRACKING_FULL;
|
||||
@@ -188,7 +192,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["dwindle:force_split"].intValue = 0;
|
||||
configValues["dwindle:permanent_direction_override"].intValue = 0;
|
||||
configValues["dwindle:preserve_split"].intValue = 0;
|
||||
configValues["dwindle:special_scale_factor"].floatValue = 0.8f;
|
||||
configValues["dwindle:special_scale_factor"].floatValue = 1.f;
|
||||
configValues["dwindle:split_width_multiplier"].floatValue = 1.0f;
|
||||
configValues["dwindle:no_gaps_when_only"].intValue = 0;
|
||||
configValues["dwindle:use_active_for_splits"].intValue = 1;
|
||||
@@ -196,7 +200,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["dwindle:smart_split"].intValue = 0;
|
||||
configValues["dwindle:smart_resizing"].intValue = 1;
|
||||
|
||||
configValues["master:special_scale_factor"].floatValue = 0.8f;
|
||||
configValues["master:special_scale_factor"].floatValue = 1.f;
|
||||
configValues["master:mfact"].floatValue = 0.55f;
|
||||
configValues["master:new_is_master"].intValue = 1;
|
||||
configValues["master:always_center_master"].intValue = 0;
|
||||
@@ -208,7 +212,8 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["master:smart_resizing"].intValue = 1;
|
||||
configValues["master:drop_at_cursor"].intValue = 1;
|
||||
|
||||
configValues["animations:enabled"].intValue = 1;
|
||||
configValues["animations:enabled"].intValue = 1;
|
||||
configValues["animations:first_launch_animation"].intValue = 1;
|
||||
|
||||
configValues["input:follow_mouse"].intValue = 1;
|
||||
configValues["input:mouse_refocus"].intValue = 1;
|
||||
@@ -1164,13 +1169,13 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std:
|
||||
auto rules = value.substr(FIRST_DELIM + 1);
|
||||
SWorkspaceRule wsRule;
|
||||
wsRule.workspaceString = first_ident;
|
||||
if (id == INT_MAX) {
|
||||
if (id == WORKSPACE_INVALID) {
|
||||
// it could be the monitor. If so, second value MUST be
|
||||
// the workspace.
|
||||
const auto WORKSPACE_DELIM = value.find_first_of(',', FIRST_DELIM + 1);
|
||||
auto wsIdent = removeBeginEndSpacesTabs(value.substr(FIRST_DELIM + 1, (WORKSPACE_DELIM - FIRST_DELIM - 1)));
|
||||
id = getWorkspaceIDFromString(wsIdent, name);
|
||||
if (id == INT_MAX) {
|
||||
if (id == WORKSPACE_INVALID) {
|
||||
Debug::log(ERR, "Invalid workspace identifier found: {}", wsIdent);
|
||||
parseError = "Invalid workspace identifier found: " + wsIdent;
|
||||
return;
|
||||
@@ -1208,6 +1213,8 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std:
|
||||
wsRule.isPersistent = configStringToInt(rule.substr(delim + 11));
|
||||
else if ((delim = rule.find(ruleOnCreatedEmtpy)) != std::string::npos)
|
||||
wsRule.onCreatedEmptyRunCmd = cleanCmdForWorkspace(name, rule.substr(delim + ruleOnCreatedEmtpyLen));
|
||||
else if ((delim = rule.find("layoutopt:orientation:")) != std::string::npos)
|
||||
wsRule.layoutopts["orientation"] = rule.substr(delim + 22);
|
||||
};
|
||||
|
||||
size_t pos = 0;
|
||||
@@ -1255,7 +1262,12 @@ void CConfigManager::handleSource(const std::string& command, const std::string&
|
||||
for (size_t i = 0; i < glob_buf->gl_pathc; i++) {
|
||||
auto value = absolutePath(glob_buf->gl_pathv[i], configCurrentPath);
|
||||
|
||||
if (!std::filesystem::exists(value)) {
|
||||
if (!std::filesystem::is_regular_file(value)) {
|
||||
if (std::filesystem::exists(value)) {
|
||||
Debug::log(WARN, "source= skipping non-file {}", value);
|
||||
continue;
|
||||
}
|
||||
|
||||
Debug::log(ERR, "source= file doesnt exist");
|
||||
parseError = "source file " + value + " doesn't exist!";
|
||||
return;
|
||||
@@ -1509,7 +1521,7 @@ void CConfigManager::parseLine(std::string& line) {
|
||||
|
||||
const auto LASTSEP = currentCategory.find_last_of(':');
|
||||
|
||||
if (LASTSEP == std::string::npos || currentCategory.contains("device"))
|
||||
if (LASTSEP == std::string::npos || currentCategory.starts_with("device"))
|
||||
currentCategory = "";
|
||||
else
|
||||
currentCategory = currentCategory.substr(0, LASTSEP);
|
||||
@@ -1562,20 +1574,20 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
std::string mainConfigPath = getMainConfigPath();
|
||||
Debug::log(LOG, "Using config: {}", mainConfigPath);
|
||||
configPaths.push_back(mainConfigPath);
|
||||
std::string configPath = mainConfigPath.substr(0, mainConfigPath.find_last_of('/'));
|
||||
// find_last_of never returns npos since main_config at least has /hypr/
|
||||
|
||||
if (!std::filesystem::is_directory(configPath)) {
|
||||
Debug::log(WARN, "Creating config home directory");
|
||||
try {
|
||||
std::filesystem::create_directories(configPath);
|
||||
} catch (...) {
|
||||
parseError = "Broken config file! (Could not create config directory)";
|
||||
return;
|
||||
if (g_pCompositor->explicitConfigPath.empty() && !std::filesystem::exists(mainConfigPath)) {
|
||||
std::string configPath = std::filesystem::path(mainConfigPath).parent_path();
|
||||
|
||||
if (!std::filesystem::is_directory(configPath)) {
|
||||
Debug::log(WARN, "Creating config home directory");
|
||||
try {
|
||||
std::filesystem::create_directories(configPath);
|
||||
} catch (...) {
|
||||
parseError = "Broken config file! (Could not create config directory)";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists(mainConfigPath)) {
|
||||
Debug::log(WARN, "No config file found; attempting to generate.");
|
||||
std::ofstream ofs;
|
||||
ofs.open(mainConfigPath, std::ios::trunc);
|
||||
@@ -1667,6 +1679,9 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
ensureVRR();
|
||||
}
|
||||
|
||||
if (!isFirstLaunch && !g_pCompositor->m_bUnsafeState)
|
||||
refreshGroupBarGradients();
|
||||
|
||||
// Updates dynamic window and workspace rules
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (!w->m_bIsMapped)
|
||||
@@ -2073,7 +2088,7 @@ void CConfigManager::performMonitorReload() {
|
||||
if (!m->output || m->isUnsafeFallback)
|
||||
continue;
|
||||
|
||||
auto rule = getMonitorRuleFor(m->szName, m->output->description ? m->output->description : "");
|
||||
auto rule = getMonitorRuleFor(m->szName, m->szDescription);
|
||||
|
||||
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) {
|
||||
overAgain = true;
|
||||
@@ -2154,7 +2169,7 @@ void CConfigManager::ensureMonitorStatus() {
|
||||
if (!rm->output || rm->isUnsafeFallback)
|
||||
continue;
|
||||
|
||||
auto rule = getMonitorRuleFor(rm->szName, rm->output->description ? rm->output->description : "");
|
||||
auto rule = getMonitorRuleFor(rm->szName, rm->szDescription);
|
||||
|
||||
if (rule.disabled == rm->m_bEnabled)
|
||||
g_pHyprRenderer->applyMonitorRule(rm.get(), &rule);
|
||||
|
@@ -37,20 +37,21 @@ struct SConfigValue {
|
||||
};
|
||||
|
||||
struct SWorkspaceRule {
|
||||
std::string monitor = "";
|
||||
std::string workspaceString = "";
|
||||
std::string workspaceName = "";
|
||||
int workspaceId = -1;
|
||||
bool isDefault = false;
|
||||
bool isPersistent = false;
|
||||
std::optional<int64_t> gapsIn;
|
||||
std::optional<int64_t> gapsOut;
|
||||
std::optional<int64_t> borderSize;
|
||||
std::optional<int> border;
|
||||
std::optional<int> rounding;
|
||||
std::optional<int> decorate;
|
||||
std::optional<int> shadow;
|
||||
std::optional<std::string> onCreatedEmptyRunCmd;
|
||||
std::string monitor = "";
|
||||
std::string workspaceString = "";
|
||||
std::string workspaceName = "";
|
||||
int workspaceId = -1;
|
||||
bool isDefault = false;
|
||||
bool isPersistent = false;
|
||||
std::optional<int64_t> gapsIn;
|
||||
std::optional<int64_t> gapsOut;
|
||||
std::optional<int64_t> borderSize;
|
||||
std::optional<int> border;
|
||||
std::optional<int> rounding;
|
||||
std::optional<int> decorate;
|
||||
std::optional<int> shadow;
|
||||
std::optional<std::string> onCreatedEmptyRunCmd;
|
||||
std::map<std::string, std::any> layoutopts;
|
||||
};
|
||||
|
||||
struct SMonitorAdditionalReservedArea {
|
||||
|
@@ -28,6 +28,11 @@ monitor=,preferred,auto,auto
|
||||
# Source a file (multi-file configs)
|
||||
# source = ~/.config/hypr/myColors.conf
|
||||
|
||||
# Set programs that you use
|
||||
$terminal = kitty
|
||||
$fileManager = dolphin
|
||||
$menu = wofi --show drun
|
||||
|
||||
# Some default env vars.
|
||||
env = XCURSOR_SIZE,24
|
||||
|
||||
@@ -127,18 +132,19 @@ device:epic-mouse-v1 {
|
||||
# Example windowrule v2
|
||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
||||
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
||||
windowrulev2 = nomaximizerequest, class:.* # You'll probably like this.
|
||||
|
||||
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/ for more
|
||||
$mainMod = SUPER
|
||||
|
||||
# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
|
||||
bind = $mainMod, Q, exec, kitty
|
||||
bind = $mainMod, Q, exec, $terminal
|
||||
bind = $mainMod, C, killactive,
|
||||
bind = $mainMod, M, exit,
|
||||
bind = $mainMod, E, exec, dolphin
|
||||
bind = $mainMod, E, exec, $fileManager
|
||||
bind = $mainMod, V, togglefloating,
|
||||
bind = $mainMod, R, exec, wofi --show drun
|
||||
bind = $mainMod, R, exec, $menu
|
||||
bind = $mainMod, P, pseudo, # dwindle
|
||||
bind = $mainMod, J, togglesplit, # dwindle
|
||||
|
||||
|
@@ -119,7 +119,7 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
|
||||
finalCrashReport += "\n\nLog tail:\n";
|
||||
|
||||
finalCrashReport += execAndGet(("cat \"" + Debug::logFile + "\" | tail -n 50").c_str());
|
||||
finalCrashReport += Debug::rollingLog;
|
||||
|
||||
const auto HOME = getenv("HOME");
|
||||
const auto CACHE_HOME = getenv("XDG_CACHE_HOME");
|
||||
|
@@ -28,13 +28,22 @@ static std::string getWorkspaceNameFromSpecialID(const int workspaceID) {
|
||||
return workspace->m_szName;
|
||||
}
|
||||
|
||||
std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat format) {
|
||||
CVarList vars(request, 0, ' ');
|
||||
auto allMonitors = false;
|
||||
|
||||
if (vars.size() > 2)
|
||||
return "too many args";
|
||||
|
||||
if (vars.size() == 2 && vars[1] == "all")
|
||||
allMonitors = true;
|
||||
|
||||
std::string result = "";
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
result += "[";
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (!m->output)
|
||||
for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) {
|
||||
if (!m->output || m->ID == -1ull)
|
||||
continue;
|
||||
|
||||
result += std::format(
|
||||
@@ -66,10 +75,11 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
"vrr": {},
|
||||
"activelyTearing": {}
|
||||
}},)#",
|
||||
m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->output->description ? m->output->description : ""), (m->output->make ? m->output->make : ""),
|
||||
m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->szDescription), (m->output->make ? m->output->make : ""),
|
||||
(m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate,
|
||||
(int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace, escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName),
|
||||
m->specialWorkspaceID, escapeJSONStrings(getWorkspaceNameFromSpecialID(m->specialWorkspaceID)), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
|
||||
(int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace,
|
||||
(m->activeWorkspace == -1 ? "" : escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName)), m->specialWorkspaceID,
|
||||
escapeJSONStrings(getWorkspaceNameFromSpecialID(m->specialWorkspaceID)), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
|
||||
(int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "true" : "false"),
|
||||
(m->dpmsStatus ? "true" : "false"), (m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED ? "true" : "false"),
|
||||
m->tearingState.activelyTearing ? "true" : "false");
|
||||
@@ -79,21 +89,21 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
|
||||
result += "]";
|
||||
} else {
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (!m->output)
|
||||
for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) {
|
||||
if (!m->output || m->ID == -1ull)
|
||||
continue;
|
||||
|
||||
result +=
|
||||
std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\tspecial "
|
||||
"workspace: {} ({})\n\treserved: {} "
|
||||
"{} {} {}\n\tscale: {:.2f}\n\ttransform: "
|
||||
"{}\n\tfocused: {}\n\tdpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\n",
|
||||
m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y,
|
||||
(m->output->description ? m->output->description : ""), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""),
|
||||
(m->output->serial ? m->output->serial : ""), m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName, m->specialWorkspaceID,
|
||||
getWorkspaceNameFromSpecialID(m->specialWorkspaceID), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x,
|
||||
(int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus,
|
||||
(int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED), m->tearingState.activelyTearing);
|
||||
result += std::format(
|
||||
"Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\tspecial "
|
||||
"workspace: {} ({})\n\treserved: {} "
|
||||
"{} {} {}\n\tscale: {:.2f}\n\ttransform: "
|
||||
"{}\n\tfocused: {}\n\tdpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\n",
|
||||
m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y,
|
||||
m->szDescription, (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""),
|
||||
(m->output->serial ? m->output->serial : ""), m->activeWorkspace, (m->activeWorkspace == -1 ? "" : g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName),
|
||||
m->specialWorkspaceID, getWorkspaceNameFromSpecialID(m->specialWorkspaceID), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y,
|
||||
(int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"),
|
||||
(int)m->dpmsStatus, (int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED), m->tearingState.activelyTearing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,7 +260,7 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, HyprCtl::eHyprC
|
||||
std::string result = std::format(R"#({{
|
||||
"workspaceString": "{}"{}{}{}{}{}{}{}{}
|
||||
}})#",
|
||||
escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow);
|
||||
escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow);
|
||||
|
||||
return result;
|
||||
} else {
|
||||
@@ -266,7 +276,7 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, HyprCtl::eHyprC
|
||||
const std::string shadow = std::format("\tshadow: {}\n", (bool)(r.shadow) ? boolToString(r.shadow.value()) : "<unset>");
|
||||
|
||||
std::string result = std::format("Workspace rule {}:\n{}{}{}{}{}{}{}{}{}{}\n", escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut,
|
||||
borderSize, border, rounding, decorate, shadow);
|
||||
borderSize, border, rounding, decorate, shadow);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -413,6 +423,28 @@ std::string layersRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string layoutsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string result = "";
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
result += "[";
|
||||
|
||||
for (auto& m : g_pLayoutManager->getAllLayoutNames()) {
|
||||
result += std::format(
|
||||
R"#(
|
||||
"{}",)#",
|
||||
m);
|
||||
}
|
||||
trimTrailingComma(result);
|
||||
|
||||
result += "\n]\n";
|
||||
} else {
|
||||
for (auto& m : g_pLayoutManager->getAllLayoutNames()) {
|
||||
result += std::format("{}\n", m);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string result = "";
|
||||
|
||||
@@ -625,6 +657,20 @@ std::string animationsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string rollinglogRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string result = "";
|
||||
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
result += "[\n\"log\":\"";
|
||||
result += escapeJSONStrings(Debug::rollingLog);
|
||||
result += "\"]";
|
||||
} else {
|
||||
result = Debug::rollingLog;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string globalShortcutsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string ret = "";
|
||||
const auto SHORTCUTS = g_pProtocolManager->m_pGlobalShortcutsProtocolManager->getAllShortcuts();
|
||||
@@ -1230,7 +1276,7 @@ std::string dispatchPlugin(std::string request) {
|
||||
const auto PLUGIN = g_pPluginSystem->loadPlugin(PATH);
|
||||
|
||||
if (!PLUGIN)
|
||||
return "error in loading plugin";
|
||||
return "error in loading plugin, last error: " + g_pPluginSystem->m_szLastError;
|
||||
} else if (OPERATION == "unload") {
|
||||
if (vars.size() < 3)
|
||||
return "not enough args";
|
||||
@@ -1319,8 +1365,8 @@ std::string getReply(std::string request) {
|
||||
request = request.substr(sepIndex + 1); // remove flags and separator so we can compare the rest of the string
|
||||
}
|
||||
|
||||
if (request == "monitors")
|
||||
return monitorsRequest(format);
|
||||
if (request.starts_with("monitors"))
|
||||
return monitorsRequest(request, format);
|
||||
else if (request == "workspaces")
|
||||
return workspacesRequest(format);
|
||||
else if (request == "workspacerules")
|
||||
@@ -1351,6 +1397,10 @@ std::string getReply(std::string request) {
|
||||
return globalShortcutsRequest(format);
|
||||
else if (request == "animations")
|
||||
return animationsRequest(format);
|
||||
else if (request == "rollinglog")
|
||||
return rollinglogRequest(format);
|
||||
else if (request == "layouts")
|
||||
return layoutsRequest(format);
|
||||
else if (request.starts_with("plugin"))
|
||||
return dispatchPlugin(request);
|
||||
else if (request.starts_with("notify"))
|
||||
@@ -1385,14 +1435,14 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP)
|
||||
return 0;
|
||||
|
||||
sockaddr_in clientAddress;
|
||||
socklen_t clientSize = sizeof(clientAddress);
|
||||
sockaddr_in clientAddress;
|
||||
socklen_t clientSize = sizeof(clientAddress);
|
||||
|
||||
const auto ACCEPTEDCONNECTION = accept4(HyprCtl::iSocketFD, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC);
|
||||
const auto ACCEPTEDCONNECTION = accept4(HyprCtl::iSocketFD, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC);
|
||||
|
||||
char readBuffer[1024];
|
||||
std::array<char, 1024> readBuffer;
|
||||
|
||||
fd_set fdset;
|
||||
fd_set fdset;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(ACCEPTEDCONNECTION, &fdset);
|
||||
timeval timeout = {.tv_sec = 0, .tv_usec = 5000};
|
||||
@@ -1403,10 +1453,17 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024);
|
||||
readBuffer[messageSize == 1024 ? 1023 : messageSize] = '\0';
|
||||
|
||||
std::string request(readBuffer);
|
||||
std::string request;
|
||||
while (true) {
|
||||
readBuffer.fill(0);
|
||||
auto messageSize = read(ACCEPTEDCONNECTION, readBuffer.data(), 1023);
|
||||
if (messageSize < 1)
|
||||
break;
|
||||
std::string recvd = readBuffer.data();
|
||||
request += recvd;
|
||||
if (messageSize < 1023)
|
||||
break;
|
||||
}
|
||||
|
||||
std::string reply = "";
|
||||
|
||||
|
@@ -19,7 +19,8 @@ namespace HyprCtl {
|
||||
|
||||
inline int iSocketFD = -1;
|
||||
|
||||
enum eHyprCtlOutputFormat {
|
||||
enum eHyprCtlOutputFormat
|
||||
{
|
||||
FORMAT_NORMAL = 0,
|
||||
FORMAT_JSON
|
||||
};
|
||||
|
@@ -10,25 +10,24 @@ void Debug::init(const std::string& IS) {
|
||||
}
|
||||
|
||||
void Debug::wlrLog(wlr_log_importance level, const char* fmt, va_list args) {
|
||||
if (disableLogs && *disableLogs)
|
||||
return;
|
||||
|
||||
if (level > wlr_log_get_verbosity())
|
||||
return;
|
||||
|
||||
char* outputStr = nullptr;
|
||||
|
||||
std::ofstream ofs;
|
||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||
char* outputStr = nullptr;
|
||||
|
||||
vasprintf(&outputStr, fmt, args);
|
||||
|
||||
std::string output = std::string(outputStr);
|
||||
free(outputStr);
|
||||
|
||||
ofs << "[wlr] " << output << "\n";
|
||||
rollingLog += output + "\n";
|
||||
|
||||
ofs.close();
|
||||
if (!disableLogs || !*disableLogs) {
|
||||
std::ofstream ofs;
|
||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||
ofs << "[wlr] " << output << "\n";
|
||||
ofs.close();
|
||||
}
|
||||
|
||||
if (!disableStdout)
|
||||
std::cout << output << "\n";
|
||||
|
@@ -7,9 +7,11 @@
|
||||
#include "../includes.hpp"
|
||||
#include "../helpers/MiscFunctions.hpp"
|
||||
|
||||
#define LOGMESSAGESIZE 1024
|
||||
#define LOGMESSAGESIZE 1024
|
||||
#define ROLLING_LOG_SIZE 4096
|
||||
|
||||
enum LogLevel {
|
||||
enum LogLevel
|
||||
{
|
||||
NONE = -1,
|
||||
LOG = 0,
|
||||
WARN,
|
||||
@@ -25,14 +27,17 @@ namespace Debug {
|
||||
inline int64_t* disableTime = nullptr;
|
||||
inline bool disableStdout = false;
|
||||
inline bool trace = false;
|
||||
inline bool shuttingDown = false;
|
||||
|
||||
inline std::string rollingLog = ""; // rolling log contains the ROLLING_LOG_SIZE tail of the log
|
||||
|
||||
void init(const std::string& IS);
|
||||
template <typename... Args>
|
||||
void log(LogLevel level, std::format_string<Args...> fmt, Args&&... args) {
|
||||
if (disableLogs && *disableLogs)
|
||||
if (level == TRACE && !trace)
|
||||
return;
|
||||
|
||||
if (level == TRACE && !trace)
|
||||
if (shuttingDown)
|
||||
return;
|
||||
|
||||
std::string logMsg = "";
|
||||
@@ -47,10 +52,6 @@ namespace Debug {
|
||||
default: break;
|
||||
}
|
||||
|
||||
// log to a file
|
||||
std::ofstream ofs;
|
||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||
|
||||
// print date and time to the ofs
|
||||
if (disableTime && !*disableTime) {
|
||||
#ifndef _LIBCPP_VERSION
|
||||
@@ -69,9 +70,18 @@ namespace Debug {
|
||||
// 3. this is actually what std::format in stdlib does
|
||||
logMsg += std::vformat(fmt.get(), std::make_format_args(args...));
|
||||
|
||||
ofs << logMsg << "\n";
|
||||
rollingLog += logMsg + "\n";
|
||||
if (rollingLog.size() > ROLLING_LOG_SIZE)
|
||||
rollingLog = rollingLog.substr(rollingLog.size() - ROLLING_LOG_SIZE);
|
||||
|
||||
ofs.close();
|
||||
if (!disableLogs || !*disableLogs) {
|
||||
// log to a file
|
||||
std::ofstream ofs;
|
||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||
ofs << logMsg << "\n";
|
||||
|
||||
ofs.close();
|
||||
}
|
||||
|
||||
// log it to the stdout too.
|
||||
if (!disableStdout)
|
||||
|
@@ -13,15 +13,6 @@ 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({}) failed", name);
|
||||
abort();
|
||||
}
|
||||
*(void**)pProc = proc;
|
||||
}
|
||||
|
||||
#define TRACY_GPU_CONTEXT TracyGpuContext
|
||||
#define TRACY_GPU_ZONE(e) TracyGpuZone(e)
|
||||
#define TRACY_GPU_COLLECT TracyGpuCollect
|
||||
|
@@ -42,7 +42,7 @@ namespace Events {
|
||||
DYNLISTENFUNC(repositionPopupXDG);
|
||||
|
||||
// Surface XDG (window)
|
||||
LISTENER(newXDGSurface);
|
||||
LISTENER(newXDGToplevel);
|
||||
LISTENER(activateXDG);
|
||||
|
||||
// Window events
|
||||
@@ -121,10 +121,6 @@ namespace Events {
|
||||
DYNLISTENFUNC(destroyDragIcon);
|
||||
DYNLISTENFUNC(commitDragIcon);
|
||||
|
||||
// Inhibit
|
||||
LISTENER(InhibitActivate);
|
||||
LISTENER(InhibitDeactivate);
|
||||
|
||||
// Deco XDG
|
||||
LISTENER(NewXDGDeco);
|
||||
|
||||
|
@@ -254,6 +254,8 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
||||
geomFixed = {layersurface->geometry.x + (int)PMONITOR->vecPosition.x, layersurface->geometry.y + (int)PMONITOR->vecPosition.y,
|
||||
(int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
}
|
||||
|
||||
void Events::listener_commitLayerSurface(void* owner, void* data) {
|
||||
|
@@ -156,20 +156,6 @@ void Events::listener_commitDragIcon(void* owner, void* data) {
|
||||
Debug::log(LOG, "Drag icon committed.");
|
||||
}
|
||||
|
||||
void Events::listener_InhibitActivate(wl_listener* listener, void* data) {
|
||||
Debug::log(LOG, "Activated exclusive for {:x}.", (uintptr_t)g_pCompositor->m_sSeat.exclusiveClient);
|
||||
|
||||
g_pInputManager->refocus();
|
||||
g_pCompositor->m_sSeat.exclusiveClient = g_pCompositor->m_sWLRInhibitMgr->active_client;
|
||||
}
|
||||
|
||||
void Events::listener_InhibitDeactivate(wl_listener* listener, void* data) {
|
||||
Debug::log(LOG, "Deactivated exclusive.");
|
||||
|
||||
g_pCompositor->m_sSeat.exclusiveClient = nullptr;
|
||||
g_pInputManager->refocus();
|
||||
}
|
||||
|
||||
void Events::listener_RendererDestroy(wl_listener* listener, void* data) {
|
||||
Debug::log(LOG, "!!Renderer destroyed!!");
|
||||
}
|
||||
|
@@ -22,10 +22,13 @@ void Events::listener_change(wl_listener* listener, void* data) {
|
||||
if (!CONFIG)
|
||||
return;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
if (!m->output)
|
||||
continue;
|
||||
|
||||
if (g_pCompositor->m_pUnsafeOutput == m.get())
|
||||
continue;
|
||||
|
||||
const auto CONFIGHEAD = wlr_output_configuration_head_v1_create(CONFIG, m->output);
|
||||
|
||||
CBox BOX;
|
||||
@@ -195,7 +198,7 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||
|
||||
Debug::log(LOG, "Destroy called for monitor {}", pMonitor->output->name);
|
||||
|
||||
pMonitor->onDisconnect();
|
||||
pMonitor->onDisconnect(true);
|
||||
|
||||
pMonitor->output = nullptr;
|
||||
pMonitor->m_bRenderingInitPassed = false;
|
||||
|
@@ -246,20 +246,6 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
}
|
||||
vPrev = v;
|
||||
}
|
||||
} else if (r.szRule.starts_with("idleinhibit")) {
|
||||
auto IDLERULE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
||||
|
||||
if (IDLERULE == "none") {
|
||||
PWINDOW->m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
||||
} else if (IDLERULE == "always") {
|
||||
PWINDOW->m_eIdleInhibitMode = IDLEINHIBIT_ALWAYS;
|
||||
} else if (IDLERULE == "focus") {
|
||||
PWINDOW->m_eIdleInhibitMode = IDLEINHIBIT_FOCUS;
|
||||
} else if (IDLERULE == "fullscreen") {
|
||||
PWINDOW->m_eIdleInhibitMode = IDLEINHIBIT_FULLSCREEN;
|
||||
} else {
|
||||
Debug::log(ERR, "Rule idleinhibit: unknown mode {}", IDLERULE);
|
||||
}
|
||||
}
|
||||
PWINDOW->applyDynamicRule(r);
|
||||
}
|
||||
@@ -279,7 +265,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
std::string requestedWorkspaceName;
|
||||
const int REQUESTEDWORKSPACEID = getWorkspaceIDFromString(WORKSPACEARGS.join(" ", 0, workspaceSilent ? WORKSPACEARGS.size() - 1 : 0), requestedWorkspaceName);
|
||||
|
||||
if (REQUESTEDWORKSPACEID != INT_MAX) {
|
||||
if (REQUESTEDWORKSPACEID != WORKSPACE_INVALID) {
|
||||
auto pWorkspace = g_pCompositor->getWorkspaceByID(REQUESTEDWORKSPACEID);
|
||||
|
||||
if (!pWorkspace)
|
||||
@@ -1183,14 +1169,12 @@ void Events::listener_surfaceXWayland(wl_listener* listener, void* data) {
|
||||
PNEWWINDOW->hyprListener_configureX11.initCallback(&XWSURFACE->events.request_configure, &Events::listener_configureX11, PNEWWINDOW, "XWayland Window");
|
||||
}
|
||||
|
||||
void Events::listener_newXDGSurface(wl_listener* listener, void* data) {
|
||||
void Events::listener_newXDGToplevel(wl_listener* listener, void* data) {
|
||||
// A window got opened
|
||||
const auto XDGSURFACE = (wlr_xdg_surface*)data;
|
||||
const auto XDGTOPLEVEL = (wlr_xdg_toplevel*)data;
|
||||
const auto XDGSURFACE = XDGTOPLEVEL->base;
|
||||
|
||||
if (XDGSURFACE->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL)
|
||||
return;
|
||||
|
||||
Debug::log(LOG, "New XDG Surface created. (class: {})", XDGSURFACE->toplevel->app_id ? XDGSURFACE->toplevel->app_id : "null");
|
||||
Debug::log(LOG, "New XDG Toplevel created. (class: {})", XDGSURFACE->toplevel->app_id ? XDGSURFACE->toplevel->app_id : "null");
|
||||
|
||||
const auto PNEWWINDOW = g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
|
||||
PNEWWINDOW->m_uSurface.xdg = XDGSURFACE;
|
||||
|
@@ -112,6 +112,10 @@ CBox CBox::roundInternal() {
|
||||
return CBox{std::floor(x), std::floor(y), std::floor(newW), std::floor(newH)};
|
||||
}
|
||||
|
||||
CBox CBox::copy() const {
|
||||
return CBox{*this};
|
||||
}
|
||||
|
||||
Vector2D CBox::pos() const {
|
||||
return {x, y};
|
||||
}
|
||||
|
@@ -52,6 +52,8 @@ class CBox {
|
||||
CBox& addExtents(const SWindowDecorationExtents& e);
|
||||
CBox& expand(const double& value);
|
||||
|
||||
CBox copy() const;
|
||||
|
||||
SWindowDecorationExtents extentsFrom(const CBox&); // this is the big box
|
||||
|
||||
Vector2D middle() const;
|
||||
|
@@ -204,12 +204,12 @@ std::string removeBeginEndSpacesTabs(std::string str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
float getPlusMinusKeywordResult(std::string source, float relative) {
|
||||
std::optional<float> getPlusMinusKeywordResult(std::string source, float relative) {
|
||||
try {
|
||||
return relative + stof(source);
|
||||
} catch (...) {
|
||||
Debug::log(ERR, "Invalid arg \"{}\" in getPlusMinusKeywordResult!", source);
|
||||
return INT_MAX;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ bool isDirection(const char& arg) {
|
||||
}
|
||||
|
||||
int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
int result = INT_MAX;
|
||||
int result = WORKSPACE_INVALID;
|
||||
if (in.starts_with("special")) {
|
||||
outName = "special";
|
||||
|
||||
@@ -280,17 +280,17 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
}
|
||||
} else if (in.starts_with("prev")) {
|
||||
if (!g_pCompositor->m_pLastMonitor)
|
||||
return INT_MAX;
|
||||
return WORKSPACE_INVALID;
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
|
||||
|
||||
if (!PWORKSPACE)
|
||||
return INT_MAX;
|
||||
return WORKSPACE_INVALID;
|
||||
|
||||
const auto PLASTWORKSPACE = g_pCompositor->getWorkspaceByID(PWORKSPACE->m_sPrevWorkspace.iID);
|
||||
|
||||
if (!PLASTWORKSPACE)
|
||||
return INT_MAX;
|
||||
return WORKSPACE_INVALID;
|
||||
|
||||
outName = PLASTWORKSPACE->m_szName;
|
||||
return PLASTWORKSPACE->m_iID;
|
||||
@@ -298,10 +298,15 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
if (in[0] == 'r' && (in[1] == '-' || in[1] == '+') && isNumber(in.substr(2))) {
|
||||
if (!g_pCompositor->m_pLastMonitor) {
|
||||
Debug::log(ERR, "Relative monitor workspace on monitor null!");
|
||||
result = INT_MAX;
|
||||
return result;
|
||||
return WORKSPACE_INVALID;
|
||||
}
|
||||
result = (int)getPlusMinusKeywordResult(in.substr(1), 0);
|
||||
|
||||
const auto PLUSMINUSRESULT = getPlusMinusKeywordResult(in.substr(1), 0);
|
||||
|
||||
if (!PLUSMINUSRESULT.has_value())
|
||||
return WORKSPACE_INVALID;
|
||||
|
||||
result = (int)PLUSMINUSRESULT.value();
|
||||
|
||||
int remains = (int)result;
|
||||
|
||||
@@ -433,12 +438,16 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
|
||||
if (!g_pCompositor->m_pLastMonitor) {
|
||||
Debug::log(ERR, "Relative monitor workspace on monitor null!");
|
||||
result = INT_MAX;
|
||||
return result;
|
||||
return WORKSPACE_INVALID;
|
||||
}
|
||||
|
||||
// monitor relative
|
||||
result = (int)getPlusMinusKeywordResult(in.substr(1), 0);
|
||||
const auto PLUSMINUSRESULT = getPlusMinusKeywordResult(in.substr(1), 0);
|
||||
|
||||
if (!PLUSMINUSRESULT.has_value())
|
||||
return WORKSPACE_INVALID;
|
||||
|
||||
result = (int)PLUSMINUSRESULT.value();
|
||||
|
||||
// result now has +/- what we should move on mon
|
||||
int remains = (int)result;
|
||||
@@ -479,11 +488,15 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
outName = g_pCompositor->getWorkspaceByID(validWSes[currentItem])->m_szName;
|
||||
} else {
|
||||
if (in[0] == '+' || in[0] == '-') {
|
||||
if (g_pCompositor->m_pLastMonitor)
|
||||
result = std::max((int)getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace), 1);
|
||||
else {
|
||||
if (g_pCompositor->m_pLastMonitor) {
|
||||
const auto PLUSMINUSRESULT = getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace);
|
||||
if (!PLUSMINUSRESULT.has_value())
|
||||
return WORKSPACE_INVALID;
|
||||
|
||||
result = std::max((int)PLUSMINUSRESULT.value(), 1);
|
||||
} else {
|
||||
Debug::log(ERR, "Relative workspace on no mon!");
|
||||
result = INT_MAX;
|
||||
return WORKSPACE_INVALID;
|
||||
}
|
||||
} else if (isNumber(in))
|
||||
result = std::max(std::stoi(in), 1);
|
||||
@@ -695,6 +708,10 @@ int64_t configStringToInt(const std::string& VALUE) {
|
||||
} else if (VALUE.starts_with("false") || VALUE.starts_with("off") || VALUE.starts_with("no")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (VALUE.empty() || !isNumber(VALUE))
|
||||
return 0;
|
||||
|
||||
return std::stoll(VALUE);
|
||||
}
|
||||
|
||||
@@ -764,4 +781,14 @@ uint32_t drmFormatToGL(uint32_t drm) {
|
||||
}
|
||||
UNREACHABLE();
|
||||
return GL_RGBA;
|
||||
}
|
||||
|
||||
uint32_t glFormatToType(uint32_t gl) {
|
||||
return gl != GL_RGBA ?
|
||||
#ifdef GLES2
|
||||
GL_UNSIGNED_INT_2_10_10_10_REV_EXT :
|
||||
#else
|
||||
GL_UNSIGNED_INT_2_10_10_10_REV :
|
||||
#endif
|
||||
GL_UNSIGNED_BYTE;
|
||||
}
|
@@ -27,13 +27,14 @@ void logSystemInfo();
|
||||
std::string execAndGet(const char*);
|
||||
int64_t getPPIDof(int64_t pid);
|
||||
int64_t configStringToInt(const std::string&);
|
||||
float getPlusMinusKeywordResult(std::string in, float relative);
|
||||
std::optional<float> getPlusMinusKeywordResult(std::string in, float relative);
|
||||
void matrixProjection(float mat[9], int w, int h, wl_output_transform tr);
|
||||
double normalizeAngleRad(double ang);
|
||||
std::string replaceInString(std::string subject, const std::string& search, const std::string& replace);
|
||||
std::vector<SCallstackFrameInfo> getBacktrace();
|
||||
void throwError(const std::string& err);
|
||||
uint32_t drmFormatToGL(uint32_t drm);
|
||||
uint32_t glFormatToType(uint32_t gl);
|
||||
|
||||
template <typename... Args>
|
||||
[[deprecated("use std::format instead")]] std::string getFormat(std::format_string<Args...> fmt, Args&&... args) {
|
||||
|
@@ -50,6 +50,10 @@ void CMonitor::onConnect(bool noRule) {
|
||||
|
||||
szName = output->name;
|
||||
|
||||
szDescription = output->description ? output->description : "";
|
||||
// remove comma character from description. This allow monitor specific rules to work on monitor with comma on their description
|
||||
szDescription.erase(std::remove(szDescription.begin(), szDescription.end(), ','), szDescription.end());
|
||||
|
||||
if (!wlr_backend_is_drm(output->backend))
|
||||
createdByUser = true; // should be true. WL, X11 and Headless backends should be addable / removable
|
||||
|
||||
@@ -188,7 +192,7 @@ void CMonitor::onConnect(bool noRule) {
|
||||
g_pCompositor->scheduleFrameForMonitor(this);
|
||||
}
|
||||
|
||||
void CMonitor::onDisconnect() {
|
||||
void CMonitor::onDisconnect(bool destroy) {
|
||||
|
||||
if (renderTimer) {
|
||||
wl_event_source_remove(renderTimer);
|
||||
@@ -276,7 +280,8 @@ void CMonitor::onDisconnect() {
|
||||
|
||||
activeWorkspace = -1;
|
||||
|
||||
wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output);
|
||||
if (!destroy)
|
||||
wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output);
|
||||
|
||||
wlr_output_enable(output, false);
|
||||
|
||||
@@ -298,7 +303,6 @@ void CMonitor::onDisconnect() {
|
||||
|
||||
g_pHyprRenderer->m_pMostHzMonitor = pMonitorMostHz;
|
||||
}
|
||||
|
||||
std::erase_if(g_pCompositor->m_vMonitors, [&](std::shared_ptr<CMonitor>& el) { return el.get() == this; });
|
||||
}
|
||||
|
||||
@@ -353,7 +357,7 @@ void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) {
|
||||
findAvailableDefaultWS() :
|
||||
getWorkspaceIDFromString(g_pConfigManager->getDefaultWorkspaceFor(szName), newDefaultWorkspaceName);
|
||||
|
||||
if (WORKSPACEID == INT_MAX || (WORKSPACEID >= SPECIAL_WORKSPACE_START && WORKSPACEID <= -2)) {
|
||||
if (WORKSPACEID == WORKSPACE_INVALID || (WORKSPACEID >= SPECIAL_WORKSPACE_START && WORKSPACEID <= -2)) {
|
||||
WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1;
|
||||
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
|
||||
|
||||
@@ -642,4 +646,13 @@ void CMonitor::moveTo(const Vector2D& pos) {
|
||||
|
||||
Vector2D CMonitor::middle() {
|
||||
return vecPosition + vecSize / 2.f;
|
||||
}
|
||||
}
|
||||
|
||||
void CMonitor::updateMatrix() {
|
||||
wlr_matrix_identity(projMatrix.data());
|
||||
if (transform != WL_OUTPUT_TRANSFORM_NORMAL) {
|
||||
wlr_matrix_translate(projMatrix.data(), vecPixelSize.x / 2.0, vecPixelSize.y / 2.0);
|
||||
wlr_matrix_transform(projMatrix.data(), transform);
|
||||
wlr_matrix_translate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0);
|
||||
}
|
||||
}
|
||||
|
@@ -43,6 +43,7 @@ class CMonitor {
|
||||
float scale = 1;
|
||||
|
||||
std::string szName = "";
|
||||
std::string szDescription = "";
|
||||
|
||||
Vector2D vecReservedTopLeft = Vector2D(0, 0);
|
||||
Vector2D vecReservedBottomRight = Vector2D(0, 0);
|
||||
@@ -50,32 +51,33 @@ class CMonitor {
|
||||
drmModeModeInfo customDrmMode = {};
|
||||
|
||||
// WLR stuff
|
||||
wlr_damage_ring damage;
|
||||
wlr_output* output = nullptr;
|
||||
float refreshRate = 60;
|
||||
int framesToSkip = 0;
|
||||
int forceFullFrames = 0;
|
||||
bool noFrameSchedule = false;
|
||||
bool scheduledRecalc = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
bool gammaChanged = false;
|
||||
float xwaylandScale = 1.f;
|
||||
wlr_damage_ring damage;
|
||||
wlr_output* output = nullptr;
|
||||
float refreshRate = 60;
|
||||
int framesToSkip = 0;
|
||||
int forceFullFrames = 0;
|
||||
bool noFrameSchedule = false;
|
||||
bool scheduledRecalc = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
bool gammaChanged = false;
|
||||
float xwaylandScale = 1.f;
|
||||
std::array<float, 9> projMatrix = {0};
|
||||
|
||||
bool dpmsStatus = true;
|
||||
bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
||||
bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
|
||||
bool createdByUser = false;
|
||||
uint32_t drmFormat = DRM_FORMAT_INVALID;
|
||||
bool isUnsafeFallback = false;
|
||||
bool dpmsStatus = true;
|
||||
bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it.
|
||||
bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed.
|
||||
bool createdByUser = false;
|
||||
uint32_t drmFormat = DRM_FORMAT_INVALID;
|
||||
bool isUnsafeFallback = false;
|
||||
|
||||
bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after
|
||||
bool renderingActive = false;
|
||||
bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after
|
||||
bool renderingActive = false;
|
||||
|
||||
wl_event_source* renderTimer = nullptr; // for RAT
|
||||
bool RATScheduled = false;
|
||||
CTimer lastPresentationTimer;
|
||||
wl_event_source* renderTimer = nullptr; // for RAT
|
||||
bool RATScheduled = false;
|
||||
CTimer lastPresentationTimer;
|
||||
|
||||
SMonitorRule activeMonitorRule;
|
||||
SMonitorRule activeMonitorRule;
|
||||
|
||||
// mirroring
|
||||
CMonitor* pMirrorOf = nullptr;
|
||||
@@ -110,7 +112,7 @@ class CMonitor {
|
||||
|
||||
// methods
|
||||
void onConnect(bool noRule);
|
||||
void onDisconnect();
|
||||
void onDisconnect(bool destroy = false);
|
||||
void addDamage(const pixman_region32_t* rg);
|
||||
void addDamage(const CRegion* rg);
|
||||
void addDamage(const CBox* box);
|
||||
@@ -123,6 +125,7 @@ class CMonitor {
|
||||
void setSpecialWorkspace(const int& id);
|
||||
void moveTo(const Vector2D& pos);
|
||||
Vector2D middle();
|
||||
void updateMatrix();
|
||||
|
||||
bool m_bEnabled = false;
|
||||
bool m_bRenderingInitPassed = false;
|
||||
|
@@ -88,11 +88,25 @@ CRegion& CRegion::invert(pixman_box32_t* box) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::invert(const CBox& box) {
|
||||
pixman_box32 pixmanBox = {box.x, box.y, box.w + box.x, box.h + box.y};
|
||||
return this->invert(&pixmanBox);
|
||||
}
|
||||
|
||||
CRegion& CRegion::translate(const Vector2D& vec) {
|
||||
pixman_region32_translate(&m_rRegion, vec.x, vec.y);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::transform(const wl_output_transform t, double w, double h) {
|
||||
wlr_region_transform(&m_rRegion, &m_rRegion, t, w, h);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion CRegion::copy() const {
|
||||
return CRegion(*this);
|
||||
}
|
||||
|
||||
CRegion& CRegion::scale(float scale) {
|
||||
wlr_region_scale(&m_rRegion, &m_rRegion, scale);
|
||||
return *this;
|
||||
|
@@ -45,12 +45,15 @@ class CRegion {
|
||||
CRegion& intersect(const CRegion& other);
|
||||
CRegion& intersect(double x, double y, double w, double h);
|
||||
CRegion& translate(const Vector2D& vec);
|
||||
CRegion& transform(const wl_output_transform t, double w, double h);
|
||||
CRegion& invert(pixman_box32_t* box);
|
||||
CRegion& invert(const CBox& box);
|
||||
CRegion& scale(float scale);
|
||||
CBox getExtents();
|
||||
bool containsPoint(const Vector2D& vec) const;
|
||||
bool empty() const;
|
||||
Vector2D closestPoint(const Vector2D& vec) const;
|
||||
CRegion copy() const;
|
||||
|
||||
std::vector<pixman_box32_t> getRects() const;
|
||||
|
||||
|
@@ -220,6 +220,8 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
|
||||
|
||||
// no damaging if it's not visible
|
||||
if (!g_pHyprRenderer->shouldRenderWindow(pNode->pWindowOwner)) {
|
||||
pNode->lastSize = pNode->pSurface->exists() ? Vector2D{pNode->pSurface->wlr()->current.width, pNode->pSurface->wlr()->current.height} : Vector2D{};
|
||||
|
||||
static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
||||
if (*PLOGDAMAGE)
|
||||
Debug::log(LOG, "Refusing to commit damage from {} because it's invisible.", pNode->pWindowOwner);
|
||||
@@ -244,9 +246,13 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
|
||||
}
|
||||
}
|
||||
|
||||
if (pNode->pSurface && pNode->pSurface->exists())
|
||||
if (pNode->pSurface && pNode->pSurface->exists()) {
|
||||
g_pHyprRenderer->damageSurface(pNode->pSurface->wlr(), lx, ly, SCALE);
|
||||
|
||||
if (pNode->lastSize != Vector2D{pNode->pSurface->wlr()->current.width, pNode->pSurface->wlr()->current.height} && pNode->pWindowOwner)
|
||||
g_pHyprRenderer->damageWindow(pNode->pWindowOwner);
|
||||
}
|
||||
|
||||
if (pNode->pWindowOwner) {
|
||||
if (pNode->pWindowOwner->m_bIsX11)
|
||||
pNode->pWindowOwner->m_vReportedSize = pNode->pWindowOwner->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged.
|
||||
@@ -269,6 +275,8 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pNode->lastSize = pNode->pSurface->exists() ? Vector2D{pNode->pSurface->wlr()->current.width, pNode->pSurface->wlr()->current.height} : Vector2D{};
|
||||
}
|
||||
|
||||
void Events::listener_destroySubsurface(void* owner, void* data) {
|
||||
|
@@ -26,6 +26,8 @@ struct SSurfaceTreeNode {
|
||||
void* globalOffsetData;
|
||||
CWindow* pWindowOwner = nullptr;
|
||||
|
||||
Vector2D lastSize;
|
||||
|
||||
//
|
||||
bool operator==(const SSurfaceTreeNode& rhs) const {
|
||||
return pSurface == rhs.pSurface;
|
||||
|
@@ -25,10 +25,10 @@ class Vector2D {
|
||||
Vector2D operator-() const {
|
||||
return Vector2D(-this->x, -this->y);
|
||||
}
|
||||
Vector2D operator*(const float& a) const {
|
||||
Vector2D operator*(const double& a) const {
|
||||
return Vector2D(this->x * a, this->y * a);
|
||||
}
|
||||
Vector2D operator/(const float& a) const {
|
||||
Vector2D operator/(const double& a) const {
|
||||
return Vector2D(this->x / a, this->y / a);
|
||||
}
|
||||
|
||||
@@ -55,6 +55,36 @@ class Vector2D {
|
||||
bool operator<(const Vector2D& a) const {
|
||||
return this->x < a.x && this->y < a.y;
|
||||
}
|
||||
Vector2D& operator+=(const Vector2D& a) {
|
||||
this->x += a.x;
|
||||
this->y += a.y;
|
||||
return *this;
|
||||
}
|
||||
Vector2D& operator-=(const Vector2D& a) {
|
||||
this->x -= a.x;
|
||||
this->y -= a.y;
|
||||
return *this;
|
||||
}
|
||||
Vector2D& operator*=(const Vector2D& a) {
|
||||
this->x *= a.x;
|
||||
this->y *= a.y;
|
||||
return *this;
|
||||
}
|
||||
Vector2D& operator/=(const Vector2D& a) {
|
||||
this->x /= a.x;
|
||||
this->y /= a.y;
|
||||
return *this;
|
||||
}
|
||||
Vector2D& operator*=(const double& a) {
|
||||
this->x *= a;
|
||||
this->y *= a;
|
||||
return *this;
|
||||
}
|
||||
Vector2D& operator/=(const double& a) {
|
||||
this->x /= a;
|
||||
this->y /= a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
double distance(const Vector2D& other) const;
|
||||
double size() const;
|
||||
|
@@ -8,6 +8,14 @@ SLayerSurface::SLayerSurface() {
|
||||
alpha.registerVar();
|
||||
}
|
||||
|
||||
SLayerSurface::~SLayerSurface() {
|
||||
if (!g_pHyprOpenGL)
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
std::erase_if(g_pHyprOpenGL->m_mLayerFramebuffers, [&](const auto& other) { return other.first == this; });
|
||||
}
|
||||
|
||||
void SLayerSurface::applyRules() {
|
||||
noAnimations = false;
|
||||
forceBlur = false;
|
||||
|
@@ -16,6 +16,7 @@ struct SLayerRule {
|
||||
|
||||
struct SLayerSurface {
|
||||
SLayerSurface();
|
||||
~SLayerSurface();
|
||||
|
||||
void applyRules();
|
||||
|
||||
|
@@ -65,7 +65,7 @@ void CWLSurface::destroy() {
|
||||
if (g_pInputManager->m_pLastMouseSurface == m_pWLRSurface)
|
||||
g_pInputManager->m_pLastMouseSurface = nullptr;
|
||||
if (g_pHyprRenderer->m_sLastCursorData.surf == m_pWLRSurface)
|
||||
g_pInputManager->setCursorImageOverride("left_ptr");
|
||||
g_pHyprRenderer->m_sLastCursorData.surf.reset();
|
||||
|
||||
m_pWLRSurface = nullptr;
|
||||
|
||||
|
@@ -38,7 +38,8 @@ CWorkspace::~CWorkspace() {
|
||||
}
|
||||
|
||||
void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle;
|
||||
const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle;
|
||||
const auto PWORKSPACEGAP = &g_pConfigManager->getConfigValuePtr("general:gaps_workspaces")->intValue;
|
||||
|
||||
if (ANIMSTYLE.starts_with("slidefade")) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
@@ -90,26 +91,28 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
} else if (ANIMSTYLE == "slidevert") {
|
||||
// fallback is slide
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
const auto YDISTANCE = PMONITOR->vecSize.y + *PWORKSPACEGAP;
|
||||
|
||||
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
|
||||
|
||||
if (in) {
|
||||
m_vRenderOffset.setValueAndWarp(Vector2D(0, left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y));
|
||||
m_vRenderOffset.setValueAndWarp(Vector2D(0, left ? YDISTANCE : -YDISTANCE));
|
||||
m_vRenderOffset = Vector2D(0, 0);
|
||||
} else {
|
||||
m_vRenderOffset = Vector2D(0, left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y);
|
||||
m_vRenderOffset = Vector2D(0, left ? -YDISTANCE : YDISTANCE);
|
||||
}
|
||||
} else {
|
||||
// fallback is slide
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
const auto XDISTANCE = PMONITOR->vecSize.x + *PWORKSPACEGAP;
|
||||
|
||||
m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
|
||||
|
||||
if (in) {
|
||||
m_vRenderOffset.setValueAndWarp(Vector2D(left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x, 0));
|
||||
m_vRenderOffset.setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0));
|
||||
m_vRenderOffset = Vector2D(0, 0);
|
||||
} else {
|
||||
m_vRenderOffset = Vector2D(left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x, 0);
|
||||
m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -70,7 +70,6 @@ extern "C" {
|
||||
#include <wlr/types/wlr_xdg_shell.h>
|
||||
#include <wlr/types/wlr_subcompositor.h>
|
||||
#include <wlr/types/wlr_damage_ring.h>
|
||||
#include <wlr/types/wlr_input_inhibitor.h>
|
||||
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
|
||||
#include <wlr/types/wlr_virtual_pointer_v1.h>
|
||||
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
|
||||
@@ -106,6 +105,9 @@ extern "C" {
|
||||
#include <wlr/types/wlr_cursor_shape_v1.h>
|
||||
#include <wlr/types/wlr_tearing_control_v1.h>
|
||||
#include <wlr/util/box.h>
|
||||
#include <wlr/util/transform.h>
|
||||
#include <wlr/render/swapchain.h>
|
||||
#include <wlr/render/egl.h>
|
||||
|
||||
#include <libdrm/drm_fourcc.h>
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#include "IHyprLayout.hpp"
|
||||
#include "../defines.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
||||
|
||||
void IHyprLayout::onWindowCreated(CWindow* pWindow, eDirection direction) {
|
||||
if (pWindow->m_bIsFloating) {
|
||||
@@ -264,10 +265,36 @@ void IHyprLayout::onEndDragWindow() {
|
||||
g_pInputManager->refocus();
|
||||
changeWindowFloatingMode(DRAGGINGWINDOW);
|
||||
DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize;
|
||||
} else if (g_pInputManager->dragMode == MBIND_MOVE) {
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
|
||||
CWindow* pWindow = g_pCompositor->vectorToWindowIdeal(MOUSECOORDS, DRAGGINGWINDOW);
|
||||
|
||||
if (pWindow && pWindow->m_bIsFloating) {
|
||||
for (auto& wd : pWindow->m_dWindowDecorations) {
|
||||
if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))
|
||||
continue;
|
||||
|
||||
if (g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(MOUSECOORDS)) {
|
||||
if (!wd->onEndWindowDragOnDeco(DRAGGINGWINDOW, MOUSECOORDS))
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pWindow->m_sGroupData.pNextWindow && DRAGGINGWINDOW->canBeGroupedInto(pWindow)) {
|
||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue;
|
||||
(*USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW);
|
||||
pWindow->setGroupCurrent(DRAGGINGWINDOW);
|
||||
DRAGGINGWINDOW->updateWindowDecos();
|
||||
|
||||
if (!DRAGGINGWINDOW->getDecorationByType(DECORATION_GROUPBAR))
|
||||
DRAGGINGWINDOW->addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(DRAGGINGWINDOW));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
|
||||
g_pCompositor->focusWindow(DRAGGINGWINDOW);
|
||||
|
||||
g_pInputManager->m_bWasDraggingWindow = false;
|
||||
@@ -427,7 +454,8 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
|
||||
const auto PSAVEDSIZE = pWindow->m_vRealSize.goalv();
|
||||
|
||||
// if the window is pseudo, update its size
|
||||
pWindow->m_vPseudoSize = pWindow->m_vRealSize.goalv();
|
||||
if (!pWindow->m_bDraggingTiled)
|
||||
pWindow->m_vPseudoSize = pWindow->m_vRealSize.goalv();
|
||||
|
||||
pWindow->m_vLastFloatingSize = PSAVEDSIZE;
|
||||
|
||||
|
@@ -42,13 +42,21 @@ SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const int& ws) {
|
||||
const auto PWORKSPACEDATA = &m_lMasterWorkspacesData.emplace_back();
|
||||
PWORKSPACEDATA->workspaceID = ws;
|
||||
const auto orientation = &g_pConfigManager->getConfigValuePtr("master:orientation")->strValue;
|
||||
if (*orientation == "top") {
|
||||
const auto layoutoptsForWs = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(ws)).layoutopts;
|
||||
auto orientationForWs = *orientation;
|
||||
|
||||
try {
|
||||
if (layoutoptsForWs.contains("orientation"))
|
||||
orientationForWs = std::any_cast<std::string>(layoutoptsForWs.at("orientation"));
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Error from layoutopt rules: {}", e.what()); }
|
||||
|
||||
if (orientationForWs == "top") {
|
||||
PWORKSPACEDATA->orientation = ORIENTATION_TOP;
|
||||
} else if (*orientation == "right") {
|
||||
} else if (orientationForWs == "right") {
|
||||
PWORKSPACEDATA->orientation = ORIENTATION_RIGHT;
|
||||
} else if (*orientation == "bottom") {
|
||||
} else if (orientationForWs == "bottom") {
|
||||
PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM;
|
||||
} else if (*orientation == "left") {
|
||||
} else if (orientationForWs == "left") {
|
||||
PWORKSPACEDATA->orientation = ORIENTATION_LEFT;
|
||||
} else {
|
||||
PWORKSPACEDATA->orientation = ORIENTATION_CENTER;
|
||||
|
@@ -22,6 +22,8 @@
|
||||
|
||||
#define STRVAL_EMPTY "[[EMPTY]]"
|
||||
|
||||
#define WORKSPACE_INVALID -1L
|
||||
|
||||
#define LISTENER(name) \
|
||||
void listener_##name(wl_listener*, void*); \
|
||||
inline wl_listener listen_##name = {.notify = listener_##name}
|
||||
|
12
src/main.cpp
12
src/main.cpp
@@ -54,14 +54,17 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
std::string next_arg = std::next(it)->c_str();
|
||||
|
||||
if (!std::filesystem::exists(next_arg)) {
|
||||
std::cerr << "[ ERROR ] Config path '" << next_arg << "' doesn't exist!\n";
|
||||
if (std::filesystem::is_symlink(next_arg))
|
||||
next_arg = std::filesystem::read_symlink(next_arg);
|
||||
|
||||
if (!std::filesystem::is_regular_file(next_arg)) {
|
||||
std::cerr << "[ ERROR ] Config file '" << next_arg << "' doesn't exist!\n";
|
||||
help();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
configPath = next_arg;
|
||||
configPath = std::filesystem::weakly_canonical(next_arg);
|
||||
Debug::log(LOG, "User-specified config location: '{}'", configPath);
|
||||
|
||||
it++;
|
||||
@@ -97,7 +100,8 @@ int main(int argc, char** argv) {
|
||||
|
||||
g_pCompositor->initServer();
|
||||
|
||||
Init::gainRealTime();
|
||||
if (!getenv("HYPRLAND_NO_RT") || configStringToInt(std::string(getenv("HYPRLAND_NO_RT"))) == 0)
|
||||
Init::gainRealTime();
|
||||
|
||||
Debug::log(LOG, "Hyprland init finished.");
|
||||
|
||||
|
@@ -213,6 +213,12 @@ void CAnimationManager::tick() {
|
||||
continue;
|
||||
|
||||
w->updateWindowDecos();
|
||||
|
||||
if (w->m_bIsFloating) {
|
||||
auto bb = w->getFullWindowBoundingBox();
|
||||
bb.translate(PWORKSPACE->m_vRenderOffset.vec());
|
||||
g_pHyprRenderer->damageBox(&bb);
|
||||
}
|
||||
}
|
||||
} else if (PLAYER) {
|
||||
if (PLAYER->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || PLAYER->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM)
|
||||
|
@@ -641,11 +641,6 @@ void CKeybindManager::spawn(std::string args) {
|
||||
args = args.substr(args.find_first_of(']') + 1);
|
||||
}
|
||||
|
||||
if (g_pXWaylandManager->m_sWLRXWayland)
|
||||
args = "WAYLAND_DISPLAY=" + std::string(g_pCompositor->m_szWLDisplaySocket) + " DISPLAY=" + std::string(g_pXWaylandManager->m_sWLRXWayland->display_name) + " " + args;
|
||||
else
|
||||
args = "WAYLAND_DISPLAY=" + std::string(g_pCompositor->m_szWLDisplaySocket) + " " + args;
|
||||
|
||||
const uint64_t PROC = spawnRaw(args);
|
||||
|
||||
if (!RULES.empty()) {
|
||||
@@ -735,11 +730,10 @@ void CKeybindManager::clearKeybinds() {
|
||||
void CKeybindManager::toggleActiveFloating(std::string args) {
|
||||
CWindow* PWINDOW = nullptr;
|
||||
|
||||
if (args != "" && args != "active" && args.length() > 1) {
|
||||
if (args != "" && args != "active" && args.length() > 1)
|
||||
PWINDOW = g_pCompositor->getWindowByRegex(args);
|
||||
} else {
|
||||
else
|
||||
PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
}
|
||||
|
||||
if (!PWINDOW)
|
||||
return;
|
||||
@@ -747,9 +741,6 @@ void CKeybindManager::toggleActiveFloating(std::string args) {
|
||||
// remove drag status
|
||||
g_pInputManager->currentlyDraggedWindow = nullptr;
|
||||
|
||||
if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID))
|
||||
return;
|
||||
|
||||
if (PWINDOW->m_sGroupData.pNextWindow && PWINDOW->m_sGroupData.pNextWindow != PWINDOW) {
|
||||
|
||||
const auto PCURRENT = PWINDOW->getGroupCurrent();
|
||||
@@ -831,7 +822,7 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
workspaceToChangeTo = getWorkspaceIDFromString(args, workspaceName);
|
||||
}
|
||||
|
||||
if (workspaceToChangeTo == INT_MAX) {
|
||||
if (workspaceToChangeTo == WORKSPACE_INVALID) {
|
||||
Debug::log(ERR, "Error in changeworkspace, invalid value");
|
||||
return;
|
||||
}
|
||||
@@ -920,7 +911,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
std::string workspaceName;
|
||||
const auto WORKSPACEID = getWorkspaceIDFromString(args, workspaceName);
|
||||
|
||||
if (WORKSPACEID == INT_MAX) {
|
||||
if (WORKSPACEID == WORKSPACE_INVALID) {
|
||||
Debug::log(LOG, "Invalid workspace in moveActiveToWorkspace");
|
||||
return;
|
||||
}
|
||||
@@ -949,6 +940,11 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
|
||||
POLDWS->m_pLastFocusedWindow = g_pCompositor->getFirstWindowOnWorkspace(POLDWS->m_iID);
|
||||
|
||||
if (pWorkspace->m_bIsSpecialWorkspace)
|
||||
pMonitor->setSpecialWorkspace(pWorkspace);
|
||||
else if (POLDWS->m_bIsSpecialWorkspace)
|
||||
g_pCompositor->getMonitorFromID(POLDWS->m_iMonitorID)->setSpecialWorkspace(nullptr);
|
||||
|
||||
pMonitor->changeWorkspace(pWorkspace);
|
||||
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
@@ -977,7 +973,7 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||
|
||||
const int WORKSPACEID = getWorkspaceIDFromString(args, workspaceName);
|
||||
|
||||
if (WORKSPACEID == INT_MAX) {
|
||||
if (WORKSPACEID == WORKSPACE_INVALID) {
|
||||
Debug::log(ERR, "Error in moveActiveToWorkspaceSilent, invalid value");
|
||||
return;
|
||||
}
|
||||
@@ -1216,24 +1212,16 @@ void CKeybindManager::toggleSplit(std::string args) {
|
||||
}
|
||||
|
||||
void CKeybindManager::alterSplitRatio(std::string args) {
|
||||
float splitratio = 0;
|
||||
bool exact = false;
|
||||
std::optional<float> splitResult;
|
||||
bool exact = false;
|
||||
|
||||
if (args == "+" || args == "-") {
|
||||
Debug::log(LOG, "alterSplitRatio: using LEGACY +/-, consider switching to the Hyprland syntax.");
|
||||
splitratio = (args == "+" ? 0.05f : -0.05f);
|
||||
}
|
||||
if (args.starts_with("exact")) {
|
||||
exact = true;
|
||||
splitResult = getPlusMinusKeywordResult(args.substr(5), 0);
|
||||
} else
|
||||
splitResult = getPlusMinusKeywordResult(args, 0);
|
||||
|
||||
if (splitratio == 0) {
|
||||
if (args.starts_with("exact")) {
|
||||
exact = true;
|
||||
splitratio = getPlusMinusKeywordResult(args.substr(5), 0);
|
||||
} else {
|
||||
splitratio = getPlusMinusKeywordResult(args, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (splitratio == INT_MAX) {
|
||||
if (!splitResult.has_value()) {
|
||||
Debug::log(ERR, "Splitratio invalid in alterSplitRatio!");
|
||||
return;
|
||||
}
|
||||
@@ -1243,7 +1231,7 @@ void CKeybindManager::alterSplitRatio(std::string args) {
|
||||
if (!PLASTWINDOW)
|
||||
return;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->alterSplitRatio(PLASTWINDOW, splitratio, exact);
|
||||
g_pLayoutManager->getCurrentLayout()->alterSplitRatio(PLASTWINDOW, splitResult.value(), exact);
|
||||
}
|
||||
|
||||
void CKeybindManager::focusMonitor(std::string arg) {
|
||||
@@ -1425,7 +1413,7 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
|
||||
std::string workspaceName;
|
||||
const int WORKSPACEID = getWorkspaceIDFromString(workspace, workspaceName);
|
||||
|
||||
if (WORKSPACEID == INT_MAX) {
|
||||
if (WORKSPACEID == WORKSPACE_INVALID) {
|
||||
Debug::log(ERR, "moveWorkspaceToMonitor invalid workspace!");
|
||||
return;
|
||||
}
|
||||
@@ -1447,7 +1435,7 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
||||
std::string workspaceName = "";
|
||||
int workspaceID = getWorkspaceIDFromString("special:" + args, workspaceName);
|
||||
|
||||
if (workspaceID == INT_MAX || !g_pCompositor->isWorkspaceSpecial(workspaceID)) {
|
||||
if (workspaceID == WORKSPACE_INVALID || !g_pCompositor->isWorkspaceSpecial(workspaceID)) {
|
||||
Debug::log(ERR, "Invalid workspace passed to special");
|
||||
return;
|
||||
}
|
||||
@@ -1485,7 +1473,7 @@ void CKeybindManager::forceRendererReload(std::string args) {
|
||||
if (!m->output)
|
||||
continue;
|
||||
|
||||
auto rule = g_pConfigManager->getMonitorRuleFor(m->szName, m->output->description ? m->output->description : "");
|
||||
auto rule = g_pConfigManager->getMonitorRuleFor(m->szName, m->szDescription);
|
||||
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule, true)) {
|
||||
overAgain = true;
|
||||
break;
|
||||
@@ -1915,7 +1903,7 @@ void CKeybindManager::alterZOrder(std::string args) {
|
||||
else if (POSITION == "bottom")
|
||||
g_pCompositor->changeWindowZOrder(PWINDOW, 0);
|
||||
else {
|
||||
Debug::log(ERR, "alterZOrder: bad position: %s", POSITION);
|
||||
Debug::log(ERR, "alterZOrder: bad position: {}", POSITION);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2067,7 +2055,7 @@ void CKeybindManager::moveWindowOrGroup(std::string args) {
|
||||
static auto* const PIGNOREGROUPLOCK = &g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock")->intValue;
|
||||
|
||||
if (!isDirection(args)) {
|
||||
Debug::log(ERR, "Cannot move into group in direction %c, unsupported direction. Supported: l,r,u/t,d/b", arg);
|
||||
Debug::log(ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -51,3 +51,10 @@ bool CLayoutManager::removeLayout(IHyprLayout* layout) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::string> CLayoutManager::getAllLayoutNames() {
|
||||
std::vector<std::string> results(m_vLayouts.size());
|
||||
for (size_t i = 0; i < m_vLayouts.size(); ++i)
|
||||
results[i] = m_vLayouts[i].first;
|
||||
return results;
|
||||
}
|
||||
|
@@ -7,16 +7,16 @@ class CLayoutManager {
|
||||
public:
|
||||
CLayoutManager();
|
||||
|
||||
IHyprLayout* getCurrentLayout();
|
||||
IHyprLayout* getCurrentLayout();
|
||||
|
||||
void switchToLayout(std::string);
|
||||
void switchToLayout(std::string);
|
||||
|
||||
bool addLayout(const std::string& name, IHyprLayout* layout);
|
||||
bool removeLayout(IHyprLayout* layout);
|
||||
bool addLayout(const std::string& name, IHyprLayout* layout);
|
||||
bool removeLayout(IHyprLayout* layout);
|
||||
std::vector<std::string> getAllLayoutNames();
|
||||
|
||||
private:
|
||||
enum HYPRLAYOUTS
|
||||
{
|
||||
enum HYPRLAYOUTS {
|
||||
LAYOUT_DWINDLE = 0,
|
||||
LAYOUT_MASTER
|
||||
};
|
||||
@@ -25,8 +25,7 @@ class CLayoutManager {
|
||||
|
||||
CHyprDwindleLayout m_cDwindleLayout;
|
||||
CHyprMasterLayout m_cMasterLayout;
|
||||
|
||||
std::vector<std::pair<std::string, IHyprLayout*>> m_vLayouts;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CLayoutManager> g_pLayoutManager;
|
||||
inline std::unique_ptr<CLayoutManager> g_pLayoutManager;
|
||||
|
@@ -45,10 +45,11 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate)
|
||||
wlr_xdg_toplevel_set_activated(PSURF->toplevel, activate);
|
||||
|
||||
} else if (wlr_xwayland_surface_try_from_wlr_surface(pSurface)) {
|
||||
wlr_xwayland_surface_activate(wlr_xwayland_surface_try_from_wlr_surface(pSurface), activate);
|
||||
const auto XSURF = wlr_xwayland_surface_try_from_wlr_surface(pSurface);
|
||||
wlr_xwayland_surface_activate(XSURF, activate);
|
||||
|
||||
if (activate)
|
||||
wlr_xwayland_surface_restack(wlr_xwayland_surface_try_from_wlr_surface(pSurface), nullptr, XCB_STACK_MODE_ABOVE);
|
||||
if (activate && !XSURF->override_redirect)
|
||||
wlr_xwayland_surface_restack(XSURF, nullptr, XCB_STACK_MODE_ABOVE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +59,8 @@ void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) {
|
||||
|
||||
if (activate) {
|
||||
wlr_xwayland_surface_set_minimized(pWindow->m_uSurface.xwayland, false);
|
||||
wlr_xwayland_surface_restack(pWindow->m_uSurface.xwayland, nullptr, XCB_STACK_MODE_ABOVE);
|
||||
if (!pWindow->m_uSurface.xwayland->override_redirect)
|
||||
wlr_xwayland_surface_restack(pWindow->m_uSurface.xwayland, nullptr, XCB_STACK_MODE_ABOVE);
|
||||
}
|
||||
|
||||
wlr_xwayland_surface_activate(pWindow->m_uSurface.xwayland, activate);
|
||||
|
@@ -3,6 +3,18 @@
|
||||
#include "wlr/types/wlr_switch.h"
|
||||
#include <ranges>
|
||||
|
||||
CInputManager::~CInputManager() {
|
||||
m_lConstraints.clear();
|
||||
m_lKeyboards.clear();
|
||||
m_lMice.clear();
|
||||
m_lTablets.clear();
|
||||
m_lTabletTools.clear();
|
||||
m_lTabletPads.clear();
|
||||
m_lIdleInhibitors.clear();
|
||||
m_lTouchDevices.clear();
|
||||
m_lSwitches.clear();
|
||||
}
|
||||
|
||||
void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) {
|
||||
static auto* const PSENS = &g_pConfigManager->getConfigValuePtr("general:sensitivity")->floatValue;
|
||||
static auto* const PNOACCEL = &g_pConfigManager->getConfigValuePtr("input:force_no_accel")->intValue;
|
||||
@@ -221,10 +233,20 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
surfacePos = PMONITOR->vecPosition;
|
||||
}
|
||||
|
||||
// overlay is above fullscreen
|
||||
// overlays are above fullscreen
|
||||
if (!foundSurface)
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &surfaceCoords, &pFoundLayerSurface);
|
||||
|
||||
// also IME popups
|
||||
if (!foundSurface) {
|
||||
auto popup = g_pCompositor->vectorToIMEPopup(mouseCoords, m_sIMERelay.m_lIMEPopups);
|
||||
if (popup) {
|
||||
foundSurface = popup->pSurface->surface;
|
||||
surfacePos = Vector2D(popup->realX, popup->realY);
|
||||
}
|
||||
}
|
||||
|
||||
// also top layers
|
||||
if (!foundSurface)
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface);
|
||||
|
||||
@@ -459,7 +481,6 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
|
||||
}
|
||||
|
||||
void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_event* e) {
|
||||
|
||||
if (!e->surface)
|
||||
g_pHyprRenderer->m_bWindowRequestedCursorHide = true;
|
||||
else
|
||||
@@ -572,10 +593,13 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) {
|
||||
void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
||||
|
||||
// notify the keybind manager
|
||||
static auto* const PPASSMOUSE = &g_pConfigManager->getConfigValuePtr("binds:pass_mouse_when_bound")->intValue;
|
||||
const auto PASS = g_pKeybindManager->onMouseEvent(e);
|
||||
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||
static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue;
|
||||
static auto* const PPASSMOUSE = &g_pConfigManager->getConfigValuePtr("binds:pass_mouse_when_bound")->intValue;
|
||||
const auto PASS = g_pKeybindManager->onMouseEvent(e);
|
||||
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||
static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue;
|
||||
static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
static auto* const PBORDERGRABEXTEND = &g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area")->intValue;
|
||||
const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0;
|
||||
|
||||
if (!PASS && !*PPASSMOUSE)
|
||||
return;
|
||||
@@ -600,7 +624,8 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
||||
if (*PRESIZEONBORDER && !m_bLastFocusOnLS) {
|
||||
if (w && !w->m_bIsFullscreen) {
|
||||
const CBox real = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if ((!real.containsPoint(mouseCoords) || w->isInCurvedCorner(mouseCoords.x, mouseCoords.y)) && !w->hasPopupAt(mouseCoords)) {
|
||||
const CBox grab = {real.x - BORDER_GRAB_AREA, real.y - BORDER_GRAB_AREA, real.width + 2 * BORDER_GRAB_AREA, real.height + 2 * BORDER_GRAB_AREA};
|
||||
if ((grab.containsPoint(mouseCoords) && (!real.containsPoint(mouseCoords) || w->isInCurvedCorner(mouseCoords.x, mouseCoords.y))) && !w->hasPopupAt(mouseCoords)) {
|
||||
g_pKeybindManager->resizeWithBorder(e);
|
||||
return;
|
||||
}
|
||||
@@ -667,10 +692,16 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
|
||||
|
||||
auto factor = (*PSCROLLFACTOR <= 0.f || e->source != WLR_AXIS_SOURCE_FINGER ? 1.f : *PSCROLLFACTOR);
|
||||
|
||||
bool passEvent = g_pKeybindManager->onAxisEvent(e);
|
||||
const auto EMAP = std::unordered_map<std::string, std::any>{{"event", e}};
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("mouseAxis", EMAP);
|
||||
|
||||
bool passEvent = g_pKeybindManager->onAxisEvent(e);
|
||||
|
||||
g_pCompositor->notifyIdleActivity();
|
||||
|
||||
if (!passEvent)
|
||||
return;
|
||||
|
||||
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
|
||||
const auto pWindow = g_pCompositor->vectorToWindowIdeal(MOUSECOORDS);
|
||||
|
||||
@@ -685,8 +716,7 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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() {
|
||||
@@ -871,7 +901,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
pKeyboard->currentRules.model = "";
|
||||
pKeyboard->currentRules.variant = "";
|
||||
pKeyboard->currentRules.options = "";
|
||||
pKeyboard->currentRules.layout = "";
|
||||
pKeyboard->currentRules.layout = "us";
|
||||
|
||||
KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
}
|
||||
@@ -1053,7 +1083,7 @@ void CInputManager::setPointerConfigs() {
|
||||
|
||||
const auto CONFIG = libinput_config_accel_create(LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM);
|
||||
libinput_config_accel_set_points(CONFIG, LIBINPUT_ACCEL_TYPE_MOTION, step, points.size(), points.data());
|
||||
libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM);
|
||||
libinput_device_config_accel_apply(LIBINPUTDEV, CONFIG);
|
||||
libinput_config_accel_destroy(CONFIG);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Invalid values in custom accel profile"); }
|
||||
} else {
|
||||
@@ -1131,6 +1161,9 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar
|
||||
if (!pKeyboard->enabled)
|
||||
return;
|
||||
|
||||
const auto EMAP = std::unordered_map<std::string, std::any>{{"keyboard", pKeyboard}, {"event", e}};
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("keyPress", EMAP);
|
||||
|
||||
static auto* const PDPMS = &g_pConfigManager->getConfigValuePtr("misc:key_press_enables_dpms")->intValue;
|
||||
if (*PDPMS && !g_pCompositor->m_bDPMSStateON) {
|
||||
// enable dpms
|
||||
|
@@ -7,12 +7,14 @@
|
||||
#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 = 1,
|
||||
@@ -20,7 +22,8 @@ enum eMouseBindMode {
|
||||
MBIND_RESIZE_FORCE_RATIO = 3
|
||||
};
|
||||
|
||||
enum eBorderIconDirection {
|
||||
enum eBorderIconDirection
|
||||
{
|
||||
BORDERICON_NONE,
|
||||
BORDERICON_UP,
|
||||
BORDERICON_DOWN,
|
||||
@@ -61,6 +64,8 @@ class CKeybindManager;
|
||||
|
||||
class CInputManager {
|
||||
public:
|
||||
~CInputManager();
|
||||
|
||||
void onMouseMoved(wlr_pointer_motion_event*);
|
||||
void onMouseWarp(wlr_pointer_motion_absolute_event*);
|
||||
void onMouseButton(wlr_pointer_button_event*);
|
||||
|
@@ -44,13 +44,14 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
if (!m_sActiveSwipe.pWorkspaceBegin)
|
||||
return; // no valid swipe
|
||||
|
||||
static auto* const PSWIPEPERC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_cancel_ratio")->floatValue;
|
||||
static auto* const PSWIPEDIST = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance")->intValue;
|
||||
static auto* const PSWIPEFORC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_min_speed_to_force")->intValue;
|
||||
static auto* const PSWIPENEW = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_create_new")->intValue;
|
||||
static auto* const PSWIPENUMBER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_numbered")->intValue;
|
||||
static auto* const PSWIPEUSER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_use_r")->intValue;
|
||||
const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" ||
|
||||
static auto* const PSWIPEPERC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_cancel_ratio")->floatValue;
|
||||
static auto* const PSWIPEDIST = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance")->intValue;
|
||||
static auto* const PSWIPEFORC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_min_speed_to_force")->intValue;
|
||||
static auto* const PSWIPENEW = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_create_new")->intValue;
|
||||
static auto* const PSWIPENUMBER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_numbered")->intValue;
|
||||
static auto* const PSWIPEUSER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_use_r")->intValue;
|
||||
static auto* const PWORKSPACEGAP = &g_pConfigManager->getConfigValuePtr("general:gaps_workspaces")->intValue;
|
||||
const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" ||
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert");
|
||||
|
||||
// commit
|
||||
@@ -75,10 +76,12 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
workspaceIDRight = maxWorkspace + 1;
|
||||
}
|
||||
|
||||
auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); // not guaranteed if PSWIPENEW || PSWIPENUMBER
|
||||
auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); // not guaranteed if PSWIPENUMBER
|
||||
auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); // not guaranteed if PSWIPENEW || PSWIPENUMBER
|
||||
auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); // not guaranteed if PSWIPENUMBER
|
||||
|
||||
const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.vec();
|
||||
const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.vec();
|
||||
const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + *PWORKSPACEGAP;
|
||||
const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + *PWORKSPACEGAP;
|
||||
|
||||
CWorkspace* pSwitchedTo = nullptr;
|
||||
|
||||
@@ -94,18 +97,19 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
} else {
|
||||
if (m_sActiveSwipe.delta < 0) {
|
||||
// to left
|
||||
|
||||
if (PWORKSPACEL) {
|
||||
if (VERTANIMS)
|
||||
PWORKSPACEL->m_vRenderOffset = Vector2D({0, -m_sActiveSwipe.pMonitor->vecSize.y});
|
||||
PWORKSPACEL->m_vRenderOffset = Vector2D({0, -YDISTANCE});
|
||||
else
|
||||
PWORKSPACEL->m_vRenderOffset = Vector2D({-m_sActiveSwipe.pMonitor->vecSize.x, 0});
|
||||
PWORKSPACEL->m_vRenderOffset = Vector2D({-XDISTANCE, 0});
|
||||
}
|
||||
} else if (PWORKSPACER) {
|
||||
// to right
|
||||
if (VERTANIMS)
|
||||
PWORKSPACER->m_vRenderOffset = Vector2D({0, m_sActiveSwipe.pMonitor->vecSize.y});
|
||||
PWORKSPACER->m_vRenderOffset = Vector2D({0, YDISTANCE});
|
||||
else
|
||||
PWORKSPACER->m_vRenderOffset = Vector2D({m_sActiveSwipe.pMonitor->vecSize.x, 0});
|
||||
PWORKSPACER->m_vRenderOffset = Vector2D({XDISTANCE, 0});
|
||||
}
|
||||
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D();
|
||||
@@ -128,9 +132,9 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE);
|
||||
if (VERTANIMS)
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0, m_sActiveSwipe.pMonitor->vecSize.y);
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0, YDISTANCE);
|
||||
else
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(m_sActiveSwipe.pMonitor->vecSize.x, 0);
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(XDISTANCE, 0);
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(1.f);
|
||||
|
||||
g_pInputManager->unconstrainMouse();
|
||||
@@ -154,9 +158,9 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE);
|
||||
if (VERTANIMS)
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0, -m_sActiveSwipe.pMonitor->vecSize.y);
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0, -YDISTANCE);
|
||||
else
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-m_sActiveSwipe.pMonitor->vecSize.x, 0);
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-XDISTANCE, 0);
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(1.f);
|
||||
|
||||
g_pInputManager->unconstrainMouse();
|
||||
@@ -198,8 +202,11 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||
static auto* const PSWIPEFOREVER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_forever")->intValue;
|
||||
static auto* const PSWIPENUMBER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_numbered")->intValue;
|
||||
static auto* const PSWIPEUSER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_use_r")->intValue;
|
||||
static auto* const PWORKSPACEGAP = &g_pConfigManager->getConfigValuePtr("general:gaps_workspaces")->intValue;
|
||||
|
||||
const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" ||
|
||||
const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + *PWORKSPACEGAP;
|
||||
const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + *PWORKSPACEGAP;
|
||||
const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" ||
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert");
|
||||
|
||||
m_sActiveSwipe.delta += VERTANIMS ? (*PSWIPEINVR ? -e->dy : e->dy) : (*PSWIPEINVR ? -e->dx : e->dx);
|
||||
@@ -211,7 +218,7 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||
auto workspaceIDLeft = getWorkspaceIDFromString(*PSWIPENUMBER ? "-1" : (*PSWIPEUSER ? "r-1" : "m-1"), wsname);
|
||||
auto workspaceIDRight = getWorkspaceIDFromString(*PSWIPENUMBER ? "+1" : (*PSWIPEUSER ? "r+1" : "m+1"), wsname);
|
||||
|
||||
if ((workspaceIDLeft == INT_MAX || workspaceIDRight == INT_MAX || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID) && !*PSWIPENEW) {
|
||||
if ((workspaceIDLeft == WORKSPACE_INVALID || workspaceIDRight == WORKSPACE_INVALID || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID) && !*PSWIPENEW) {
|
||||
m_sActiveSwipe.pWorkspaceBegin = nullptr; // invalidate the swipe
|
||||
return;
|
||||
}
|
||||
@@ -244,9 +251,11 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||
g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor);
|
||||
|
||||
if (VERTANIMS)
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y));
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(
|
||||
Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE));
|
||||
else
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0));
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(
|
||||
Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0));
|
||||
|
||||
g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID);
|
||||
return;
|
||||
@@ -268,13 +277,15 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||
}
|
||||
|
||||
if (VERTANIMS) {
|
||||
PWORKSPACE->m_vRenderOffset.setValueAndWarp(
|
||||
Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y - m_sActiveSwipe.pMonitor->vecSize.y));
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y));
|
||||
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(
|
||||
0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE - YDISTANCE));
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(
|
||||
Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE));
|
||||
} else {
|
||||
PWORKSPACE->m_vRenderOffset.setValueAndWarp(
|
||||
Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x - m_sActiveSwipe.pMonitor->vecSize.x, 0));
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0));
|
||||
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(
|
||||
((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE - XDISTANCE, 0));
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(
|
||||
Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0));
|
||||
}
|
||||
|
||||
g_pCompositor->updateWorkspaceWindowDecos(workspaceIDLeft);
|
||||
@@ -286,9 +297,11 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||
g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor);
|
||||
|
||||
if (VERTANIMS)
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y));
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(
|
||||
Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE));
|
||||
else
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0));
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(
|
||||
Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0));
|
||||
|
||||
g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID);
|
||||
return;
|
||||
@@ -310,13 +323,15 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||
}
|
||||
|
||||
if (VERTANIMS) {
|
||||
PWORKSPACE->m_vRenderOffset.setValueAndWarp(
|
||||
Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y + m_sActiveSwipe.pMonitor->vecSize.y));
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y));
|
||||
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(
|
||||
0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE + YDISTANCE));
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(
|
||||
Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE));
|
||||
} else {
|
||||
PWORKSPACE->m_vRenderOffset.setValueAndWarp(
|
||||
Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x + m_sActiveSwipe.pMonitor->vecSize.x, 0));
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0));
|
||||
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(
|
||||
((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE + XDISTANCE, 0));
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(
|
||||
Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0));
|
||||
}
|
||||
|
||||
g_pCompositor->updateWorkspaceWindowDecos(workspaceIDRight);
|
||||
|
@@ -2,6 +2,8 @@
|
||||
#include "../../Compositor.hpp"
|
||||
|
||||
void CInputManager::onTouchDown(wlr_touch_down_event* e) {
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("touchDown", e);
|
||||
|
||||
auto PMONITOR = g_pCompositor->getMonitorFromName(e->touch->output_name ? e->touch->output_name : "");
|
||||
|
||||
const auto PDEVIT = std::find_if(m_lTouchDevices.begin(), m_lTouchDevices.end(), [&](const STouchDevice& other) { return other.pWlrDevice == &e->touch->base; });
|
||||
@@ -52,12 +54,14 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) {
|
||||
}
|
||||
|
||||
void CInputManager::onTouchUp(wlr_touch_up_event* e) {
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("touchUp", e);
|
||||
if (m_sTouchData.touchFocusSurface) {
|
||||
wlr_seat_touch_notify_up(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id);
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::onTouchMove(wlr_touch_motion_event* e) {
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("touchMove", e);
|
||||
if (m_sTouchData.touchFocusWindow && g_pCompositor->windowValidMapped(m_sTouchData.touchFocusWindow)) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusWindow->m_iMonitorID);
|
||||
|
||||
@@ -68,7 +72,7 @@ void CInputManager::onTouchMove(wlr_touch_motion_event* e) {
|
||||
local = local * m_sTouchData.touchFocusWindow->m_fX11SurfaceScaledBy;
|
||||
|
||||
wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id, local.x, local.y);
|
||||
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, local.x, local.y);
|
||||
// wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, local.x, local.y);
|
||||
} else if (m_sTouchData.touchFocusLS) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusLS->monitorID);
|
||||
|
||||
@@ -77,7 +81,7 @@ void CInputManager::onTouchMove(wlr_touch_motion_event* e) {
|
||||
const auto local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchSurfaceOrigin;
|
||||
|
||||
wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id, local.x, local.y);
|
||||
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, local.x, local.y);
|
||||
// wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, local.x, local.y);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include "HookSystem.hpp"
|
||||
#include "../debug/Log.hpp"
|
||||
|
||||
#define register
|
||||
#include <udis86.h>
|
||||
@@ -45,6 +46,10 @@ size_t CFunctionHook::getInstructionLenAt(void* start) {
|
||||
// I don't have an assembler. I don't think udis provides one. Besides, variables might be tricky.
|
||||
if (((uint8_t*)start)[0] == 0xFF && ((uint8_t*)start)[1] == 0x15)
|
||||
m_vTrampolineRIPUses.emplace_back(std::make_pair<>((uint64_t)start - (uint64_t)m_pSource, ins));
|
||||
else {
|
||||
Debug::log(ERR, "[CFunctionHook] Cannot hook: unsupported %rip usage: {}", ins);
|
||||
throw std::runtime_error("unsupported %rip usage");
|
||||
}
|
||||
}
|
||||
|
||||
return insSize;
|
||||
@@ -90,7 +95,10 @@ bool CFunctionHook::hook() {
|
||||
static constexpr size_t CALL_WITH_RAX_ADDRESS_OFFSET = 2;
|
||||
|
||||
// get minimum size to overwrite
|
||||
const auto HOOKSIZE = probeMinimumJumpSize(m_pSource, sizeof(ABSOLUTE_JMP_ADDRESS) + sizeof(PUSH_RAX) + sizeof(POP_RAX));
|
||||
size_t HOOKSIZE = 0;
|
||||
try {
|
||||
HOOKSIZE = probeMinimumJumpSize(m_pSource, sizeof(ABSOLUTE_JMP_ADDRESS) + sizeof(PUSH_RAX) + sizeof(POP_RAX));
|
||||
} catch (std::exception& e) { return false; }
|
||||
|
||||
// alloc trampoline
|
||||
const auto TRAMPOLINE_SIZE = sizeof(ABSOLUTE_JMP_ADDRESS) + HOOKSIZE + sizeof(PUSH_RAX) + m_vTrampolineRIPUses.size() * (sizeof(CALL_WITH_RAX) - 6);
|
||||
|
@@ -10,7 +10,10 @@ CPluginSystem::CPluginSystem() {
|
||||
|
||||
CPlugin* CPluginSystem::loadPlugin(const std::string& path) {
|
||||
|
||||
m_szLastError = "";
|
||||
|
||||
if (getPluginByPath(path)) {
|
||||
m_szLastError = "Cannot load a plugin twice!";
|
||||
Debug::log(ERR, " [PluginSystem] Cannot load a plugin twice!");
|
||||
return nullptr;
|
||||
}
|
||||
@@ -22,7 +25,9 @@ CPlugin* CPluginSystem::loadPlugin(const std::string& path) {
|
||||
HANDLE MODULE = dlopen(path.c_str(), RTLD_LAZY);
|
||||
|
||||
if (!MODULE) {
|
||||
Debug::log(ERR, " [PluginSystem] Plugin {} could not be loaded: {}", path, dlerror());
|
||||
std::string strerr = dlerror();
|
||||
m_szLastError = std::format("Plugin {} could not be loaded: {}", path, strerr);
|
||||
Debug::log(ERR, " [PluginSystem] Plugin {} could not be loaded: {}", path, strerr);
|
||||
m_vLoadedPlugins.pop_back();
|
||||
return nullptr;
|
||||
}
|
||||
@@ -33,6 +38,7 @@ CPlugin* CPluginSystem::loadPlugin(const std::string& path) {
|
||||
PPLUGIN_INIT_FUNC initFunc = (PPLUGIN_INIT_FUNC)dlsym(MODULE, PLUGIN_INIT_FUNC_STR);
|
||||
|
||||
if (!apiVerFunc || !initFunc) {
|
||||
m_szLastError = std::format("Plugin {} could not be loaded: {}", path, "missing apiver/init func");
|
||||
Debug::log(ERR, " [PluginSystem] Plugin {} could not be loaded. (No apiver/init func)", path);
|
||||
dlclose(MODULE);
|
||||
m_vLoadedPlugins.pop_back();
|
||||
@@ -42,6 +48,7 @@ CPlugin* CPluginSystem::loadPlugin(const std::string& path) {
|
||||
const std::string PLUGINAPIVER = apiVerFunc();
|
||||
|
||||
if (PLUGINAPIVER != HYPRLAND_API_VERSION) {
|
||||
m_szLastError = std::format("Plugin {} could not be loaded: {}", path, "API version mismatch");
|
||||
Debug::log(ERR, " [PluginSystem] Plugin {} could not be loaded. (API version mismatch)", path);
|
||||
dlclose(MODULE);
|
||||
m_vLoadedPlugins.pop_back();
|
||||
@@ -56,10 +63,11 @@ CPlugin* CPluginSystem::loadPlugin(const std::string& path) {
|
||||
PLUGINDATA = initFunc(MODULE);
|
||||
} else {
|
||||
// this module crashed.
|
||||
throw std::exception();
|
||||
throw std::runtime_error("received a fatal signal");
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
m_bAllowConfigVars = false;
|
||||
m_szLastError = std::format("Plugin {} could not be loaded: plugin crashed/threw in main: {}", path, e.what());
|
||||
Debug::log(ERR, " [PluginSystem] Plugin {} (Handle {:x}) crashed in init. Unloading.", path, (uintptr_t)MODULE);
|
||||
unloadPlugin(PLUGIN, true); // Plugin could've already hooked/done something
|
||||
return nullptr;
|
||||
|
@@ -38,6 +38,7 @@ class CPluginSystem {
|
||||
std::vector<CPlugin*> getAllPlugins();
|
||||
|
||||
bool m_bAllowConfigVars = false;
|
||||
std::string m_szLastError = "";
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<CPlugin>> m_vLoadedPlugins;
|
||||
|
@@ -210,7 +210,8 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r
|
||||
PFRAME->client = PCLIENT;
|
||||
PCLIENT->ref++;
|
||||
|
||||
PFRAME->shmFormat = wlr_output_preferred_read_format(PFRAME->pMonitor->output);
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
PFRAME->shmFormat = g_pHyprOpenGL->getPreferredReadFormat(PFRAME->pMonitor);
|
||||
if (PFRAME->shmFormat == DRM_FORMAT_INVALID) {
|
||||
Debug::log(ERR, "No format supported by renderer in capture output");
|
||||
zwlr_screencopy_frame_v1_send_failed(PFRAME->resource);
|
||||
@@ -241,7 +242,7 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r
|
||||
wlr_output_effective_resolution(PFRAME->pMonitor->output, &ow, &oh);
|
||||
PFRAME->box.transform(PFRAME->pMonitor->transform, ow, oh).scale(PFRAME->pMonitor->scale).round();
|
||||
|
||||
PFRAME->shmStride = (PSHMINFO->bpp / 8) * PFRAME->box.width;
|
||||
PFRAME->shmStride = pixel_format_info_min_stride(PSHMINFO, PFRAME->box.w);
|
||||
|
||||
zwlr_screencopy_frame_v1_send_buffer(PFRAME->resource, convert_drm_format_to_wl_shm(PFRAME->shmFormat), PFRAME->box.width, PFRAME->box.height, PFRAME->shmStride);
|
||||
|
||||
@@ -424,23 +425,76 @@ void CScreencopyProtocolManager::sendFrameDamage(SScreencopyFrame* frame) {
|
||||
}
|
||||
|
||||
bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* now) {
|
||||
wlr_texture* sourceTex = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer);
|
||||
if (!sourceTex)
|
||||
return false;
|
||||
|
||||
void* data;
|
||||
uint32_t format;
|
||||
size_t stride;
|
||||
if (!wlr_buffer_begin_data_ptr_access(frame->buffer, WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &data, &format, &stride))
|
||||
if (!wlr_buffer_begin_data_ptr_access(frame->buffer, WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &data, &format, &stride)) {
|
||||
wlr_texture_destroy(sourceTex);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!wlr_renderer_begin_with_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer)) {
|
||||
Debug::log(ERR, "[sc] shm: Client requested a copy to a buffer that failed to pass wlr_renderer_begin_with_buffer");
|
||||
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
|
||||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
CFramebuffer fb;
|
||||
fb.alloc(frame->box.w, frame->box.h, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : frame->pMonitor->drmFormat);
|
||||
|
||||
if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb)) {
|
||||
wlr_texture_destroy(sourceTex);
|
||||
wlr_buffer_end_data_ptr_access(frame->buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
CBox monbox = CBox{0, 0, frame->pMonitor->vecTransformedSize.x, frame->pMonitor->vecTransformedSize.y}.translate({-frame->box.x, -frame->box.y});
|
||||
g_pHyprOpenGL->setMonitorTransformEnabled(false);
|
||||
g_pHyprOpenGL->renderTexture(sourceTex, &monbox, 1);
|
||||
g_pHyprOpenGL->setMonitorTransformEnabled(true);
|
||||
|
||||
return success;
|
||||
#ifndef GLES2
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.m_iFb);
|
||||
#else
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb.m_iFb);
|
||||
#endif
|
||||
|
||||
const auto PFORMAT = g_pHyprOpenGL->getPixelFormatFromDRM(format);
|
||||
if (!PFORMAT) {
|
||||
g_pHyprRenderer->endRender();
|
||||
wlr_texture_destroy(sourceTex);
|
||||
wlr_buffer_end_data_ptr_access(frame->buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
g_pHyprRenderer->endRender();
|
||||
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
g_pHyprOpenGL->m_RenderData.pMonitor = frame->pMonitor;
|
||||
fb.bind();
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
const wlr_pixel_format_info* drmFmtWlr = drm_get_pixel_format_info(format);
|
||||
uint32_t packStride = pixel_format_info_min_stride(drmFmtWlr, frame->box.w);
|
||||
|
||||
if (packStride == stride) {
|
||||
glReadPixels(0, 0, frame->box.w, frame->box.h, PFORMAT->glFormat, PFORMAT->glType, data);
|
||||
} else {
|
||||
for (size_t i = 0; i < frame->box.h; ++i) {
|
||||
uint32_t y = i;
|
||||
glReadPixels(0, y, frame->box.w, 1, PFORMAT->glFormat, PFORMAT->glType, ((unsigned char*)data) + i * stride);
|
||||
}
|
||||
}
|
||||
|
||||
g_pHyprOpenGL->m_RenderData.pMonitor = nullptr;
|
||||
|
||||
wlr_buffer_end_data_ptr_access(frame->buffer);
|
||||
wlr_texture_destroy(sourceTex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
|
||||
@@ -448,25 +502,19 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) {
|
||||
if (!sourceTex)
|
||||
return false;
|
||||
|
||||
float glMatrix[9];
|
||||
wlr_matrix_identity(glMatrix);
|
||||
wlr_matrix_translate(glMatrix, -frame->box.x, -frame->box.y);
|
||||
wlr_matrix_scale(glMatrix, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y);
|
||||
CRegion fakeDamage = {0, 0, frame->box.width, frame->box.height};
|
||||
|
||||
if (!wlr_renderer_begin_with_buffer(g_pCompositor->m_sWLRRenderer, frame->buffer)) {
|
||||
Debug::log(ERR, "[sc] dmabuf: Client requested a copy to a buffer that failed to pass wlr_renderer_begin_with_buffer");
|
||||
wlr_texture_destroy(sourceTex);
|
||||
if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer))
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y}.translate({-frame->box.x, -frame->box.y});
|
||||
g_pHyprOpenGL->setMonitorTransformEnabled(false);
|
||||
g_pHyprOpenGL->renderTexture(sourceTex, &monbox, 1);
|
||||
g_pHyprOpenGL->setMonitorTransformEnabled(true);
|
||||
|
||||
g_pHyprRenderer->endRender();
|
||||
|
||||
wlr_texture_destroy(sourceTex);
|
||||
|
||||
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -134,7 +134,8 @@ void CToplevelExportProtocolManager::removeFrame(SScreencopyFrame* frame, bool f
|
||||
std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other == frame; });
|
||||
|
||||
wl_resource_set_user_data(frame->resource, nullptr);
|
||||
wlr_buffer_unlock(frame->buffer);
|
||||
if (frame->buffer && frame->buffer->n_locks > 0)
|
||||
wlr_buffer_unlock(frame->buffer);
|
||||
removeClient(frame->client, force);
|
||||
m_lFrames.remove(*frame);
|
||||
}
|
||||
@@ -176,7 +177,8 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PFRAME->pWindow->m_iMonitorID);
|
||||
|
||||
PFRAME->shmFormat = wlr_output_preferred_read_format(PMONITOR->output);
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
PFRAME->shmFormat = g_pHyprOpenGL->getPreferredReadFormat(PMONITOR);
|
||||
if (PFRAME->shmFormat == DRM_FORMAT_INVALID) {
|
||||
Debug::log(ERR, "No format supported by renderer in capture toplevel");
|
||||
hyprland_toplevel_export_frame_v1_send_failed(resource);
|
||||
@@ -203,7 +205,7 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou
|
||||
wlr_output_effective_resolution(PMONITOR->output, &ow, &oh);
|
||||
PFRAME->box.transform(PMONITOR->transform, ow, oh).round();
|
||||
|
||||
PFRAME->shmStride = (PSHMINFO->bpp / 8) * PFRAME->box.width;
|
||||
PFRAME->shmStride = pixel_format_info_min_stride(PSHMINFO, PFRAME->box.w);
|
||||
|
||||
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);
|
||||
|
||||
@@ -362,18 +364,19 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times
|
||||
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);
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
if (!wlr_output_attach_render(PMONITOR->output, nullptr)) {
|
||||
Debug::log(ERR, "[toplevel_export] Couldn't attach render");
|
||||
CFramebuffer outFB;
|
||||
outFB.alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : PMONITOR->drmFormat);
|
||||
|
||||
if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &outFB)) {
|
||||
wlr_buffer_end_data_ptr_access(frame->buffer);
|
||||
if (frame->overlayCursor)
|
||||
wlr_output_lock_software_cursors(PMONITOR->output, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
g_pHyprOpenGL->begin(PMONITOR, &fakeDamage, true);
|
||||
if (frame->overlayCursor)
|
||||
wlr_output_lock_software_cursors(PMONITOR->output, true);
|
||||
|
||||
g_pHyprOpenGL->clear(CColor(0, 0, 0, 1.0));
|
||||
|
||||
// render client at 0,0
|
||||
@@ -381,46 +384,23 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times
|
||||
g_pHyprRenderer->renderWindow(frame->pWindow, PMONITOR, now, false, RENDER_PASS_ALL, true, true);
|
||||
g_pHyprRenderer->m_bBlockSurfaceFeedback = false;
|
||||
|
||||
if (frame->overlayCursor && wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y)) {
|
||||
// hack le massive
|
||||
wlr_output_cursor* cursor;
|
||||
const auto OFFSET = frame->pWindow->m_vRealPosition.vec() - PMONITOR->vecPosition;
|
||||
wl_list_for_each(cursor, &PMONITOR->output->cursors, link) {
|
||||
if (!cursor->enabled || !cursor->visible || PMONITOR->output->hardware_cursor == cursor) {
|
||||
continue;
|
||||
}
|
||||
cursor->x -= OFFSET.x;
|
||||
cursor->y -= OFFSET.y;
|
||||
}
|
||||
wlr_output_render_software_cursors(PMONITOR->output, NULL);
|
||||
wl_list_for_each(cursor, &PMONITOR->output->cursors, link) {
|
||||
if (!cursor->enabled || !cursor->visible || PMONITOR->output->hardware_cursor == cursor) {
|
||||
continue;
|
||||
}
|
||||
cursor->x += OFFSET.x;
|
||||
cursor->y += OFFSET.y;
|
||||
}
|
||||
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
|
||||
}
|
||||
if (frame->overlayCursor)
|
||||
g_pHyprRenderer->renderSoftwareCursors(PMONITOR, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.vec());
|
||||
|
||||
// copy pixels
|
||||
const auto PFORMAT = gles2FromDRM(format);
|
||||
const auto PFORMAT = g_pHyprOpenGL->getPixelFormatFromDRM(format);
|
||||
if (!PFORMAT) {
|
||||
Debug::log(ERR, "[toplevel_export] Cannot read pixels, unsupported format {:x}", (uintptr_t)PFORMAT);
|
||||
g_pHyprOpenGL->end();
|
||||
g_pHyprRenderer->endRender();
|
||||
wlr_buffer_end_data_ptr_access(frame->buffer);
|
||||
if (frame->overlayCursor)
|
||||
wlr_output_lock_software_cursors(PMONITOR->output, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_RenderData.pCurrentMonData->primaryFB.m_iFb);
|
||||
g_pHyprOpenGL->m_RenderData.mainFB->bind();
|
||||
|
||||
glReadPixels(0, 0, frame->box.width, frame->box.height, PFORMAT->gl_format, PFORMAT->gl_type, data);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
g_pHyprOpenGL->end();
|
||||
glReadPixels(0, 0, frame->box.width, frame->box.height, PFORMAT->glFormat, PFORMAT->glType, data);
|
||||
|
||||
wlr_output_rollback(PMONITOR->output);
|
||||
g_pHyprRenderer->endRender();
|
||||
|
||||
wlr_buffer_end_data_ptr_access(frame->buffer);
|
||||
|
||||
@@ -431,14 +411,12 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times
|
||||
}
|
||||
|
||||
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);
|
||||
if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer))
|
||||
return false;
|
||||
|
||||
g_pHyprOpenGL->clear(CColor(0, 0, 0, 1.0));
|
||||
|
||||
@@ -446,14 +424,10 @@ bool CToplevelExportProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame, ti
|
||||
g_pHyprRenderer->renderWindow(frame->pWindow, PMONITOR, now, false, RENDER_PASS_ALL, true, true);
|
||||
g_pHyprRenderer->m_bBlockSurfaceFeedback = false;
|
||||
|
||||
g_pHyprOpenGL->bindWlrOutputFb();
|
||||
if (frame->overlayCursor)
|
||||
g_pHyprRenderer->renderSoftwareCursors(PMONITOR, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.vec());
|
||||
|
||||
CBox monbox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.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);
|
||||
g_pHyprRenderer->endRender();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -11,8 +11,10 @@ struct wlr_pixel_format_info {
|
||||
*/
|
||||
uint32_t opaque_substitute;
|
||||
|
||||
/* Bits per pixels */
|
||||
uint32_t bpp;
|
||||
/* Bytes per block (including padding) */
|
||||
uint32_t bytes_per_block;
|
||||
/* Size of a block in pixels (zero for 1×1) */
|
||||
uint32_t block_width, block_height;
|
||||
|
||||
/* True if the format has an alpha channel */
|
||||
bool has_alpha;
|
||||
@@ -20,143 +22,171 @@ struct wlr_pixel_format_info {
|
||||
|
||||
static const struct wlr_pixel_format_info pixel_format_info[] = {
|
||||
{
|
||||
.drm_format = DRM_FORMAT_XRGB8888,
|
||||
.opaque_substitute = DRM_FORMAT_INVALID,
|
||||
.bpp = 32,
|
||||
.has_alpha = false,
|
||||
.drm_format = DRM_FORMAT_XRGB8888,
|
||||
.bytes_per_block = 4,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_ARGB8888,
|
||||
.opaque_substitute = DRM_FORMAT_XRGB8888,
|
||||
.bpp = 32,
|
||||
.bytes_per_block = 4,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_XBGR8888,
|
||||
.opaque_substitute = DRM_FORMAT_INVALID,
|
||||
.bpp = 32,
|
||||
.has_alpha = false,
|
||||
.drm_format = DRM_FORMAT_XBGR8888,
|
||||
.bytes_per_block = 4,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_ABGR8888,
|
||||
.opaque_substitute = DRM_FORMAT_XBGR8888,
|
||||
.bpp = 32,
|
||||
.bytes_per_block = 4,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_RGBX8888,
|
||||
.opaque_substitute = DRM_FORMAT_INVALID,
|
||||
.bpp = 32,
|
||||
.has_alpha = false,
|
||||
.drm_format = DRM_FORMAT_RGBX8888,
|
||||
.bytes_per_block = 4,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_RGBA8888,
|
||||
.opaque_substitute = DRM_FORMAT_RGBX8888,
|
||||
.bpp = 32,
|
||||
.bytes_per_block = 4,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_BGRX8888,
|
||||
.opaque_substitute = DRM_FORMAT_INVALID,
|
||||
.bpp = 32,
|
||||
.has_alpha = false,
|
||||
.drm_format = DRM_FORMAT_BGRX8888,
|
||||
.bytes_per_block = 4,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_BGRA8888,
|
||||
.opaque_substitute = DRM_FORMAT_BGRX8888,
|
||||
.bpp = 32,
|
||||
.bytes_per_block = 4,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_BGR888,
|
||||
.opaque_substitute = DRM_FORMAT_INVALID,
|
||||
.bpp = 24,
|
||||
.has_alpha = false,
|
||||
.drm_format = DRM_FORMAT_R8,
|
||||
.bytes_per_block = 1,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_RGBX4444,
|
||||
.opaque_substitute = DRM_FORMAT_INVALID,
|
||||
.bpp = 16,
|
||||
.has_alpha = false,
|
||||
.drm_format = DRM_FORMAT_GR88,
|
||||
.bytes_per_block = 2,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_RGB888,
|
||||
.bytes_per_block = 3,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_BGR888,
|
||||
.bytes_per_block = 3,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_RGBX4444,
|
||||
.bytes_per_block = 2,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_RGBA4444,
|
||||
.opaque_substitute = DRM_FORMAT_RGBX4444,
|
||||
.bpp = 16,
|
||||
.bytes_per_block = 2,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_RGBX5551,
|
||||
.opaque_substitute = DRM_FORMAT_INVALID,
|
||||
.bpp = 16,
|
||||
.has_alpha = false,
|
||||
.drm_format = DRM_FORMAT_BGRX4444,
|
||||
.bytes_per_block = 2,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_BGRA4444,
|
||||
.opaque_substitute = DRM_FORMAT_BGRX4444,
|
||||
.bytes_per_block = 2,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_RGBX5551,
|
||||
.bytes_per_block = 2,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_RGBA5551,
|
||||
.opaque_substitute = DRM_FORMAT_RGBX5551,
|
||||
.bpp = 16,
|
||||
.bytes_per_block = 2,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_RGB565,
|
||||
.opaque_substitute = DRM_FORMAT_INVALID,
|
||||
.bpp = 16,
|
||||
.has_alpha = false,
|
||||
.drm_format = DRM_FORMAT_BGRX5551,
|
||||
.bytes_per_block = 2,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_BGR565,
|
||||
.opaque_substitute = DRM_FORMAT_INVALID,
|
||||
.bpp = 16,
|
||||
.has_alpha = false,
|
||||
.drm_format = DRM_FORMAT_BGRA5551,
|
||||
.opaque_substitute = DRM_FORMAT_BGRX5551,
|
||||
.bytes_per_block = 2,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_XRGB2101010,
|
||||
.opaque_substitute = DRM_FORMAT_INVALID,
|
||||
.bpp = 32,
|
||||
.has_alpha = false,
|
||||
.drm_format = DRM_FORMAT_XRGB1555,
|
||||
.bytes_per_block = 2,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_ARGB1555,
|
||||
.opaque_substitute = DRM_FORMAT_XRGB1555,
|
||||
.bytes_per_block = 2,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_RGB565,
|
||||
.bytes_per_block = 2,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_BGR565,
|
||||
.bytes_per_block = 2,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_XRGB2101010,
|
||||
.bytes_per_block = 4,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_ARGB2101010,
|
||||
.opaque_substitute = DRM_FORMAT_XRGB2101010,
|
||||
.bpp = 32,
|
||||
.bytes_per_block = 4,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_XBGR2101010,
|
||||
.opaque_substitute = DRM_FORMAT_INVALID,
|
||||
.bpp = 32,
|
||||
.has_alpha = false,
|
||||
.drm_format = DRM_FORMAT_XBGR2101010,
|
||||
.bytes_per_block = 4,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_ABGR2101010,
|
||||
.opaque_substitute = DRM_FORMAT_XBGR2101010,
|
||||
.bpp = 32,
|
||||
.bytes_per_block = 4,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_XBGR16161616F,
|
||||
.opaque_substitute = DRM_FORMAT_INVALID,
|
||||
.bpp = 64,
|
||||
.has_alpha = false,
|
||||
.drm_format = DRM_FORMAT_XBGR16161616F,
|
||||
.bytes_per_block = 8,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_ABGR16161616F,
|
||||
.opaque_substitute = DRM_FORMAT_XBGR16161616F,
|
||||
.bpp = 64,
|
||||
.bytes_per_block = 8,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_XBGR16161616,
|
||||
.opaque_substitute = DRM_FORMAT_INVALID,
|
||||
.bpp = 64,
|
||||
.has_alpha = false,
|
||||
.drm_format = DRM_FORMAT_XBGR16161616,
|
||||
.bytes_per_block = 8,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_ABGR16161616,
|
||||
.opaque_substitute = DRM_FORMAT_XBGR16161616,
|
||||
.bpp = 64,
|
||||
.bytes_per_block = 8,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_YVYU,
|
||||
.bytes_per_block = 4,
|
||||
.block_width = 2,
|
||||
.block_height = 1,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_VYUY,
|
||||
.bytes_per_block = 4,
|
||||
.block_width = 2,
|
||||
.block_height = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static const size_t pixel_format_info_size = sizeof(pixel_format_info) / sizeof(pixel_format_info[0]);
|
||||
@@ -187,124 +217,27 @@ static enum wl_shm_format convert_drm_format_to_wl_shm(uint32_t fmt) {
|
||||
}
|
||||
}
|
||||
|
||||
struct wlr_gles2_pixel_format {
|
||||
uint32_t drm_format;
|
||||
// optional field, if empty then internalformat = format
|
||||
GLint gl_internalformat;
|
||||
GLint gl_format, gl_type;
|
||||
bool has_alpha;
|
||||
};
|
||||
static uint32_t pixel_format_info_pixels_per_block(const struct wlr_pixel_format_info* info) {
|
||||
uint32_t pixels = info->block_width * info->block_height;
|
||||
return pixels > 0 ? pixels : 1;
|
||||
}
|
||||
|
||||
static const struct wlr_gles2_pixel_format formats[] = {
|
||||
{
|
||||
.drm_format = DRM_FORMAT_ARGB8888,
|
||||
.gl_format = GL_BGRA_EXT,
|
||||
.gl_type = GL_UNSIGNED_BYTE,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_XRGB8888,
|
||||
.gl_format = GL_BGRA_EXT,
|
||||
.gl_type = GL_UNSIGNED_BYTE,
|
||||
.has_alpha = false,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_XBGR8888,
|
||||
.gl_format = GL_RGBA,
|
||||
.gl_type = GL_UNSIGNED_BYTE,
|
||||
.has_alpha = false,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_ABGR8888,
|
||||
.gl_format = GL_RGBA,
|
||||
.gl_type = GL_UNSIGNED_BYTE,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_BGR888,
|
||||
.gl_format = GL_RGB,
|
||||
.gl_type = GL_UNSIGNED_BYTE,
|
||||
.has_alpha = false,
|
||||
},
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
{
|
||||
.drm_format = DRM_FORMAT_RGBX4444,
|
||||
.gl_format = GL_RGBA,
|
||||
.gl_type = GL_UNSIGNED_SHORT_4_4_4_4,
|
||||
.has_alpha = false,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_RGBA4444,
|
||||
.gl_format = GL_RGBA,
|
||||
.gl_type = GL_UNSIGNED_SHORT_4_4_4_4,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_RGBX5551,
|
||||
.gl_format = GL_RGBA,
|
||||
.gl_type = GL_UNSIGNED_SHORT_5_5_5_1,
|
||||
.has_alpha = false,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_RGBA5551,
|
||||
.gl_format = GL_RGBA,
|
||||
.gl_type = GL_UNSIGNED_SHORT_5_5_5_1,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_RGB565,
|
||||
.gl_format = GL_RGB,
|
||||
.gl_type = GL_UNSIGNED_SHORT_5_6_5,
|
||||
.has_alpha = false,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_XBGR2101010,
|
||||
.gl_format = GL_RGBA,
|
||||
.gl_type = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
|
||||
.has_alpha = false,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_ABGR2101010,
|
||||
.gl_format = GL_RGBA,
|
||||
.gl_type = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_XBGR16161616F,
|
||||
.gl_format = GL_RGBA,
|
||||
.gl_type = GL_HALF_FLOAT_OES,
|
||||
.has_alpha = false,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_ABGR16161616F,
|
||||
.gl_format = GL_RGBA,
|
||||
.gl_type = GL_HALF_FLOAT_OES,
|
||||
.has_alpha = true,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_XBGR16161616,
|
||||
.gl_internalformat = GL_RGBA16_EXT,
|
||||
.gl_format = GL_RGBA,
|
||||
.gl_type = GL_UNSIGNED_SHORT,
|
||||
.has_alpha = false,
|
||||
},
|
||||
{
|
||||
.drm_format = DRM_FORMAT_ABGR16161616,
|
||||
.gl_internalformat = GL_RGBA16_EXT,
|
||||
.gl_format = GL_RGBA,
|
||||
.gl_type = GL_UNSIGNED_SHORT,
|
||||
.has_alpha = true,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
inline const struct wlr_gles2_pixel_format* gles2FromDRM(uint32_t fmt) {
|
||||
for (size_t i = 0; i < sizeof(formats) / sizeof(*formats); ++i) {
|
||||
if (formats[i].drm_format == fmt) {
|
||||
return &formats[i];
|
||||
}
|
||||
static int32_t div_round_up(int32_t dividend, int32_t divisor) {
|
||||
int32_t quotient = dividend / divisor;
|
||||
if (dividend % divisor != 0) {
|
||||
quotient++;
|
||||
}
|
||||
return NULL;
|
||||
return quotient;
|
||||
}
|
||||
|
||||
static int32_t pixel_format_info_min_stride(const wlr_pixel_format_info* fmt, int32_t width) {
|
||||
int32_t pixels_per_block = (int32_t)pixel_format_info_pixels_per_block(fmt);
|
||||
int32_t bytes_per_block = (int32_t)fmt->bytes_per_block;
|
||||
if (width > INT32_MAX / bytes_per_block) {
|
||||
wlr_log(WLR_DEBUG, "Invalid width %d (overflow)", width);
|
||||
return 0;
|
||||
}
|
||||
return div_round_up(width * bytes_per_block, pixels_per_block);
|
||||
}
|
||||
|
||||
#endif
|
@@ -6,13 +6,7 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) {
|
||||
RASSERT((w > 1 && h > 1), "cannot alloc a FB with negative / zero size! (attempted {}x{})", w, h);
|
||||
|
||||
uint32_t glFormat = drmFormatToGL(drmFormat);
|
||||
uint32_t glType = glFormat != GL_RGBA ?
|
||||
#ifdef GLES2
|
||||
GL_UNSIGNED_INT_2_10_10_10_REV_EXT :
|
||||
#else
|
||||
GL_UNSIGNED_INT_2_10_10_10_REV :
|
||||
#endif
|
||||
GL_UNSIGNED_BYTE;
|
||||
uint32_t glType = glFormatToType(glFormat);
|
||||
|
||||
if (m_iFb == (uint32_t)-1) {
|
||||
firstAlloc = true;
|
||||
@@ -62,6 +56,24 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void CFramebuffer::addStencil() {
|
||||
// TODO: Allow this with gles2
|
||||
#ifndef GLES2
|
||||
glBindTexture(GL_TEXTURE_2D, m_pStencilTex->m_iTexID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_vSize.x, m_vSize.y, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iFb);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_pStencilTex->m_iTexID, 0);
|
||||
|
||||
auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
RASSERT((status == GL_FRAMEBUFFER_COMPLETE), "Failed adding a stencil to fbo!", status);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_iCurrentOutputFb);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CFramebuffer::bind() {
|
||||
#ifndef GLES2
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_iFb);
|
||||
|
@@ -8,6 +8,7 @@ class CFramebuffer {
|
||||
~CFramebuffer();
|
||||
|
||||
bool alloc(int w, int h, uint32_t format = GL_RGBA);
|
||||
void addStencil();
|
||||
void bind();
|
||||
void release();
|
||||
void reset();
|
||||
|
@@ -5,6 +5,15 @@
|
||||
#include "Shaders.hpp"
|
||||
#include <random>
|
||||
|
||||
inline void loadGLProc(void* pProc, const char* name) {
|
||||
void* proc = (void*)eglGetProcAddress(name);
|
||||
if (proc == NULL) {
|
||||
Debug::log(CRIT, "[Tracy GPU Profiling] eglGetProcAddress({}) failed", name);
|
||||
abort();
|
||||
}
|
||||
*(void**)pProc = proc;
|
||||
}
|
||||
|
||||
CHyprOpenGLImpl::CHyprOpenGLImpl() {
|
||||
RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)),
|
||||
"Couldn't unset current EGL!");
|
||||
@@ -23,6 +32,11 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() {
|
||||
Debug::log(LOG, "Renderer: {}", (char*)glGetString(GL_RENDERER));
|
||||
Debug::log(LOG, "Supported extensions size: {}", std::count(m_szExtensions.begin(), m_szExtensions.end(), ' '));
|
||||
|
||||
loadGLProc(&m_sProc.glEGLImageTargetRenderbufferStorageOES, "glEGLImageTargetRenderbufferStorageOES");
|
||||
loadGLProc(&m_sProc.eglDestroyImageKHR, "eglDestroyImageKHR");
|
||||
|
||||
m_sExts.EXT_read_format_bgra = m_szExtensions.contains("GL_EXT_read_format_bgra");
|
||||
|
||||
#ifdef USE_TRACY_GPU
|
||||
|
||||
loadGLProc(&glQueryCounter, "glQueryCounterEXT");
|
||||
@@ -103,34 +117,96 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool
|
||||
return shader;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) {
|
||||
bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) {
|
||||
// passes requiring introspection are the ones that need to render blur.
|
||||
|
||||
static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue;
|
||||
static auto* const PXRAY = &g_pConfigManager->getConfigValuePtr("decoration:blur:xray")->intValue;
|
||||
static auto* const POPTIM = &g_pConfigManager->getConfigValuePtr("decoration:blur:new_optimizations")->intValue;
|
||||
static auto* const PBLURSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:blur:special")->intValue;
|
||||
|
||||
if (m_RenderData.mouseZoomFactor != 1.0)
|
||||
return true;
|
||||
|
||||
if (!pMonitor->mirrors.empty())
|
||||
return true;
|
||||
|
||||
if (*PBLUR == 0)
|
||||
return false;
|
||||
|
||||
if (m_RenderData.pCurrentMonData->blurFBShouldRender)
|
||||
return true;
|
||||
|
||||
if (pMonitor->solitaryClient)
|
||||
return false;
|
||||
|
||||
for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
|
||||
const auto XRAYMODE = ls->xray == -1 ? *PXRAY : ls->xray;
|
||||
if (ls->forceBlur && !XRAYMODE)
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
const auto XRAYMODE = ls->xray == -1 ? *PXRAY : ls->xray;
|
||||
if (ls->forceBlur && !XRAYMODE)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (*PBLURSPECIAL) {
|
||||
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||
if (!ws->m_bIsSpecialWorkspace || ws->m_iMonitorID != pMonitor->ID)
|
||||
continue;
|
||||
|
||||
if (ws->m_fAlpha.fl() == 0)
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (*PXRAY)
|
||||
return false;
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (!w->m_bIsMapped || w->isHidden() || (!w->m_bIsFloating && *POPTIM && !g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID)))
|
||||
continue;
|
||||
|
||||
if (!g_pHyprRenderer->shouldRenderWindow(w.get()))
|
||||
continue;
|
||||
|
||||
if (w->m_sAdditionalConfigData.forceNoBlur.toUnderlying() == true || w->m_sAdditionalConfigData.xray.toUnderlying() == true)
|
||||
continue;
|
||||
|
||||
if (w->opaque())
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, CFramebuffer* fb) {
|
||||
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));
|
||||
}
|
||||
|
||||
glViewport(0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
|
||||
matrixProjection(m_RenderData.projection, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
|
||||
m_RenderData.pCurrentMonData = &m_mMonitorRenderResources[pMonitor];
|
||||
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_iCurrentOutputFb);
|
||||
m_iWLROutputFb = m_iCurrentOutputFb;
|
||||
|
||||
// ensure a framebuffer for the monitor exists
|
||||
if (!m_mMonitorRenderResources.contains(pMonitor) || m_RenderData.pCurrentMonData->primaryFB.m_vSize != pMonitor->vecPixelSize) {
|
||||
if (!m_mMonitorRenderResources.contains(pMonitor) || m_RenderData.pCurrentMonData->offloadFB.m_vSize != pMonitor->vecPixelSize) {
|
||||
m_RenderData.pCurrentMonData->stencilTex.allocate();
|
||||
|
||||
m_RenderData.pCurrentMonData->primaryFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
m_RenderData.pCurrentMonData->offloadFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
m_RenderData.pCurrentMonData->mirrorFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
m_RenderData.pCurrentMonData->offMainFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
|
||||
m_RenderData.pCurrentMonData->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
||||
m_RenderData.pCurrentMonData->offloadFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
||||
m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
||||
m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
||||
m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat);
|
||||
@@ -144,19 +220,38 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) {
|
||||
if (!m_RenderData.pCurrentMonData->m_bShadersInitialized)
|
||||
initShaders();
|
||||
|
||||
// bind the primary Hypr Framebuffer
|
||||
m_RenderData.pCurrentMonData->primaryFB.bind();
|
||||
|
||||
m_RenderData.damage.set(*pDamage);
|
||||
|
||||
m_bFakeFrame = fake;
|
||||
|
||||
m_RenderData.currentFB = &m_RenderData.pCurrentMonData->primaryFB;
|
||||
m_bFakeFrame = fb;
|
||||
|
||||
if (m_bReloadScreenShader) {
|
||||
m_bReloadScreenShader = false;
|
||||
applyScreenShader(g_pConfigManager->getString("decoration:screen_shader"));
|
||||
}
|
||||
|
||||
const auto PRBO = g_pHyprRenderer->getCurrentRBO();
|
||||
const bool FBPROPERSIZE = fb && fb->m_vSize == pMonitor->vecPixelSize;
|
||||
|
||||
if (!FBPROPERSIZE || m_sFinalScreenShader.program > 0 || (PRBO && pMonitor->vecPixelSize != PRBO->getFB()->m_vSize) || passRequiresIntrospection(pMonitor)) {
|
||||
// we have to offload
|
||||
// bind the offload Hypr Framebuffer
|
||||
m_RenderData.pCurrentMonData->offloadFB.bind();
|
||||
m_RenderData.currentFB = &m_RenderData.pCurrentMonData->offloadFB;
|
||||
m_bOffloadedFramebuffer = true;
|
||||
} else {
|
||||
// we can render to the rbo / fbo (fake) directly
|
||||
const auto PFBO = fb ? fb : PRBO->getFB();
|
||||
m_RenderData.currentFB = PFBO;
|
||||
if (PFBO->m_pStencilTex != &m_RenderData.pCurrentMonData->stencilTex) {
|
||||
PFBO->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
PFBO->addStencil();
|
||||
}
|
||||
PFBO->bind();
|
||||
m_bOffloadedFramebuffer = false;
|
||||
}
|
||||
|
||||
m_RenderData.mainFB = m_RenderData.currentFB;
|
||||
m_RenderData.outFB = fb ? fb : PRBO->getFB();
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::end() {
|
||||
@@ -164,14 +259,15 @@ void CHyprOpenGLImpl::end() {
|
||||
|
||||
TRACY_GPU_ZONE("RenderEnd");
|
||||
|
||||
if (!m_RenderData.pMonitor->mirrors.empty() && !m_bFakeFrame)
|
||||
saveBufferForMirror(); // save with original damage region
|
||||
|
||||
// end the render, copy the data to the WLR framebuffer
|
||||
if (!m_bFakeFrame) {
|
||||
if (m_bOffloadedFramebuffer) {
|
||||
m_RenderData.damage = m_RenderData.pMonitor->lastFrameDamage;
|
||||
|
||||
if (!m_RenderData.pMonitor->mirrors.empty())
|
||||
saveBufferForMirror(); // save with original damage region
|
||||
m_RenderData.outFB->bind();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb);
|
||||
CBox monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
|
||||
if (m_RenderData.mouseZoomFactor != 1.f) {
|
||||
@@ -199,9 +295,9 @@ void CHyprOpenGLImpl::end() {
|
||||
blend(false);
|
||||
|
||||
if (m_sFinalScreenShader.program < 1)
|
||||
renderTexturePrimitive(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox);
|
||||
renderTexturePrimitive(m_RenderData.pCurrentMonData->offloadFB.m_cTex, &monbox);
|
||||
else
|
||||
renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 1.f);
|
||||
renderTexture(m_RenderData.pCurrentMonData->offloadFB.m_cTex, &monbox, 1.f);
|
||||
|
||||
blend(true);
|
||||
|
||||
@@ -212,15 +308,10 @@ void CHyprOpenGLImpl::end() {
|
||||
|
||||
// reset our data
|
||||
m_RenderData.pMonitor = nullptr;
|
||||
m_iWLROutputFb = 0;
|
||||
m_RenderData.mouseZoomFactor = 1.f;
|
||||
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;
|
||||
@@ -501,8 +592,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round
|
||||
|
||||
CFramebuffer* POUTFB = blurMainFramebufferWithDamage(blurA, &damage);
|
||||
|
||||
// bind primary
|
||||
m_RenderData.pCurrentMonData->primaryFB.bind();
|
||||
m_RenderData.currentFB->bind();
|
||||
|
||||
// make a stencil for rounded corners to work with blur
|
||||
scissor((CBox*)nullptr); // allow the entire window and stencil to render
|
||||
@@ -553,7 +643,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion
|
||||
|
||||
float matrix[9];
|
||||
wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0,
|
||||
m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
|
||||
m_RenderData.pMonitor->projMatrix.data()); // TODO: write own, don't use WLR here
|
||||
|
||||
float glMatrix[9];
|
||||
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
||||
@@ -640,7 +730,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox*
|
||||
// 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.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||
wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->projMatrix.data());
|
||||
|
||||
float glMatrix[9];
|
||||
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
||||
@@ -801,7 +891,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, CBox* pBox) {
|
||||
// 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.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||
wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->projMatrix.data());
|
||||
|
||||
float glMatrix[9];
|
||||
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
||||
@@ -855,7 +945,7 @@ void CHyprOpenGLImpl::renderTextureMatte(const CTexture& tex, CBox* pBox, CFrame
|
||||
// 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.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||
wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->projMatrix.data());
|
||||
|
||||
float glMatrix[9];
|
||||
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
||||
@@ -914,7 +1004,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
|
||||
const auto TRANSFORM = wlr_output_transform_invert(m_RenderData.pMonitor->transform);
|
||||
float matrix[9];
|
||||
CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
wlr_matrix_project_box(matrix, MONITORBOX.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix);
|
||||
wlr_matrix_project_box(matrix, MONITORBOX.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->projMatrix.data());
|
||||
|
||||
float glMatrix[9];
|
||||
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
||||
@@ -947,9 +1037,9 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glBindTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTarget, m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTexID);
|
||||
glBindTexture(m_RenderData.currentFB->m_cTex.m_iTarget, m_RenderData.currentFB->m_cTex.m_iTexID);
|
||||
|
||||
glTexParameteri(m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(m_RenderData.currentFB->m_cTex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glUseProgram(m_RenderData.pCurrentMonData->m_shBLURPREPARE.program);
|
||||
|
||||
@@ -957,7 +1047,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
|
||||
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_TRUE, glMatrix);
|
||||
#else
|
||||
wlr_matrix_transpose(glMatrix, glMatrix);
|
||||
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_FALSE, glMatrix);
|
||||
glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_FALSE, glMatrix);
|
||||
#endif
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.contrast, *PBLURCONTRAST);
|
||||
glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.brightness, *PBLURBRIGHTNESS);
|
||||
@@ -1117,13 +1207,6 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::markBlurDirtyForMonitor(CMonitor* pMonitor) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace);
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(pMonitor->activeWorkspace);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL && PFULLWINDOW && !PFULLWINDOW->m_vRealSize.isBeingAnimated() &&
|
||||
PFULLWINDOW->opaque())
|
||||
return;
|
||||
|
||||
m_mMonitorRenderResources[pMonitor].blurFBDirty = true;
|
||||
}
|
||||
|
||||
@@ -1135,6 +1218,10 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) {
|
||||
if (!*PBLURNEWOPTIMIZE || !m_mMonitorRenderResources[pMonitor].blurFBDirty || !*PBLUR)
|
||||
return;
|
||||
|
||||
// ignore if solitary present, nothing to blur
|
||||
if (pMonitor->solitaryClient)
|
||||
return;
|
||||
|
||||
// check if we need to update the blur fb
|
||||
// if there are no windows that would benefit from it,
|
||||
// we will ignore that the blur FB is dirty.
|
||||
@@ -1225,7 +1312,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() {
|
||||
renderTextureInternalWithDamage(POUTFB->m_cTex, &wholeMonitor, 1, &fakeDamage, 0, false, true, false);
|
||||
m_bEndFrame = false;
|
||||
|
||||
m_RenderData.pCurrentMonData->primaryFB.bind();
|
||||
m_RenderData.currentFB->bind();
|
||||
|
||||
m_RenderData.pCurrentMonData->blurFBDirty = false;
|
||||
|
||||
@@ -1294,7 +1381,8 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, flo
|
||||
|
||||
// amazing hack: the surface has an opaque region!
|
||||
CRegion inverseOpaque;
|
||||
if (a >= 1.f) {
|
||||
if (a >= 1.f && std::round(pSurface->current.width * m_RenderData.pMonitor->scale) == pBox->w &&
|
||||
std::round(pSurface->current.height * m_RenderData.pMonitor->scale) == pBox->h) {
|
||||
pixman_box32_t surfbox = {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);
|
||||
@@ -1321,8 +1409,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, flo
|
||||
POUTFB = &m_RenderData.pCurrentMonData->blurFB;
|
||||
}
|
||||
|
||||
// bind primary
|
||||
m_RenderData.pCurrentMonData->primaryFB.bind();
|
||||
m_RenderData.currentFB->bind();
|
||||
|
||||
// make a stencil for rounded corners to work with blur
|
||||
scissor((CBox*)nullptr); // allow the entire window and stencil to render
|
||||
@@ -1404,7 +1491,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in
|
||||
|
||||
float matrix[9];
|
||||
wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0,
|
||||
m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
|
||||
m_RenderData.pMonitor->projMatrix.data()); // TODO: write own, don't use WLR here
|
||||
|
||||
float glMatrix[9];
|
||||
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
||||
@@ -1478,14 +1565,18 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFra
|
||||
if (!PMONITOR || !PMONITOR->output || PMONITOR->vecPixelSize.x <= 0 || PMONITOR->vecPixelSize.y <= 0)
|
||||
return;
|
||||
|
||||
wlr_output_attach_render(PMONITOR->output, nullptr);
|
||||
|
||||
// we need to "damage" the entire monitor
|
||||
// so that we render the entire window
|
||||
// this is temporary, doesnt mess with the actual wlr damage
|
||||
CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y};
|
||||
|
||||
begin(PMONITOR, &fakeDamage, true);
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
pFramebuffer->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
|
||||
pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat);
|
||||
|
||||
g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, pFramebuffer);
|
||||
|
||||
clear(CColor(0, 0, 0, 0)); // JIC
|
||||
|
||||
@@ -1503,12 +1594,6 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFra
|
||||
// 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);
|
||||
|
||||
pFramebuffer->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
|
||||
pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat);
|
||||
|
||||
pFramebuffer->bind();
|
||||
|
||||
m_RenderData.currentFB = pFramebuffer;
|
||||
|
||||
clear(CColor(0, 0, 0, 0)); // JIC
|
||||
@@ -1517,15 +1602,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFra
|
||||
|
||||
g_pConfigManager->setInt("decoration:blur:enabled", BLURVAL);
|
||||
|
||||
// restore original fb
|
||||
#ifndef GLES2
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_iCurrentOutputFb);
|
||||
#else
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iCurrentOutputFb);
|
||||
#endif
|
||||
end();
|
||||
|
||||
wlr_output_rollback(PMONITOR->output);
|
||||
g_pHyprRenderer->endRender();
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
|
||||
@@ -1535,14 +1612,21 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
|
||||
if (!PMONITOR || !PMONITOR->output || PMONITOR->vecPixelSize.x <= 0 || PMONITOR->vecPixelSize.y <= 0)
|
||||
return;
|
||||
|
||||
wlr_output_attach_render(PMONITOR->output, nullptr);
|
||||
if (!g_pHyprRenderer->shouldRenderWindow(pWindow))
|
||||
return; // ignore, window is not being rendered
|
||||
|
||||
// we need to "damage" the entire monitor
|
||||
// so that we render the entire window
|
||||
// this is temporary, doesnt mess with the actual wlr damage
|
||||
CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y};
|
||||
|
||||
begin(PMONITOR, &fakeDamage, true);
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
const auto PFRAMEBUFFER = &m_mWindowFramebuffers[pWindow];
|
||||
|
||||
PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat);
|
||||
|
||||
g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, PFRAMEBUFFER);
|
||||
|
||||
g_pHyprRenderer->m_bRenderingSnapshot = true;
|
||||
|
||||
@@ -1559,35 +1643,15 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
|
||||
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);
|
||||
|
||||
const auto PFRAMEBUFFER = &m_mWindowFramebuffers[pWindow];
|
||||
|
||||
PFRAMEBUFFER->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
|
||||
PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat);
|
||||
|
||||
PFRAMEBUFFER->bind();
|
||||
|
||||
m_RenderData.currentFB = PFRAMEBUFFER;
|
||||
|
||||
clear(CColor(0, 0, 0, 0)); // JIC
|
||||
|
||||
g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders, RENDER_PASS_ALL);
|
||||
|
||||
g_pConfigManager->setInt("decoration:blur:enabled", BLURVAL);
|
||||
|
||||
// restore original fb
|
||||
#ifndef GLES2
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_iCurrentOutputFb);
|
||||
#else
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iCurrentOutputFb);
|
||||
#endif
|
||||
end();
|
||||
g_pHyprRenderer->endRender();
|
||||
|
||||
g_pHyprRenderer->m_bRenderingSnapshot = false;
|
||||
|
||||
wlr_output_rollback(PMONITOR->output);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
|
||||
@@ -1597,26 +1661,20 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
|
||||
if (!PMONITOR || !PMONITOR->output || PMONITOR->vecPixelSize.x <= 0 || PMONITOR->vecPixelSize.y <= 0)
|
||||
return;
|
||||
|
||||
wlr_output_attach_render(PMONITOR->output, nullptr);
|
||||
|
||||
// we need to "damage" the entire monitor
|
||||
// so that we render the entire window
|
||||
// this is temporary, doesnt mess with the actual wlr damage
|
||||
CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y};
|
||||
|
||||
begin(PMONITOR, &fakeDamage, true);
|
||||
|
||||
g_pHyprRenderer->m_bRenderingSnapshot = true;
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
const auto PFRAMEBUFFER = &m_mLayerFramebuffers[pLayer];
|
||||
|
||||
glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y);
|
||||
|
||||
PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat);
|
||||
|
||||
PFRAMEBUFFER->bind();
|
||||
g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, PFRAMEBUFFER);
|
||||
|
||||
m_RenderData.currentFB = PFRAMEBUFFER;
|
||||
g_pHyprRenderer->m_bRenderingSnapshot = true;
|
||||
|
||||
clear(CColor(0, 0, 0, 0)); // JIC
|
||||
|
||||
@@ -1631,20 +1689,9 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
|
||||
|
||||
pLayer->forceBlur = BLURLSSTATUS;
|
||||
|
||||
// TODO: WARN:
|
||||
// revise if any stencil-requiring rendering is done to the layers.
|
||||
|
||||
// restore original fb
|
||||
#ifndef GLES2
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_iCurrentOutputFb);
|
||||
#else
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iCurrentOutputFb);
|
||||
#endif
|
||||
end();
|
||||
g_pHyprRenderer->endRender();
|
||||
|
||||
g_pHyprRenderer->m_bRenderingSnapshot = false;
|
||||
|
||||
wlr_output_rollback(PMONITOR->output);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
|
||||
@@ -1741,7 +1788,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const
|
||||
|
||||
float matrix[9];
|
||||
wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0,
|
||||
m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
|
||||
m_RenderData.pMonitor->projMatrix.data()); // TODO: write own, don't use WLR here
|
||||
|
||||
float glMatrix[9];
|
||||
wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix);
|
||||
@@ -1808,11 +1855,11 @@ void CHyprOpenGLImpl::saveBufferForMirror() {
|
||||
|
||||
blend(false);
|
||||
|
||||
renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 1.f, 0, false, false);
|
||||
renderTexture(m_RenderData.currentFB->m_cTex, &monbox, 1.f, 0, false, false);
|
||||
|
||||
blend(true);
|
||||
|
||||
m_RenderData.pCurrentMonData->primaryFB.bind();
|
||||
m_RenderData.currentFB->bind();
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderMirrored() {
|
||||
@@ -1968,10 +2015,10 @@ void CHyprOpenGLImpl::clearWithTex() {
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) {
|
||||
wlr_output_attach_render(pMonitor->output, nullptr);
|
||||
g_pHyprRenderer->makeEGLCurrent();
|
||||
|
||||
g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].mirrorFB.release();
|
||||
g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].primaryFB.release();
|
||||
g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].offloadFB.release();
|
||||
g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].mirrorSwapFB.release();
|
||||
g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].monitorMirrorFB.release();
|
||||
g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].blurFB.release();
|
||||
@@ -1982,8 +2029,6 @@ void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) {
|
||||
g_pHyprOpenGL->m_mMonitorBGTextures.erase(pMonitor);
|
||||
|
||||
Debug::log(LOG, "Monitor {} -> destroyed all render data", pMonitor->szName);
|
||||
|
||||
wlr_output_rollback(pMonitor->output);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::saveMatrix() {
|
||||
@@ -2011,10 +2056,144 @@ void CHyprOpenGLImpl::renderOffToMain(CFramebuffer* off) {
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::bindBackOnMain() {
|
||||
m_RenderData.pCurrentMonData->primaryFB.bind();
|
||||
m_RenderData.currentFB = &m_RenderData.pCurrentMonData->primaryFB;
|
||||
m_RenderData.mainFB->bind();
|
||||
m_RenderData.currentFB = m_RenderData.mainFB;
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::setMonitorTransformEnabled(bool enabled) {
|
||||
m_bEndFrame = !enabled;
|
||||
}
|
||||
|
||||
inline const SGLPixelFormat GLES2_FORMATS[] = {
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_ARGB8888,
|
||||
.glFormat = GL_BGRA_EXT,
|
||||
.glType = GL_UNSIGNED_BYTE,
|
||||
.withAlpha = true,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_XRGB8888,
|
||||
.glFormat = GL_BGRA_EXT,
|
||||
.glType = GL_UNSIGNED_BYTE,
|
||||
.withAlpha = false,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_XBGR8888,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_BYTE,
|
||||
.withAlpha = false,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_ABGR8888,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_BYTE,
|
||||
.withAlpha = true,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_BGR888,
|
||||
.glFormat = GL_RGB,
|
||||
.glType = GL_UNSIGNED_BYTE,
|
||||
.withAlpha = false,
|
||||
},
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_RGBX4444,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT_4_4_4_4,
|
||||
.withAlpha = false,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_RGBA4444,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT_4_4_4_4,
|
||||
.withAlpha = true,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_RGBX5551,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT_5_5_5_1,
|
||||
.withAlpha = false,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_RGBA5551,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT_5_5_5_1,
|
||||
.withAlpha = true,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_RGB565,
|
||||
.glFormat = GL_RGB,
|
||||
.glType = GL_UNSIGNED_SHORT_5_6_5,
|
||||
.withAlpha = false,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_XBGR2101010,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
|
||||
.withAlpha = false,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_ABGR2101010,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_INT_2_10_10_10_REV_EXT,
|
||||
.withAlpha = true,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_XBGR16161616F,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_HALF_FLOAT_OES,
|
||||
.withAlpha = false,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_ABGR16161616F,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_HALF_FLOAT_OES,
|
||||
.withAlpha = true,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_XBGR16161616,
|
||||
.glInternalFormat = GL_RGBA16_EXT,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT,
|
||||
.withAlpha = false,
|
||||
},
|
||||
{
|
||||
.drmFormat = DRM_FORMAT_ABGR16161616,
|
||||
.glInternalFormat = GL_RGBA16_EXT,
|
||||
.glFormat = GL_RGBA,
|
||||
.glType = GL_UNSIGNED_SHORT,
|
||||
.withAlpha = true,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) {
|
||||
GLint glf = -1, glt = -1, as = -1;
|
||||
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf);
|
||||
glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glt);
|
||||
glGetIntegerv(GL_ALPHA_BITS, &as);
|
||||
|
||||
if (glf == 0 || glt == 0) {
|
||||
glf = drmFormatToGL(pMonitor->drmFormat);
|
||||
glt = glFormatToType(glf);
|
||||
}
|
||||
|
||||
for (auto& fmt : GLES2_FORMATS) {
|
||||
if (fmt.glFormat == glf && fmt.glType == glt && fmt.withAlpha == (as > 0))
|
||||
return fmt.drmFormat;
|
||||
}
|
||||
|
||||
if (m_sExts.EXT_read_format_bgra)
|
||||
return DRM_FORMAT_XRGB8888;
|
||||
|
||||
return DRM_FORMAT_XBGR8888;
|
||||
}
|
||||
|
||||
const SGLPixelFormat* CHyprOpenGLImpl::getPixelFormatFromDRM(uint32_t drmFormat) {
|
||||
for (auto& fmt : GLES2_FORMATS) {
|
||||
if (fmt.drmFormat == drmFormat)
|
||||
return &fmt;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
@@ -14,6 +14,9 @@
|
||||
#include "Texture.hpp"
|
||||
#include "Framebuffer.hpp"
|
||||
#include "Transformer.hpp"
|
||||
#include "Renderbuffer.hpp"
|
||||
|
||||
#include <GLES2/gl2ext.h>
|
||||
|
||||
#include "../debug/TracyDefines.hpp"
|
||||
|
||||
@@ -38,8 +41,16 @@ struct SRenderModifData {
|
||||
float scale = 1.f;
|
||||
};
|
||||
|
||||
struct SGLPixelFormat {
|
||||
uint32_t drmFormat = DRM_FORMAT_INVALID;
|
||||
GLint glInternalFormat = 0;
|
||||
GLint glFormat = 0;
|
||||
GLint glType = 0;
|
||||
bool withAlpha = false;
|
||||
};
|
||||
|
||||
struct SMonitorRenderData {
|
||||
CFramebuffer primaryFB;
|
||||
CFramebuffer offloadFB;
|
||||
CFramebuffer mirrorFB; // these are used for some effects,
|
||||
CFramebuffer mirrorSwapFB; // etc
|
||||
CFramebuffer offMainFB;
|
||||
@@ -79,7 +90,9 @@ struct SCurrentRenderData {
|
||||
float savedProjection[9];
|
||||
|
||||
SMonitorRenderData* pCurrentMonData = nullptr;
|
||||
CFramebuffer* currentFB = nullptr;
|
||||
CFramebuffer* currentFB = nullptr; // current rendering to
|
||||
CFramebuffer* mainFB = nullptr; // main to render to
|
||||
CFramebuffer* outFB = nullptr; // out to render to (if offloaded, etc)
|
||||
|
||||
CRegion damage;
|
||||
|
||||
@@ -103,72 +116,82 @@ class CHyprOpenGLImpl {
|
||||
public:
|
||||
CHyprOpenGLImpl();
|
||||
|
||||
void begin(CMonitor*, CRegion*, bool fake = false);
|
||||
void end();
|
||||
void bindWlrOutputFb();
|
||||
void begin(CMonitor*, CRegion*, CFramebuffer* fb = nullptr /* if provided, it's not a real frame */);
|
||||
void end();
|
||||
|
||||
void renderRect(CBox*, const CColor&, int round = 0);
|
||||
void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f);
|
||||
void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0);
|
||||
void renderTexture(wlr_texture*, CBox*, float a, int round = 0, bool allowCustomUV = false);
|
||||
void renderTexture(const CTexture&, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
|
||||
void renderTextureWithBlur(const CTexture&, CBox*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f);
|
||||
void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0);
|
||||
void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */);
|
||||
void renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte);
|
||||
void renderRect(CBox*, const CColor&, int round = 0);
|
||||
void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f);
|
||||
void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0);
|
||||
void renderTexture(wlr_texture*, CBox*, float a, int round = 0, bool allowCustomUV = false);
|
||||
void renderTexture(const CTexture&, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false);
|
||||
void renderTextureWithBlur(const CTexture&, CBox*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f);
|
||||
void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0);
|
||||
void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */);
|
||||
void renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte);
|
||||
|
||||
void setMonitorTransformEnabled(bool enabled);
|
||||
void setMonitorTransformEnabled(bool enabled);
|
||||
|
||||
void saveMatrix();
|
||||
void setMatrixScaleTranslate(const Vector2D& translate, const float& scale);
|
||||
void restoreMatrix();
|
||||
void saveMatrix();
|
||||
void setMatrixScaleTranslate(const Vector2D& translate, const float& scale);
|
||||
void restoreMatrix();
|
||||
|
||||
void blend(bool enabled);
|
||||
void blend(bool enabled);
|
||||
|
||||
void makeWindowSnapshot(CWindow*);
|
||||
void makeRawWindowSnapshot(CWindow*, CFramebuffer*);
|
||||
void makeLayerSnapshot(SLayerSurface*);
|
||||
void renderSnapshot(CWindow**);
|
||||
void renderSnapshot(SLayerSurface**);
|
||||
void makeWindowSnapshot(CWindow*);
|
||||
void makeRawWindowSnapshot(CWindow*, CFramebuffer*);
|
||||
void makeLayerSnapshot(SLayerSurface*);
|
||||
void renderSnapshot(CWindow**);
|
||||
void renderSnapshot(SLayerSurface**);
|
||||
|
||||
void clear(const CColor&);
|
||||
void clearWithTex();
|
||||
void scissor(const CBox*, bool transform = true);
|
||||
void scissor(const pixman_box32*, bool transform = true);
|
||||
void scissor(const int x, const int y, const int w, const int h, bool transform = true);
|
||||
void clear(const CColor&);
|
||||
void clearWithTex();
|
||||
void scissor(const CBox*, bool transform = true);
|
||||
void scissor(const pixman_box32*, bool transform = true);
|
||||
void scissor(const int x, const int y, const int w, const int h, bool transform = true);
|
||||
|
||||
void destroyMonitorResources(CMonitor*);
|
||||
void destroyMonitorResources(CMonitor*);
|
||||
|
||||
void markBlurDirtyForMonitor(CMonitor*);
|
||||
void markBlurDirtyForMonitor(CMonitor*);
|
||||
|
||||
void preWindowPass();
|
||||
bool preBlurQueued();
|
||||
void preRender(CMonitor*);
|
||||
void preWindowPass();
|
||||
bool preBlurQueued();
|
||||
void preRender(CMonitor*);
|
||||
|
||||
void saveBufferForMirror();
|
||||
void renderMirrored();
|
||||
void saveBufferForMirror();
|
||||
void renderMirrored();
|
||||
|
||||
void applyScreenShader(const std::string& path);
|
||||
void applyScreenShader(const std::string& path);
|
||||
|
||||
void bindOffMain();
|
||||
void renderOffToMain(CFramebuffer* off);
|
||||
void bindBackOnMain();
|
||||
void bindOffMain();
|
||||
void renderOffToMain(CFramebuffer* off);
|
||||
void bindBackOnMain();
|
||||
|
||||
SCurrentRenderData m_RenderData;
|
||||
uint32_t getPreferredReadFormat(CMonitor* pMonitor);
|
||||
const SGLPixelFormat* getPixelFormatFromDRM(uint32_t drmFormat);
|
||||
|
||||
GLint m_iCurrentOutputFb = 0;
|
||||
GLint m_iWLROutputFb = 0;
|
||||
SCurrentRenderData m_RenderData;
|
||||
|
||||
bool m_bReloadScreenShader = true; // at launch it can be set
|
||||
GLint m_iCurrentOutputFb = 0;
|
||||
|
||||
CWindow* m_pCurrentWindow = nullptr; // hack to get the current rendered window
|
||||
SLayerSurface* m_pCurrentLayer = nullptr; // hack to get the current rendered layer
|
||||
bool m_bReloadScreenShader = true; // at launch it can be set
|
||||
|
||||
CWindow* m_pCurrentWindow = nullptr; // hack to get the current rendered window
|
||||
SLayerSurface* m_pCurrentLayer = nullptr; // hack to get the current rendered layer
|
||||
|
||||
std::unordered_map<CWindow*, CFramebuffer> m_mWindowFramebuffers;
|
||||
std::unordered_map<SLayerSurface*, CFramebuffer> m_mLayerFramebuffers;
|
||||
std::unordered_map<CMonitor*, SMonitorRenderData> m_mMonitorRenderResources;
|
||||
std::unordered_map<CMonitor*, CTexture> m_mMonitorBGTextures;
|
||||
|
||||
struct {
|
||||
PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES = nullptr;
|
||||
PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = nullptr;
|
||||
} m_sProc;
|
||||
|
||||
struct {
|
||||
bool EXT_read_format_bgra = false;
|
||||
} m_sExts;
|
||||
|
||||
private:
|
||||
std::list<GLuint> m_lBuffers;
|
||||
std::list<GLuint> m_lTextures;
|
||||
@@ -176,10 +199,11 @@ class CHyprOpenGLImpl {
|
||||
int m_iDRMFD;
|
||||
std::string m_szExtensions;
|
||||
|
||||
bool m_bFakeFrame = false;
|
||||
bool m_bEndFrame = false;
|
||||
bool m_bApplyFinalShader = false;
|
||||
bool m_bBlend = false;
|
||||
bool m_bFakeFrame = false;
|
||||
bool m_bEndFrame = false;
|
||||
bool m_bApplyFinalShader = false;
|
||||
bool m_bBlend = false;
|
||||
bool m_bOffloadedFramebuffer = false;
|
||||
|
||||
CShader m_sFinalScreenShader;
|
||||
CTimer m_tGlobalTimer;
|
||||
@@ -201,6 +225,8 @@ class CHyprOpenGLImpl {
|
||||
|
||||
bool shouldUseNewBlurOptimizations(SLayerSurface* pLayer, CWindow* pWindow);
|
||||
|
||||
bool passRequiresIntrospection(CMonitor* pMonitor);
|
||||
|
||||
friend class CHyprRenderer;
|
||||
};
|
||||
|
||||
|
84
src/render/Renderbuffer.cpp
Normal file
84
src/render/Renderbuffer.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "Renderbuffer.hpp"
|
||||
#include "OpenGL.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
CRenderbuffer::~CRenderbuffer() {
|
||||
if (!g_pCompositor)
|
||||
return;
|
||||
|
||||
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));
|
||||
|
||||
m_sFramebuffer.release();
|
||||
glDeleteRenderbuffers(1, &m_iRBO);
|
||||
|
||||
g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(wlr_egl_get_display(g_pCompositor->m_sWLREGL), m_iImage);
|
||||
}
|
||||
|
||||
CRenderbuffer::CRenderbuffer(wlr_buffer* buffer, uint32_t format) : m_pWlrBuffer(buffer) {
|
||||
|
||||
// EVIL, but we can't include a hidden header because nixos is fucking special
|
||||
static EGLImageKHR (*PWLREGLCREATEIMAGEFROMDMABUF)(wlr_egl*, wlr_dmabuf_attributes*, bool*);
|
||||
static bool symbolFound = false;
|
||||
if (!symbolFound) {
|
||||
PWLREGLCREATEIMAGEFROMDMABUF = reinterpret_cast<EGLImageKHR (*)(wlr_egl*, wlr_dmabuf_attributes*, bool*)>(dlsym(RTLD_DEFAULT, "wlr_egl_create_image_from_dmabuf"));
|
||||
|
||||
symbolFound = true;
|
||||
|
||||
RASSERT(PWLREGLCREATEIMAGEFROMDMABUF, "wlr_egl_create_image_from_dmabuf was not found in wlroots!");
|
||||
|
||||
Debug::log(LOG, "CRenderbuffer: wlr_egl_create_image_from_dmabuf found at {:x}", (uintptr_t)PWLREGLCREATEIMAGEFROMDMABUF);
|
||||
}
|
||||
// end evil hack
|
||||
|
||||
struct wlr_dmabuf_attributes dmabuf = {0};
|
||||
if (!wlr_buffer_get_dmabuf(buffer, &dmabuf))
|
||||
throw std::runtime_error("wlr_buffer_get_dmabuf failed");
|
||||
|
||||
bool externalOnly;
|
||||
m_iImage = PWLREGLCREATEIMAGEFROMDMABUF(g_pCompositor->m_sWLREGL, &dmabuf, &externalOnly);
|
||||
if (m_iImage == EGL_NO_IMAGE_KHR)
|
||||
throw std::runtime_error("wlr_egl_create_image_from_dmabuf failed");
|
||||
|
||||
glGenRenderbuffers(1, &m_iRBO);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_iRBO);
|
||||
g_pHyprOpenGL->m_sProc.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)m_iImage);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
|
||||
glGenFramebuffers(1, &m_sFramebuffer.m_iFb);
|
||||
m_sFramebuffer.m_vSize = {buffer->width, buffer->height};
|
||||
m_sFramebuffer.bind();
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_iRBO);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
throw std::runtime_error("rbo: glCheckFramebufferStatus failed");
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
hyprListener_destroyBuffer.initCallback(
|
||||
&buffer->events.destroy, [](void* owner, void* data) { g_pHyprRenderer->onRenderbufferDestroy((CRenderbuffer*)owner); }, this, "CRenderbuffer");
|
||||
}
|
||||
|
||||
void CRenderbuffer::bind() {
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_iRBO);
|
||||
bindFB();
|
||||
}
|
||||
|
||||
void CRenderbuffer::bindFB() {
|
||||
m_sFramebuffer.bind();
|
||||
}
|
||||
|
||||
void CRenderbuffer::unbind() {
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
#ifndef GLES2
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
#else
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
CFramebuffer* CRenderbuffer::getFB() {
|
||||
return &m_sFramebuffer;
|
||||
}
|
25
src/render/Renderbuffer.hpp
Normal file
25
src/render/Renderbuffer.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "Framebuffer.hpp"
|
||||
|
||||
class CMonitor;
|
||||
|
||||
class CRenderbuffer {
|
||||
public:
|
||||
CRenderbuffer(wlr_buffer* buffer, uint32_t format);
|
||||
~CRenderbuffer();
|
||||
|
||||
void bind();
|
||||
void bindFB();
|
||||
void unbind();
|
||||
CFramebuffer* getFB();
|
||||
|
||||
wlr_buffer* m_pWlrBuffer = nullptr;
|
||||
|
||||
DYNLISTENER(destroyBuffer);
|
||||
|
||||
private:
|
||||
EGLImageKHR m_iImage = 0;
|
||||
GLuint m_iRBO = 0;
|
||||
CFramebuffer m_sFramebuffer;
|
||||
};
|
@@ -2,12 +2,53 @@
|
||||
#include "../Compositor.hpp"
|
||||
#include "linux-dmabuf-unstable-v1-protocol.h"
|
||||
#include "../helpers/Region.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
extern "C" {
|
||||
#include <xf86drm.h>
|
||||
}
|
||||
|
||||
CHyprRenderer::CHyprRenderer() {
|
||||
const auto ENV = getenv("WLR_DRM_NO_ATOMIC");
|
||||
|
||||
if (ENV && std::string(ENV) == "1")
|
||||
m_bTearingEnvSatisfied = true;
|
||||
|
||||
if (g_pCompositor->m_sWLRSession) {
|
||||
wlr_device* dev;
|
||||
wl_list_for_each(dev, &g_pCompositor->m_sWLRSession->devices, link) {
|
||||
const auto DRMV = drmGetVersion(dev->fd);
|
||||
|
||||
std::string name = std::string{DRMV->name, DRMV->name_len};
|
||||
std::transform(name.begin(), name.end(), name.begin(), tolower);
|
||||
|
||||
if (name.contains("nvidia"))
|
||||
m_bNvidia = true;
|
||||
|
||||
Debug::log(LOG, "DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel,
|
||||
std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len});
|
||||
|
||||
drmFreeVersion(DRMV);
|
||||
}
|
||||
} else {
|
||||
Debug::log(LOG, "m_sWLRSession is null, omitting full DRM node checks");
|
||||
|
||||
const auto DRMV = drmGetVersion(g_pCompositor->m_iDRMFD);
|
||||
|
||||
std::string name = std::string{DRMV->name, DRMV->name_len};
|
||||
std::transform(name.begin(), name.end(), name.begin(), tolower);
|
||||
|
||||
if (name.contains("nvidia"))
|
||||
m_bNvidia = true;
|
||||
|
||||
Debug::log(LOG, "Primary DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel,
|
||||
std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len});
|
||||
|
||||
drmFreeVersion(DRMV);
|
||||
}
|
||||
|
||||
if (m_bNvidia)
|
||||
Debug::log(WARN, "NVIDIA detected, please remember to follow nvidia instructions on the wiki");
|
||||
}
|
||||
|
||||
void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
||||
@@ -65,7 +106,7 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
||||
if (windowBox.width <= 1 || windowBox.height <= 1)
|
||||
return; // invisible
|
||||
|
||||
g_pHyprRenderer->calculateUVForSurface(RDATA->pWindow, surface, RDATA->squishOversized);
|
||||
g_pHyprRenderer->calculateUVForSurface(RDATA->pWindow, surface, RDATA->surface == surface);
|
||||
|
||||
windowBox.scale(RDATA->pMonitor->scale);
|
||||
windowBox.round();
|
||||
@@ -188,6 +229,9 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp
|
||||
if (w->m_bIsFullscreen || w->m_bIsFloating)
|
||||
continue;
|
||||
|
||||
if (pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
|
||||
}
|
||||
|
||||
@@ -202,9 +246,16 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp
|
||||
if (w->m_bIsFullscreen || !w->m_bIsFloating)
|
||||
continue;
|
||||
|
||||
if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
if (pWorkspace->m_bIsSpecialWorkspace && w->m_iMonitorID != pWorkspace->m_iMonitorID)
|
||||
continue; // special on another are rendered as a part of the base pass
|
||||
|
||||
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
|
||||
}
|
||||
|
||||
// TODO: this pass sucks
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID);
|
||||
|
||||
@@ -216,7 +267,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp
|
||||
continue;
|
||||
}
|
||||
|
||||
if (w->m_iWorkspaceID == pMonitor->activeWorkspace && !w->m_bIsFullscreen)
|
||||
if (w->m_iWorkspaceID != pMonitor->activeWorkspace || !w->m_bIsFullscreen)
|
||||
continue;
|
||||
|
||||
renderWindow(w.get(), pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL, RENDER_PASS_ALL);
|
||||
@@ -235,6 +286,12 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp
|
||||
if (w->m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || (!w->m_bCreatedOverFullscreen && !w->m_bPinned) || (!w->m_bIsMapped && !w->m_bFadingOut) || w->m_bIsFullscreen)
|
||||
continue;
|
||||
|
||||
if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
if (pWorkspace->m_bIsSpecialWorkspace && w->m_iMonitorID != pWorkspace->m_iMonitorID)
|
||||
continue; // special on another are rendered as a part of the base pass
|
||||
|
||||
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
|
||||
}
|
||||
}
|
||||
@@ -252,14 +309,14 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork
|
||||
if (w->m_bIsFloating)
|
||||
continue; // floating are in the second pass
|
||||
|
||||
if (g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue; // special are in the third pass
|
||||
|
||||
if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace))
|
||||
continue;
|
||||
|
||||
if (pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
// render active window after all others of this pass
|
||||
if (w.get() == g_pCompositor->m_pLastWindow) {
|
||||
if (w.get() == g_pCompositor->m_pLastWindow && w->m_iWorkspaceID == pWorkspace->m_iID) {
|
||||
lastWindow = w.get();
|
||||
continue;
|
||||
}
|
||||
@@ -279,8 +336,8 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork
|
||||
if (w->m_bIsFloating)
|
||||
continue; // floating are in the second pass
|
||||
|
||||
if (g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue; // special are in the third pass
|
||||
if (pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace))
|
||||
continue;
|
||||
@@ -297,29 +354,14 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork
|
||||
if (!w->m_bIsFloating || w->m_bPinned)
|
||||
continue;
|
||||
|
||||
if (g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace))
|
||||
continue;
|
||||
|
||||
// render the bad boy
|
||||
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
|
||||
}
|
||||
|
||||
// pinned always above
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut)
|
||||
if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
if (!w->m_bPinned || !w->m_bIsFloating)
|
||||
continue;
|
||||
|
||||
if (g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace))
|
||||
continue;
|
||||
if (pWorkspace->m_bIsSpecialWorkspace && w->m_iMonitorID != pWorkspace->m_iMonitorID)
|
||||
continue; // special on another are rendered as a part of the base pass
|
||||
|
||||
// render the bad boy
|
||||
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
|
||||
@@ -418,6 +460,12 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
renderdata.y += offset.y;
|
||||
}
|
||||
|
||||
// if window is floating and we have a slide animation, clip it to its full bb
|
||||
if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bIsFullscreen && PWORKSPACE->m_vRenderOffset.isBeingAnimated()) {
|
||||
CRegion rg = pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition + PWORKSPACE->m_vRenderOffset.vec()).scale(pMonitor->scale);
|
||||
g_pHyprOpenGL->m_RenderData.clipBox = rg.getExtents();
|
||||
}
|
||||
|
||||
// render window decorations first, if not fullscreen full
|
||||
if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_MAIN) {
|
||||
|
||||
@@ -507,6 +555,8 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
}
|
||||
}
|
||||
|
||||
g_pHyprOpenGL->m_RenderData.clipBox = CBox();
|
||||
|
||||
if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_POPUP) {
|
||||
if (!pWindow->m_bIsX11) {
|
||||
CBox geom;
|
||||
@@ -539,7 +589,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec*
|
||||
EMIT_HOOK_EVENT("render", RENDER_POST_WINDOW);
|
||||
|
||||
g_pHyprOpenGL->m_pCurrentWindow = nullptr;
|
||||
g_pHyprOpenGL->m_RenderData.clipBox = {0, 0, 0, 0};
|
||||
g_pHyprOpenGL->m_RenderData.clipBox = CBox();
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, timespec* time) {
|
||||
@@ -600,9 +650,11 @@ void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, CMon
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* time, const Vector2D& translate, const float& scale) {
|
||||
static auto* const PDIMSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:dim_special")->floatValue;
|
||||
static auto* const PBLURSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:blur:special")->intValue;
|
||||
static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue;
|
||||
static auto* const PDIMSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:dim_special")->floatValue;
|
||||
static auto* const PBLURSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:blur:special")->intValue;
|
||||
static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue;
|
||||
static auto* const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue;
|
||||
static auto* const PBACKGROUNDCOLOR = &g_pConfigManager->getConfigValuePtr("misc:background_color")->intValue;
|
||||
|
||||
const SRenderModifData RENDERMODIFDATA = {translate, scale};
|
||||
|
||||
@@ -634,6 +686,15 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace*
|
||||
if (!g_pHyprOpenGL->m_RenderData.pCurrentMonData->blurFBShouldRender)
|
||||
setOccludedForBackLayers(g_pHyprOpenGL->m_RenderData.damage, pWorkspace);
|
||||
|
||||
g_pHyprOpenGL->blend(false);
|
||||
if (!canSkipBackBufferClear(pMonitor)) {
|
||||
if (*PRENDERTEX /* inverted cfg flag */)
|
||||
g_pHyprOpenGL->clear(CColor(*PBACKGROUNDCOLOR));
|
||||
else
|
||||
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
|
||||
}
|
||||
g_pHyprOpenGL->blend(true);
|
||||
|
||||
for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) {
|
||||
renderLayer(ls.get(), pMonitor, time);
|
||||
}
|
||||
@@ -674,11 +735,18 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace*
|
||||
}
|
||||
}
|
||||
|
||||
// special
|
||||
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||
if (ws->m_iMonitorID == pMonitor->ID && ws->m_fAlpha.fl() > 0.f && ws->m_bIsSpecialWorkspace)
|
||||
renderWorkspaceWindows(pMonitor, ws.get(), time);
|
||||
}
|
||||
|
||||
// pinned always above
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut)
|
||||
continue;
|
||||
|
||||
if (!g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))
|
||||
if (!w->m_bPinned || !w->m_bIsFloating)
|
||||
continue;
|
||||
|
||||
if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace))
|
||||
@@ -775,10 +843,16 @@ void CHyprRenderer::calculateUVForSurface(CWindow* pWindow, wlr_surface* pSurfac
|
||||
uvBR = uvBR - Vector2D(1.0 - WPERC * (uvBR.x - uvTL.x), 1.0 - HPERC * (uvBR.y - uvTL.y));
|
||||
uvTL = uvTL + TOADDTL;
|
||||
|
||||
if (geom.width > pWindow->m_vRealSize.vec().x || geom.height > pWindow->m_vRealSize.vec().y) {
|
||||
uvBR.x = uvBR.x * (pWindow->m_vRealSize.vec().x / geom.width);
|
||||
uvBR.y = uvBR.y * (pWindow->m_vRealSize.vec().y / geom.height);
|
||||
}
|
||||
// TODO: make this passed to the func. Might break in the future.
|
||||
auto maxSize = pWindow->m_vRealSize.vec();
|
||||
|
||||
if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall)
|
||||
maxSize = pWindow->m_pWLSurface.getViewporterCorrectedSize();
|
||||
|
||||
if (geom.width > maxSize.x)
|
||||
uvBR.x = uvBR.x * (maxSize.x / geom.width);
|
||||
if (geom.height > maxSize.y)
|
||||
uvBR.y = uvBR.y * (maxSize.y / geom.height);
|
||||
}
|
||||
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = uvTL;
|
||||
@@ -841,8 +915,8 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) {
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||
static std::chrono::high_resolution_clock::time_point startRender = std::chrono::high_resolution_clock::now();
|
||||
static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
static std::chrono::high_resolution_clock::time_point renderStart = std::chrono::high_resolution_clock::now();
|
||||
static std::chrono::high_resolution_clock::time_point renderStartOverlay = std::chrono::high_resolution_clock::now();
|
||||
static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
|
||||
static auto* const PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue;
|
||||
@@ -851,9 +925,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 PBACKGROUNDCOLOR = &g_pConfigManager->getConfigValuePtr("misc:background_color")->intValue;
|
||||
static auto* const PANIMENABLED = &g_pConfigManager->getConfigValuePtr("animations:enabled")->intValue;
|
||||
static auto* const PFIRSTLAUNCHANIM = &g_pConfigManager->getConfigValuePtr("animations:first_launch_animation")->intValue;
|
||||
static auto* const PTEARINGENABLED = &g_pConfigManager->getConfigValuePtr("general:allow_tearing")->intValue;
|
||||
|
||||
static int damageBlinkCleanup = 0; // because double-buffered
|
||||
@@ -862,7 +935,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||
damageBlinkCleanup = 0;
|
||||
|
||||
static bool firstLaunch = true;
|
||||
static bool firstLaunchAnimActive = true;
|
||||
static bool firstLaunchAnimActive = *PFIRSTLAUNCHANIM;
|
||||
|
||||
float zoomInFactorFirstLaunch = 1.f;
|
||||
|
||||
@@ -883,7 +956,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||
firstLaunchAnimActive = false;
|
||||
}
|
||||
|
||||
startRender = std::chrono::high_resolution_clock::now();
|
||||
renderStart = std::chrono::high_resolution_clock::now();
|
||||
|
||||
if (*PDEBUGOVERLAY == 1) {
|
||||
g_pDebugOverlay->frameData(pMonitor);
|
||||
@@ -987,7 +1060,6 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||
// check the damage
|
||||
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;
|
||||
@@ -1003,16 +1075,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||
if (UNLOCK_SC)
|
||||
wlr_output_lock_software_cursors(pMonitor->output, true);
|
||||
|
||||
if (!wlr_output_attach_render(pMonitor->output, &bufferAge)) {
|
||||
Debug::log(ERR, "Couldn't attach render to display {} ???", pMonitor->szName);
|
||||
|
||||
if (UNLOCK_SC)
|
||||
wlr_output_lock_software_cursors(pMonitor->output, false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_damage_ring_get_buffer_damage(&pMonitor->damage, bufferAge, damage.pixman());
|
||||
wlr_damage_ring_get_buffer_damage(&pMonitor->damage, m_iLastBufferAge, damage.pixman());
|
||||
|
||||
pMonitor->renderingActive = true;
|
||||
|
||||
@@ -1058,7 +1121,25 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||
|
||||
TRACY_GPU_ZONE("Render");
|
||||
|
||||
g_pHyprOpenGL->begin(pMonitor, &damage);
|
||||
if (pMonitor == g_pCompositor->getMonitorFromCursor())
|
||||
g_pHyprOpenGL->m_RenderData.mouseZoomFactor = std::clamp(*PZOOMFACTOR, 1.f, INFINITY);
|
||||
else
|
||||
g_pHyprOpenGL->m_RenderData.mouseZoomFactor = 1.f;
|
||||
|
||||
if (zoomInFactorFirstLaunch > 1.f) {
|
||||
g_pHyprOpenGL->m_RenderData.mouseZoomFactor = zoomInFactorFirstLaunch;
|
||||
g_pHyprOpenGL->m_RenderData.mouseZoomUseMouse = false;
|
||||
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false;
|
||||
}
|
||||
|
||||
if (!beginRender(pMonitor, damage, RENDER_MODE_NORMAL)) {
|
||||
Debug::log(ERR, "renderer: couldn't beginRender()!");
|
||||
|
||||
if (UNLOCK_SC)
|
||||
wlr_output_lock_software_cursors(pMonitor->output, false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
EMIT_HOOK_EVENT("render", RENDER_BEGIN);
|
||||
|
||||
@@ -1072,15 +1153,6 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||
EMIT_HOOK_EVENT("render", RENDER_POST_MIRROR);
|
||||
renderCursor = false;
|
||||
} else {
|
||||
g_pHyprOpenGL->blend(false);
|
||||
if (!canSkipBackBufferClear(pMonitor)) {
|
||||
if (*PRENDERTEX /* inverted cfg flag */)
|
||||
g_pHyprOpenGL->clear(CColor(*PBACKGROUNDCOLOR));
|
||||
else
|
||||
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
|
||||
}
|
||||
g_pHyprOpenGL->blend(true);
|
||||
|
||||
CBox renderBox = {0, 0, (int)pMonitor->vecPixelSize.x, (int)pMonitor->vecPixelSize.y};
|
||||
renderWorkspace(pMonitor, g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace), &now, renderBox);
|
||||
|
||||
@@ -1093,7 +1165,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||
|
||||
// for drawing the debug overlay
|
||||
if (pMonitor == g_pCompositor->m_vMonitors.front().get() && *PDEBUGOVERLAY == 1) {
|
||||
startRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
renderStartOverlay = std::chrono::high_resolution_clock::now();
|
||||
g_pDebugOverlay->draw();
|
||||
endRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
@@ -1114,35 +1186,22 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||
|
||||
renderCursor = renderCursor && shouldRenderCursor();
|
||||
|
||||
if (renderCursor && wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y)) {
|
||||
if (renderCursor) {
|
||||
TRACY_GPU_ZONE("RenderCursor");
|
||||
|
||||
bool lockSoftware = pMonitor == g_pCompositor->getMonitorFromCursor() && *PZOOMFACTOR != 1.f;
|
||||
|
||||
if (lockSoftware) {
|
||||
wlr_output_lock_software_cursors(pMonitor->output, true);
|
||||
wlr_output_render_software_cursors(pMonitor->output, NULL);
|
||||
g_pHyprRenderer->renderSoftwareCursors(pMonitor, g_pHyprOpenGL->m_RenderData.damage);
|
||||
wlr_output_lock_software_cursors(pMonitor->output, false);
|
||||
} else
|
||||
wlr_output_render_software_cursors(pMonitor->output, NULL);
|
||||
|
||||
wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
|
||||
}
|
||||
|
||||
if (pMonitor == g_pCompositor->getMonitorFromCursor())
|
||||
g_pHyprOpenGL->m_RenderData.mouseZoomFactor = std::clamp(*PZOOMFACTOR, 1.f, INFINITY);
|
||||
else
|
||||
g_pHyprOpenGL->m_RenderData.mouseZoomFactor = 1.f;
|
||||
|
||||
if (zoomInFactorFirstLaunch > 1.f) {
|
||||
g_pHyprOpenGL->m_RenderData.mouseZoomFactor = zoomInFactorFirstLaunch;
|
||||
g_pHyprOpenGL->m_RenderData.mouseZoomUseMouse = false;
|
||||
g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false;
|
||||
g_pHyprRenderer->renderSoftwareCursors(pMonitor, g_pHyprOpenGL->m_RenderData.damage);
|
||||
}
|
||||
|
||||
EMIT_HOOK_EVENT("render", RENDER_LAST_MOMENT);
|
||||
|
||||
g_pHyprOpenGL->end();
|
||||
endRender();
|
||||
|
||||
TRACY_GPU_COLLECT;
|
||||
|
||||
@@ -1188,12 +1247,12 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) {
|
||||
|
||||
pMonitor->pendingFrame = false;
|
||||
|
||||
const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f;
|
||||
const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - renderStart).count() / 1000.f;
|
||||
g_pDebugOverlay->renderData(pMonitor, µs);
|
||||
|
||||
if (*PDEBUGOVERLAY == 1) {
|
||||
if (pMonitor == g_pCompositor->m_vMonitors.front().get()) {
|
||||
const float µsNoOverlay = µs - std::chrono::duration_cast<std::chrono::nanoseconds>(endRenderOverlay - startRenderOverlay).count() / 1000.f;
|
||||
const float µsNoOverlay = µs - std::chrono::duration_cast<std::chrono::nanoseconds>(endRenderOverlay - renderStartOverlay).count() / 1000.f;
|
||||
g_pDebugOverlay->renderDataNoOverlay(pMonitor, µsNoOverlay);
|
||||
} else {
|
||||
g_pDebugOverlay->renderDataNoOverlay(pMonitor, µs);
|
||||
@@ -1287,13 +1346,22 @@ void CHyprRenderer::outputMgrApplyTest(wlr_output_configuration_v1* config, bool
|
||||
break;
|
||||
}
|
||||
|
||||
if (!test)
|
||||
if (!test) {
|
||||
g_pConfigManager->m_bWantsMonitorReload = true; // for monitor keywords
|
||||
// if everything is disabled, performMonitorReload won't be called from renderMonitor
|
||||
bool allDisabled = std::all_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(),
|
||||
[](const auto m) { return !m->m_bEnabled || g_pCompositor->m_pUnsafeOutput == m.get(); });
|
||||
if (allDisabled) {
|
||||
Debug::log(LOG, "OutputMgr apply: All monitors disabled; performing monitor reload.");
|
||||
g_pConfigManager->performMonitorReload();
|
||||
}
|
||||
}
|
||||
|
||||
if (ok)
|
||||
wlr_output_configuration_v1_send_succeeded(config);
|
||||
else
|
||||
wlr_output_configuration_v1_send_failed(config);
|
||||
|
||||
wlr_output_configuration_v1_destroy(config);
|
||||
|
||||
Debug::log(LOG, "OutputMgr Applied/Tested.");
|
||||
@@ -1439,9 +1507,6 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vector<std:
|
||||
|
||||
if (Vector2D{box.width, box.height} != OLDSIZE)
|
||||
wlr_layer_surface_v1_configure(ls->layerSurface, box.width, box.height);
|
||||
|
||||
Debug::log(LOG, "LayerSurface {:x} arranged: x: {} y: {} w: {} h: {} with margins: t: {} l: {} r: {} b: {}", (uintptr_t)&ls, box.x, box.y, box.width, box.height,
|
||||
PSTATE->margin.top, PSTATE->margin.left, PSTATE->margin.right, PSTATE->margin.bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1480,8 +1545,6 @@ void CHyprRenderer::arrangeLayersForMonitor(const int& monitor) {
|
||||
damageMonitor(PMONITOR);
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitor);
|
||||
|
||||
Debug::log(LOG, "Monitor {} layers arranged: reserved: {:5j} {:5j}", PMONITOR->szName, PMONITOR->vecReservedTopLeft, PMONITOR->vecReservedBottomRight);
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y, double scale) {
|
||||
@@ -1645,7 +1708,6 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
|
||||
// if it's disabled, disable and ignore
|
||||
if (pMonitorRule->disabled) {
|
||||
|
||||
if (pMonitor->m_bEnabled)
|
||||
pMonitor->onDisconnect();
|
||||
|
||||
@@ -1950,6 +2012,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
pMonitor->vecPixelSize = Vector2D(transformedBox.width, transformedBox.height);
|
||||
}
|
||||
|
||||
pMonitor->updateMatrix();
|
||||
|
||||
// update renderer (here because it will call rollback, so we cannot do this before committing)
|
||||
g_pHyprOpenGL->destroyMonitorResources(pMonitor);
|
||||
|
||||
@@ -2123,7 +2187,12 @@ bool CHyprRenderer::canSkipBackBufferClear(CMonitor* pMonitor) {
|
||||
ls->geometry.height != pMonitor->vecSize.y)
|
||||
continue;
|
||||
|
||||
if (!ls->layerSurface->surface->opaque)
|
||||
// TODO: cache maybe?
|
||||
CRegion opaque = &ls->layerSurface->surface->opaque_region;
|
||||
CBox lsbox = {0, 0, ls->layerSurface->surface->current.buffer_width, ls->layerSurface->surface->current.buffer_height};
|
||||
opaque.invert(lsbox);
|
||||
|
||||
if (!opaque.empty())
|
||||
continue;
|
||||
|
||||
return true;
|
||||
@@ -2184,3 +2253,125 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) {
|
||||
// found one!
|
||||
pMonitor->solitaryClient = PCANDIDATE;
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderSoftwareCursors(CMonitor* pMonitor, const CRegion& damage, std::optional<Vector2D> overridePos) {
|
||||
const auto CURSORPOS = overridePos.value_or(g_pInputManager->getMouseCoordsInternal() - pMonitor->vecPosition) * pMonitor->scale;
|
||||
wlr_output_cursor* cursor;
|
||||
wl_list_for_each(cursor, &pMonitor->output->cursors, link) {
|
||||
if (!cursor->enabled || !cursor->visible || pMonitor->output->hardware_cursor == cursor)
|
||||
continue;
|
||||
|
||||
if (!cursor->texture)
|
||||
continue;
|
||||
|
||||
CBox cursorBox = CBox{CURSORPOS.x, CURSORPOS.y, cursor->width, cursor->height}.translate({-cursor->hotspot_x, -cursor->hotspot_y});
|
||||
|
||||
// TODO: NVIDIA doesn't like if we use renderTexturePrimitive here. Why?
|
||||
g_pHyprOpenGL->renderTexture(cursor->texture, &cursorBox, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(wlr_buffer* buffer, uint32_t fmt) {
|
||||
auto it = std::find_if(m_vRenderbuffers.begin(), m_vRenderbuffers.end(), [&](const auto& other) { return other->m_pWlrBuffer == buffer; });
|
||||
|
||||
if (it != m_vRenderbuffers.end())
|
||||
return it->get();
|
||||
|
||||
return m_vRenderbuffers.emplace_back(std::make_unique<CRenderbuffer>(buffer, fmt)).get();
|
||||
}
|
||||
|
||||
void CHyprRenderer::makeEGLCurrent() {
|
||||
if (!g_pCompositor)
|
||||
return;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void CHyprRenderer::unsetEGL() {
|
||||
eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, wlr_buffer* buffer, CFramebuffer* fb) {
|
||||
|
||||
makeEGLCurrent();
|
||||
|
||||
m_eRenderMode = mode;
|
||||
|
||||
g_pHyprOpenGL->m_RenderData.pMonitor = pMonitor; // has to be set cuz allocs
|
||||
|
||||
if (mode == RENDER_MODE_FULL_FAKE) {
|
||||
RASSERT(fb, "Cannot render FULL_FAKE without a provided fb!");
|
||||
fb->bind();
|
||||
g_pHyprOpenGL->begin(pMonitor, &damage, fb);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!buffer) {
|
||||
if (!wlr_output_configure_primary_swapchain(pMonitor->output, &pMonitor->output->pending, &pMonitor->output->swapchain))
|
||||
return false;
|
||||
|
||||
m_pCurrentWlrBuffer = wlr_swapchain_acquire(pMonitor->output->swapchain, &m_iLastBufferAge);
|
||||
if (!m_pCurrentWlrBuffer)
|
||||
return false;
|
||||
} else {
|
||||
m_pCurrentWlrBuffer = wlr_buffer_lock(buffer);
|
||||
}
|
||||
|
||||
try {
|
||||
m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentWlrBuffer, pMonitor->drmFormat);
|
||||
} catch (std::exception& e) {
|
||||
wlr_buffer_unlock(m_pCurrentWlrBuffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pCurrentRenderbuffer->bind();
|
||||
g_pHyprOpenGL->begin(pMonitor, &damage);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CHyprRenderer::endRender() {
|
||||
const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor;
|
||||
|
||||
if (m_eRenderMode != RENDER_MODE_TO_BUFFER_READ_ONLY)
|
||||
g_pHyprOpenGL->end();
|
||||
else {
|
||||
g_pHyprOpenGL->m_RenderData.pMonitor = nullptr;
|
||||
g_pHyprOpenGL->m_RenderData.mouseZoomFactor = 1.f;
|
||||
g_pHyprOpenGL->m_RenderData.mouseZoomUseMouse = true;
|
||||
}
|
||||
|
||||
if (m_eRenderMode == RENDER_MODE_FULL_FAKE)
|
||||
return;
|
||||
|
||||
if (isNvidia())
|
||||
glFinish();
|
||||
else
|
||||
glFlush();
|
||||
|
||||
if (m_eRenderMode == RENDER_MODE_NORMAL) {
|
||||
wlr_output_state_set_buffer(&PMONITOR->output->pending, m_pCurrentWlrBuffer);
|
||||
unsetEGL(); // flush the context
|
||||
}
|
||||
|
||||
wlr_buffer_unlock(m_pCurrentWlrBuffer);
|
||||
|
||||
m_pCurrentRenderbuffer->unbind();
|
||||
|
||||
m_pCurrentRenderbuffer = nullptr;
|
||||
m_pCurrentWlrBuffer = nullptr;
|
||||
m_iLastBufferAge = 0;
|
||||
}
|
||||
|
||||
void CHyprRenderer::onRenderbufferDestroy(CRenderbuffer* rb) {
|
||||
std::erase_if(m_vRenderbuffers, [&](const auto& rbo) { return rbo.get() == rb; });
|
||||
}
|
||||
|
||||
CRenderbuffer* CHyprRenderer::getCurrentRBO() {
|
||||
return m_pCurrentRenderbuffer;
|
||||
}
|
||||
|
||||
bool CHyprRenderer::isNvidia() {
|
||||
return m_bNvidia;
|
||||
}
|
@@ -6,6 +6,7 @@
|
||||
#include "../helpers/Workspace.hpp"
|
||||
#include "../Window.hpp"
|
||||
#include "OpenGL.hpp"
|
||||
#include "Renderbuffer.hpp"
|
||||
#include "../helpers/Timer.hpp"
|
||||
#include "../helpers/Region.hpp"
|
||||
|
||||
@@ -27,6 +28,14 @@ enum eRenderPassMode
|
||||
RENDER_PASS_POPUP
|
||||
};
|
||||
|
||||
enum eRenderMode
|
||||
{
|
||||
RENDER_MODE_NORMAL = 0,
|
||||
RENDER_MODE_FULL_FAKE = 1,
|
||||
RENDER_MODE_TO_BUFFER = 2,
|
||||
RENDER_MODE_TO_BUFFER_READ_ONLY = 3,
|
||||
};
|
||||
|
||||
class CToplevelExportProtocolManager;
|
||||
class CInputManager;
|
||||
struct SSessionLockSurface;
|
||||
@@ -58,15 +67,24 @@ class CHyprRenderer {
|
||||
void recheckSolitaryForMonitor(CMonitor* pMonitor);
|
||||
void setCursorSurface(wlr_surface* surf, int hotspotX, int hotspotY);
|
||||
void setCursorFromName(const std::string& name);
|
||||
void renderSoftwareCursors(CMonitor* pMonitor, const CRegion& damage, std::optional<Vector2D> overridePos = {});
|
||||
void onRenderbufferDestroy(CRenderbuffer* rb);
|
||||
CRenderbuffer* getCurrentRBO();
|
||||
bool isNvidia();
|
||||
void makeEGLCurrent();
|
||||
void unsetEGL();
|
||||
|
||||
bool m_bWindowRequestedCursorHide = false;
|
||||
bool m_bBlockSurfaceFeedback = false;
|
||||
bool m_bRenderingSnapshot = false;
|
||||
CWindow* m_pLastScanout = nullptr;
|
||||
CMonitor* m_pMostHzMonitor = nullptr;
|
||||
bool m_bDirectScanoutBlocked = false;
|
||||
bool m_bSoftwareCursorsLocked = false;
|
||||
bool m_bTearingEnvSatisfied = false;
|
||||
bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, wlr_buffer* buffer = nullptr, CFramebuffer* fb = nullptr);
|
||||
void endRender();
|
||||
|
||||
bool m_bWindowRequestedCursorHide = false;
|
||||
bool m_bBlockSurfaceFeedback = false;
|
||||
bool m_bRenderingSnapshot = false;
|
||||
CWindow* m_pLastScanout = nullptr;
|
||||
CMonitor* m_pMostHzMonitor = nullptr;
|
||||
bool m_bDirectScanoutBlocked = false;
|
||||
bool m_bSoftwareCursorsLocked = false;
|
||||
bool m_bTearingEnvSatisfied = false;
|
||||
|
||||
DAMAGETRACKINGMODES
|
||||
damageTrackingModeFromStr(const std::string&);
|
||||
@@ -89,19 +107,28 @@ class CHyprRenderer {
|
||||
} m_sLastCursorData;
|
||||
|
||||
private:
|
||||
void arrangeLayerArray(CMonitor*, const std::vector<std::unique_ptr<SLayerSurface>>&, bool, CBox*);
|
||||
void renderWorkspaceWindowsFullscreen(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special)
|
||||
void renderWorkspaceWindows(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special)
|
||||
void renderWindow(CWindow*, CMonitor*, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false);
|
||||
void renderLayer(SLayerSurface*, CMonitor*, timespec*);
|
||||
void renderSessionLockSurface(SSessionLockSurface*, CMonitor*, timespec*);
|
||||
void renderDragIcon(CMonitor*, timespec*);
|
||||
void renderIMEPopup(SIMEPopup*, CMonitor*, timespec*);
|
||||
void renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const CBox& geometry);
|
||||
void renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f);
|
||||
void arrangeLayerArray(CMonitor*, const std::vector<std::unique_ptr<SLayerSurface>>&, bool, CBox*);
|
||||
void renderWorkspaceWindowsFullscreen(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special)
|
||||
void renderWorkspaceWindows(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special)
|
||||
void renderWindow(CWindow*, CMonitor*, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false);
|
||||
void renderLayer(SLayerSurface*, CMonitor*, timespec*);
|
||||
void renderSessionLockSurface(SSessionLockSurface*, CMonitor*, timespec*);
|
||||
void renderDragIcon(CMonitor*, timespec*);
|
||||
void renderIMEPopup(SIMEPopup*, CMonitor*, timespec*);
|
||||
void renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const CBox& geometry);
|
||||
void renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f);
|
||||
|
||||
bool m_bHasARenderedCursor = true;
|
||||
bool m_bCursorHasSurface = false;
|
||||
bool m_bHasARenderedCursor = true;
|
||||
bool m_bCursorHasSurface = false;
|
||||
CRenderbuffer* m_pCurrentRenderbuffer = nullptr;
|
||||
wlr_buffer* m_pCurrentWlrBuffer = nullptr;
|
||||
eRenderMode m_eRenderMode = RENDER_MODE_NORMAL;
|
||||
int m_iLastBufferAge = 0;
|
||||
|
||||
bool m_bNvidia = false;
|
||||
|
||||
CRenderbuffer* getOrCreateRenderbuffer(wlr_buffer* buffer, uint32_t fmt);
|
||||
std::vector<std::unique_ptr<CRenderbuffer>> m_vRenderbuffers;
|
||||
|
||||
friend class CHyprOpenGLImpl;
|
||||
friend class CToplevelExportProtocolManager;
|
||||
|
@@ -26,6 +26,10 @@ void CHyprDropShadowDecoration::onPositioningReply(const SDecorationPositioningR
|
||||
updateWindow(m_pWindow);
|
||||
}
|
||||
|
||||
uint64_t CHyprDropShadowDecoration::getDecorationFlags() {
|
||||
return DECORATION_NON_SOLID;
|
||||
}
|
||||
|
||||
void CHyprDropShadowDecoration::damageEntire() {
|
||||
static auto* const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
|
||||
|
||||
@@ -88,6 +92,7 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D
|
||||
// scale the box in relation to the center of the box
|
||||
fullBox.scaleFromCenter(SHADOWSCALE).translate(*PSHADOWOFFSET);
|
||||
|
||||
m_vLastWindowPos += WORKSPACEOFFSET;
|
||||
m_seExtents = {{m_vLastWindowPos.x - fullBox.x - pMonitor->vecPosition.x + 2, m_vLastWindowPos.y - fullBox.y - pMonitor->vecPosition.y + 2},
|
||||
{fullBox.x + fullBox.width + pMonitor->vecPosition.x - m_vLastWindowPos.x - m_vLastWindowSize.x + 2,
|
||||
fullBox.y + fullBox.height + pMonitor->vecPosition.y - m_vLastWindowPos.y - m_vLastWindowSize.y + 2}};
|
||||
@@ -122,12 +127,17 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D
|
||||
if (windowBox.width < 1 || windowBox.height < 1)
|
||||
return; // prevent assert failed
|
||||
|
||||
CRegion saveDamage = g_pHyprOpenGL->m_RenderData.damage;
|
||||
|
||||
g_pHyprOpenGL->m_RenderData.damage = fullBox;
|
||||
g_pHyprOpenGL->m_RenderData.damage.subtract(windowBox.copy().expand(-ROUNDING * pMonitor->scale)).intersect(saveDamage);
|
||||
|
||||
alphaFB.bind();
|
||||
|
||||
// build the matte
|
||||
// 10-bit formats have dogshit alpha channels, so we have to use the matte to its fullest.
|
||||
// first, clear with black (fully transparent)
|
||||
g_pHyprOpenGL->clear(CColor(0, 0, 0, 1));
|
||||
// first, clear region of interest with black (fully transparent)
|
||||
g_pHyprOpenGL->renderRect(&fullBox, CColor(0, 0, 0, 1), 0);
|
||||
|
||||
// render white shadow with the alpha of the shadow color (otherwise we clear with alpha later and shit it to 2 bit)
|
||||
g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CColor(1, 1, 1, m_pWindow->m_cRealShadowColor.col().a), a);
|
||||
@@ -138,7 +148,7 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D
|
||||
alphaSwapFB.bind();
|
||||
|
||||
// alpha swap just has the shadow color. It will be the "texture" to render.
|
||||
g_pHyprOpenGL->clear(m_pWindow->m_cRealShadowColor.col().stripA());
|
||||
g_pHyprOpenGL->renderRect(&fullBox, m_pWindow->m_cRealShadowColor.col().stripA(), 0);
|
||||
|
||||
LASTFB->bind();
|
||||
|
||||
@@ -146,6 +156,8 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D
|
||||
g_pHyprOpenGL->setMonitorTransformEnabled(false);
|
||||
g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.m_cTex, &monbox, alphaFB);
|
||||
g_pHyprOpenGL->setMonitorTransformEnabled(true);
|
||||
|
||||
g_pHyprOpenGL->m_RenderData.damage = saveDamage;
|
||||
} else {
|
||||
g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a);
|
||||
}
|
||||
|
@@ -21,6 +21,8 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration {
|
||||
|
||||
virtual eDecorationLayer getDecorationLayer();
|
||||
|
||||
virtual uint64_t getDecorationFlags();
|
||||
|
||||
private:
|
||||
SWindowDecorationExtents m_seExtents;
|
||||
SWindowDecorationExtents m_seReportedExtents;
|
||||
|
@@ -6,6 +6,9 @@
|
||||
// shared things to conserve VRAM
|
||||
static CTexture m_tGradientActive;
|
||||
static CTexture m_tGradientInactive;
|
||||
static CTexture m_tGradientLockedActive;
|
||||
static CTexture m_tGradientLockedInactive;
|
||||
|
||||
constexpr int BAR_INDICATOR_HEIGHT = 3;
|
||||
constexpr int BAR_PADDING_OUTER_VERT = 2;
|
||||
constexpr int BAR_TEXT_PAD = 2;
|
||||
@@ -13,6 +16,8 @@ constexpr int BAR_HORIZONTAL_PADDING = 2;
|
||||
|
||||
CHyprGroupBarDecoration::CHyprGroupBarDecoration(CWindow* pWindow) : IHyprWindowDecoration(pWindow) {
|
||||
m_pWindow = pWindow;
|
||||
if (m_tGradientActive.m_iTexID == 0)
|
||||
refreshGroupBarGradients();
|
||||
}
|
||||
|
||||
CHyprGroupBarDecoration::~CHyprGroupBarDecoration() {}
|
||||
@@ -118,8 +123,9 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D&
|
||||
|
||||
// render title if necessary
|
||||
if (*PRENDERTITLES) {
|
||||
CBox rect = {ASSIGNEDBOX.x + xoff - pMonitor->vecPosition.x + offset.x, ASSIGNEDBOX.y - pMonitor->vecPosition.y + offset.y + BAR_PADDING_OUTER_VERT, m_fBarWidth,
|
||||
CBox rect = {ASSIGNEDBOX.x + xoff - pMonitor->vecPosition.x + offset.x, ASSIGNEDBOX.y - pMonitor->vecPosition.y + offset.y + BAR_PADDING_OUTER_VERT, m_fBarWidth,
|
||||
ASSIGNEDBOX.h - BAR_INDICATOR_HEIGHT - BAR_PADDING_OUTER_VERT * 2};
|
||||
rect.scale(pMonitor->scale);
|
||||
|
||||
CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[i]->m_szTitle);
|
||||
|
||||
@@ -129,15 +135,13 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D&
|
||||
Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale}))
|
||||
.get();
|
||||
|
||||
refreshGradients();
|
||||
const auto& GRADIENTTEX = (m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) :
|
||||
(GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive));
|
||||
|
||||
if (*PGRADIENTS) {
|
||||
CBox rect2 = rect;
|
||||
rect2.scale(pMonitor->scale);
|
||||
g_pHyprOpenGL->renderTexture((m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? m_tGradientActive : m_tGradientInactive), &rect2, 1.0);
|
||||
}
|
||||
if (*PGRADIENTS && GRADIENTTEX.m_iTexID != 0)
|
||||
g_pHyprOpenGL->renderTexture(GRADIENTTEX, &rect, 1.0);
|
||||
|
||||
rect.y = ASSIGNEDBOX.y + ASSIGNEDBOX.h / 2.0 - (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) / 2.0;
|
||||
rect.y += (ASSIGNEDBOX.h / 2.0 - (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) / 2.0) * pMonitor->scale;
|
||||
rect.height = (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale;
|
||||
|
||||
g_pHyprOpenGL->renderTexture(pTitleTex->tex, &rect, 1.f);
|
||||
@@ -234,6 +238,9 @@ CTitleTex::~CTitleTex() {
|
||||
|
||||
void renderGradientTo(CTexture& tex, const CColor& grad) {
|
||||
|
||||
if (!g_pCompositor->m_pLastMonitor)
|
||||
return;
|
||||
|
||||
const Vector2D& bufferSize = g_pCompositor->m_pLastMonitor->vecPixelSize;
|
||||
|
||||
const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bufferSize.x, bufferSize.y);
|
||||
@@ -275,21 +282,23 @@ void renderGradientTo(CTexture& tex, const CColor& grad) {
|
||||
cairo_surface_destroy(CAIROSURFACE);
|
||||
}
|
||||
|
||||
void CHyprGroupBarDecoration::refreshGradients() {
|
||||
if (m_tGradientActive.m_iTexID > 0)
|
||||
return;
|
||||
|
||||
void refreshGroupBarGradients() {
|
||||
static auto* const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.active")->data;
|
||||
static auto* const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.inactive")->data;
|
||||
static auto* const PGROUPCOLACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_active")->data;
|
||||
static auto* const PGROUPCOLINACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_inactive")->data;
|
||||
|
||||
const bool GROUPLOCKED = m_pWindow->getGroupHead()->m_sGroupData.locked;
|
||||
const auto* const PCOLACTIVE = GROUPLOCKED ? PGROUPCOLACTIVELOCKED : PGROUPCOLACTIVE;
|
||||
const auto* const PCOLINACTIVE = GROUPLOCKED ? PGROUPCOLINACTIVELOCKED : PGROUPCOLINACTIVE;
|
||||
if (m_tGradientActive.m_iTexID != 0) {
|
||||
m_tGradientActive.destroyTexture();
|
||||
m_tGradientInactive.destroyTexture();
|
||||
m_tGradientLockedActive.destroyTexture();
|
||||
m_tGradientLockedInactive.destroyTexture();
|
||||
}
|
||||
|
||||
renderGradientTo(m_tGradientActive, ((CGradientValueData*)PCOLACTIVE->get())->m_vColors[0]);
|
||||
renderGradientTo(m_tGradientInactive, ((CGradientValueData*)PCOLINACTIVE->get())->m_vColors[0]);
|
||||
renderGradientTo(m_tGradientActive, ((CGradientValueData*)PGROUPCOLACTIVE->get())->m_vColors[0]);
|
||||
renderGradientTo(m_tGradientInactive, ((CGradientValueData*)PGROUPCOLINACTIVE->get())->m_vColors[0]);
|
||||
renderGradientTo(m_tGradientLockedActive, ((CGradientValueData*)PGROUPCOLACTIVELOCKED->get())->m_vColors[0]);
|
||||
renderGradientTo(m_tGradientLockedInactive, ((CGradientValueData*)PGROUPCOLINACTIVELOCKED->get())->m_vColors[0]);
|
||||
}
|
||||
|
||||
bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D& pos) {
|
||||
@@ -346,6 +355,9 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(CWindow* pDraggedWindow, con
|
||||
pDraggedWindow->updateWindowDecos();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(pDraggedWindow);
|
||||
|
||||
if (!pDraggedWindow->getDecorationByType(DECORATION_GROUPBAR))
|
||||
pDraggedWindow->addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(pDraggedWindow));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -405,5 +417,13 @@ uint64_t CHyprGroupBarDecoration::getDecorationFlags() {
|
||||
|
||||
CBox CHyprGroupBarDecoration::assignedBoxGlobal() {
|
||||
CBox box = m_bAssignedBox;
|
||||
return box.translate(g_pDecorationPositioner->getEdgeDefinedPoint(DECORATION_EDGE_TOP, m_pWindow));
|
||||
}
|
||||
box.translate(g_pDecorationPositioner->getEdgeDefinedPoint(DECORATION_EDGE_TOP, m_pWindow));
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_pWindow->m_iWorkspaceID);
|
||||
|
||||
if (!PWORKSPACE)
|
||||
return box;
|
||||
|
||||
const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D();
|
||||
return box.translate(WORKSPACEOFFSET);
|
||||
}
|
||||
|
@@ -16,6 +16,8 @@ class CTitleTex {
|
||||
CWindow* pWindowOwner = nullptr;
|
||||
};
|
||||
|
||||
void refreshGroupBarGradients();
|
||||
|
||||
class CHyprGroupBarDecoration : public IHyprWindowDecoration {
|
||||
public:
|
||||
CHyprGroupBarDecoration(CWindow*);
|
||||
@@ -57,8 +59,6 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration {
|
||||
CTitleTex* textureFromTitle(const std::string&);
|
||||
void invalidateTextures();
|
||||
|
||||
void refreshGradients();
|
||||
|
||||
CBox assignedBoxGlobal();
|
||||
|
||||
struct STitleTexs {
|
||||
|
@@ -6,6 +6,11 @@ CDecorationPositioner::CDecorationPositioner() {
|
||||
auto* const PWINDOW = std::any_cast<CWindow*>(data);
|
||||
this->onWindowUnmap(PWINDOW);
|
||||
});
|
||||
|
||||
g_pHookSystem->hookDynamic("openWindow", [this](void* call, SCallbackInfo& info, std::any data) {
|
||||
auto* const PWINDOW = std::any_cast<CWindow*>(data);
|
||||
this->onWindowMap(PWINDOW);
|
||||
});
|
||||
}
|
||||
|
||||
Vector2D CDecorationPositioner::getEdgeDefinedPoint(uint32_t edges, CWindow* pWindow) {
|
||||
@@ -52,7 +57,12 @@ Vector2D CDecorationPositioner::getEdgeDefinedPoint(uint32_t edges, CWindow* pWi
|
||||
|
||||
void CDecorationPositioner::uncacheDecoration(IHyprWindowDecoration* deco) {
|
||||
std::erase_if(m_vWindowPositioningDatas, [&](const auto& data) { return data->pDecoration == deco; });
|
||||
m_mWindowDatas[deco->m_pWindow].needsRecalc = true;
|
||||
|
||||
const auto WIT = std::find_if(m_mWindowDatas.begin(), m_mWindowDatas.end(), [&](const auto& other) { return other.first == deco->m_pWindow; });
|
||||
if (WIT == m_mWindowDatas.end())
|
||||
return;
|
||||
|
||||
WIT->second.needsRecalc = true;
|
||||
}
|
||||
|
||||
void CDecorationPositioner::repositionDeco(IHyprWindowDecoration* deco) {
|
||||
@@ -73,11 +83,39 @@ CDecorationPositioner::SWindowPositioningData* CDecorationPositioner::getDataFor
|
||||
return DATA;
|
||||
}
|
||||
|
||||
void CDecorationPositioner::onWindowUpdate(CWindow* pWindow) {
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
void CDecorationPositioner::sanitizeDatas() {
|
||||
std::erase_if(m_mWindowDatas, [](const auto& other) { return !g_pCompositor->windowExists(other.first); });
|
||||
std::erase_if(m_vWindowPositioningDatas, [](const auto& other) {
|
||||
if (!g_pCompositor->windowExists(other->pWindow))
|
||||
return true;
|
||||
if (std::find_if(other->pWindow->m_dWindowDecorations.begin(), other->pWindow->m_dWindowDecorations.end(),
|
||||
[&](const auto& el) { return el.get() == other->pDecoration; }) == other->pWindow->m_dWindowDecorations.end())
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
void CDecorationPositioner::forceRecalcFor(CWindow* pWindow) {
|
||||
const auto WIT = std::find_if(m_mWindowDatas.begin(), m_mWindowDatas.end(), [&](const auto& other) { return other.first == pWindow; });
|
||||
if (WIT == m_mWindowDatas.end())
|
||||
return;
|
||||
|
||||
auto* const WINDOWDATA = &m_mWindowDatas[pWindow];
|
||||
const auto WINDOWDATA = &WIT->second;
|
||||
|
||||
WINDOWDATA->needsRecalc = true;
|
||||
}
|
||||
|
||||
void CDecorationPositioner::onWindowUpdate(CWindow* pWindow) {
|
||||
if (!g_pCompositor->windowExists(pWindow) || !pWindow->m_bIsMapped)
|
||||
return;
|
||||
|
||||
const auto WIT = std::find_if(m_mWindowDatas.begin(), m_mWindowDatas.end(), [&](const auto& other) { return other.first == pWindow; });
|
||||
if (WIT == m_mWindowDatas.end())
|
||||
return;
|
||||
|
||||
const auto WINDOWDATA = &WIT->second;
|
||||
|
||||
sanitizeDatas();
|
||||
|
||||
//
|
||||
std::vector<CDecorationPositioner::SWindowPositioningData*> datas;
|
||||
@@ -140,16 +178,20 @@ void CDecorationPositioner::onWindowUpdate(CWindow* pWindow) {
|
||||
const bool LEFT = wd->positioningInfo.edges & DECORATION_EDGE_LEFT;
|
||||
const bool RIGHT = wd->positioningInfo.edges & DECORATION_EDGE_RIGHT;
|
||||
const int EDGESNO = TOP + BOTTOM + LEFT + RIGHT;
|
||||
const bool SOLID = !(wd->pDecoration->getDecorationFlags() & DECORATION_NON_SOLID);
|
||||
|
||||
if (wd->positioningInfo.policy == DECORATION_POSITION_ABSOLUTE) {
|
||||
if (LEFT)
|
||||
stickyOffsetXL += wd->positioningInfo.desiredExtents.topLeft.x;
|
||||
if (RIGHT)
|
||||
stickyOffsetXR += wd->positioningInfo.desiredExtents.bottomRight.x;
|
||||
if (TOP)
|
||||
stickyOffsetYT += wd->positioningInfo.desiredExtents.topLeft.y;
|
||||
if (BOTTOM)
|
||||
stickyOffsetYB += wd->positioningInfo.desiredExtents.bottomRight.y;
|
||||
|
||||
if (SOLID) {
|
||||
if (LEFT)
|
||||
stickyOffsetXL += wd->positioningInfo.desiredExtents.topLeft.x;
|
||||
if (RIGHT)
|
||||
stickyOffsetXR += wd->positioningInfo.desiredExtents.bottomRight.x;
|
||||
if (TOP)
|
||||
stickyOffsetYT += wd->positioningInfo.desiredExtents.topLeft.y;
|
||||
if (BOTTOM)
|
||||
stickyOffsetYB += wd->positioningInfo.desiredExtents.bottomRight.y;
|
||||
}
|
||||
|
||||
wd->lastReply = {};
|
||||
wd->pDecoration->onPositioningReply({});
|
||||
@@ -182,23 +224,27 @@ void CDecorationPositioner::onWindowUpdate(CWindow* pWindow) {
|
||||
pos.x -= desiredSize;
|
||||
size = {desiredSize, wb.size().y};
|
||||
|
||||
stickyOffsetXL += desiredSize;
|
||||
if (SOLID)
|
||||
stickyOffsetXL += desiredSize;
|
||||
} else if (RIGHT) {
|
||||
pos = wb.pos() + Vector2D{wb.size().x, 0} - EDGEPOINT + Vector2D{stickyOffsetXR, 0};
|
||||
size = {desiredSize, wb.size().y};
|
||||
|
||||
stickyOffsetXR += desiredSize;
|
||||
if (SOLID)
|
||||
stickyOffsetXR += desiredSize;
|
||||
} else if (TOP) {
|
||||
pos = wb.pos() - EDGEPOINT - Vector2D{0, stickyOffsetYT};
|
||||
pos.y -= desiredSize;
|
||||
size = {wb.size().x, desiredSize};
|
||||
|
||||
stickyOffsetYT += desiredSize;
|
||||
if (SOLID)
|
||||
stickyOffsetYT += desiredSize;
|
||||
} else {
|
||||
pos = wb.pos() + Vector2D{0, wb.size().y} - EDGEPOINT - Vector2D{0, stickyOffsetYB};
|
||||
size = {wb.size().x, desiredSize};
|
||||
|
||||
stickyOffsetYB += desiredSize;
|
||||
if (SOLID)
|
||||
stickyOffsetYB += desiredSize;
|
||||
}
|
||||
|
||||
wd->lastReply = {{pos, size}, EPHEMERAL};
|
||||
@@ -221,8 +267,15 @@ void CDecorationPositioner::onWindowUnmap(CWindow* pWindow) {
|
||||
m_mWindowDatas.erase(pWindow);
|
||||
}
|
||||
|
||||
void CDecorationPositioner::onWindowMap(CWindow* pWindow) {
|
||||
m_mWindowDatas[pWindow] = {};
|
||||
}
|
||||
|
||||
SWindowDecorationExtents CDecorationPositioner::getWindowDecorationReserved(CWindow* pWindow) {
|
||||
return m_mWindowDatas[pWindow].reserved;
|
||||
try {
|
||||
const auto E = m_mWindowDatas.at(pWindow);
|
||||
return E.reserved;
|
||||
} catch (std::out_of_range& e) { return {}; }
|
||||
}
|
||||
|
||||
SWindowDecorationExtents CDecorationPositioner::getWindowDecorationExtents(CWindow* pWindow, bool inputOnly) {
|
||||
@@ -232,6 +285,9 @@ SWindowDecorationExtents CDecorationPositioner::getWindowDecorationExtents(CWind
|
||||
if (data->pWindow != pWindow)
|
||||
continue;
|
||||
|
||||
if (!data->pWindow || !data->pDecoration)
|
||||
continue;
|
||||
|
||||
if (!(data->pDecoration->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT) && inputOnly)
|
||||
continue;
|
||||
|
||||
|
@@ -11,7 +11,7 @@ class IHyprWindowDecoration;
|
||||
|
||||
enum eDecorationPositioningPolicy
|
||||
{
|
||||
DECORATION_POSITION_ABSOLUTE = 0, /* Decoration does not interfere with anything else */
|
||||
DECORATION_POSITION_ABSOLUTE = 0, /* Decoration wants absolute positioning */
|
||||
DECORATION_POSITION_STICKY, /* Decoration is stuck to some edge of a window */
|
||||
};
|
||||
|
||||
@@ -71,6 +71,7 @@ class CDecorationPositioner {
|
||||
CBox getBoxWithIncludedDecos(CWindow* pWindow);
|
||||
void repositionDeco(IHyprWindowDecoration* deco);
|
||||
CBox getWindowDecorationBox(IHyprWindowDecoration* deco);
|
||||
void forceRecalcFor(CWindow* pWindow);
|
||||
|
||||
private:
|
||||
struct SWindowPositioningData {
|
||||
@@ -93,6 +94,8 @@ class CDecorationPositioner {
|
||||
|
||||
SWindowPositioningData* getDataFor(IHyprWindowDecoration* pDecoration, CWindow* pWindow);
|
||||
void onWindowUnmap(CWindow* pWindow);
|
||||
void onWindowMap(CWindow* pWindow);
|
||||
void sanitizeDatas();
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CDecorationPositioner> g_pDecorationPositioner;
|
@@ -24,6 +24,7 @@ enum eDecorationFlags
|
||||
{
|
||||
DECORATION_ALLOWS_MOUSE_INPUT = 1 << 0, /* this decoration accepts mouse input */
|
||||
DECORATION_PART_OF_MAIN_WINDOW = 1 << 1, /* this decoration is a *seamless* part of the main window, so stuff like shadows will include it */
|
||||
DECORATION_NON_SOLID = 1 << 2, /* this decoration is not solid. Other decorations should draw on top of it. Example: shadow */
|
||||
};
|
||||
|
||||
class CWindow;
|
||||
|
@@ -234,11 +234,11 @@ vec3 rgb2hsl(vec3 col) {
|
||||
sat = delta / (mul * 2.0);
|
||||
}
|
||||
|
||||
vec3 masks = vec3((maxc == red && maxc != green) ? 1.0 : 0.0, (maxc == green && maxc != blue) ? 1.0 : 0.0, (maxc == blue && maxc != red) ? 1.0 : 0.0);
|
||||
|
||||
vec3 adds = vec3(((green - blue) / delta), 2.0 + ((blue - red) / delta), 4.0 + ((red - green) / delta));
|
||||
|
||||
if (delta > 0.0) {
|
||||
vec3 maxcVec = vec3(maxc);
|
||||
vec3 masks = vec3(equal(maxcVec, col)) * vec3(notEqual(maxcVec, vec3(green, blue, red)));
|
||||
vec3 adds = vec3(0.0, 2.0, 4.0) + vec3(green - blue, blue - red, red - green) / delta;
|
||||
|
||||
hue += dot(adds, masks);
|
||||
hue /= 6.0;
|
||||
|
||||
@@ -248,6 +248,7 @@ vec3 rgb2hsl(vec3 col) {
|
||||
|
||||
return vec3(hue, sat, lum);
|
||||
}
|
||||
|
||||
vec3 hsl2rgb(vec3 col) {
|
||||
const float onethird = 1.0 / 3.0;
|
||||
const float twothird = 2.0 / 3.0;
|
||||
|
@@ -38,8 +38,8 @@ index 29b103a..0b6e5a4 100644
|
||||
# necessary for bugfix releases. Increasing soversion is required because
|
||||
# wlroots never guarantees ABI stability -- only API stability is guaranteed
|
||||
# between minor releases.
|
||||
-soversion = 12
|
||||
+soversion = 12032
|
||||
-soversion = 13
|
||||
+soversion = 13032
|
||||
|
||||
little_endian = target_machine.endian() == 'little'
|
||||
big_endian = target_machine.endian() == 'big'
|
||||
|
Submodule subprojects/wlroots updated: 5de9e1a99d...5d639394f3
@@ -1,7 +1,7 @@
|
||||
[wrap-git]
|
||||
directory = wlroots
|
||||
url = https://gitlab.freedesktop.org/wlroots/wlroots.git
|
||||
revision = 5de9e1a99d6642c2d09d589aa37ff0a8945dcee1
|
||||
revision = 5d639394f3e83b01596dcd166a44a9a1a2583350
|
||||
depth = 1
|
||||
|
||||
diff_files = wlroots-meson-build.patch
|
||||
|
Reference in New Issue
Block a user