mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-15 12:03:48 -07:00
Compare commits
227 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
eab2799842 | ||
|
6eb2abcb20 | ||
|
ae46fbafe5 | ||
|
52cf122a0a | ||
|
844da8db56 | ||
|
db82fc5b09 | ||
|
8180ca65a5 | ||
|
bea828ea45 | ||
|
c5d1faf72d | ||
|
cc04b52ce1 | ||
|
9b5e2e71e0 | ||
|
9be6fbf5ea | ||
|
7345b1a1ea | ||
|
e44d6de555 | ||
|
427153e86a | ||
|
1e6e9b66a5 | ||
|
92cb44ddb2 | ||
|
b8a615ffb8 | ||
|
8dd02eb5f3 | ||
|
14195835ef | ||
|
11432f69b9 | ||
|
da6fa9cbd2 | ||
|
c619e6976f | ||
|
751d2851cc | ||
|
a0fcda301d | ||
|
47654a84c2 | ||
|
29e0a7112e | ||
|
a1b7a5a53d | ||
|
ecf98069f6 | ||
|
0476e1b498 | ||
|
a122271f09 | ||
|
600a128f83 | ||
|
55825c301e | ||
|
d8b7ded18c | ||
|
c4e1a9b13b | ||
|
9404972732 | ||
|
3b786419d8 | ||
|
92e535025e | ||
|
d3e5796ee1 | ||
|
56dec1c6a2 | ||
|
931927de29 | ||
|
74cf2281dd | ||
|
2b07d54bc7 | ||
|
66a3719b86 | ||
|
64a084477e | ||
|
7a09d24065 | ||
|
a3e20d2d5f | ||
|
32b3d2b456 | ||
|
447c173cad | ||
|
55b4f84fea | ||
|
73e78f05ad | ||
|
54e51b7acf | ||
|
200cccdd3b | ||
|
15b25d5850 | ||
|
21ba8b363e | ||
|
9d2a5fb417 | ||
|
ed3d5053b2 | ||
|
93a2ac9de4 | ||
|
49fdffacea | ||
|
0f6e530798 | ||
|
88b47dfa83 | ||
|
ba9e7814b0 | ||
|
f10996b575 | ||
|
ef90d1eaaf | ||
|
062f749450 | ||
|
a4db48b46b | ||
|
c44e255194 | ||
|
21e9313c10 | ||
|
7b32b4214d | ||
|
6914103289 | ||
|
ab5497a0c9 | ||
|
f48b3774a2 | ||
|
1c9d6b94d1 | ||
|
4b592d0819 | ||
|
a1924ae435 | ||
|
cb6cfde6e8 | ||
|
8e91c038db | ||
|
86318ce04f | ||
|
59d6a12a7e | ||
|
935c90915a | ||
|
b95c0c318e | ||
|
9abfa9efc6 | ||
|
7a5234a0cc | ||
|
af9440152e | ||
|
7f4b0aaadc | ||
|
4a4e13f8ac | ||
|
1d47e2c408 | ||
|
47256a6ed8 | ||
|
732b058489 | ||
|
92cf1c2337 | ||
|
07714dd5bd | ||
|
5cc33b4e8c | ||
|
b0b88a63b6 | ||
|
5b0dc779ed | ||
|
8991be671f | ||
|
6650e4ba85 | ||
|
a1b138a625 | ||
|
df00727310 | ||
|
03771d3aa9 | ||
|
50a80efad5 | ||
|
14a3c939ce | ||
|
aeb8c8fc70 | ||
|
616ff343b7 | ||
|
2f6729f557 | ||
|
015664eb4c | ||
|
98059b52d7 | ||
|
b135bd6cd4 | ||
|
59f27e7f57 | ||
|
edb26e0306 | ||
|
d0367d8560 | ||
|
95db9108e5 | ||
|
a61eb7694d | ||
|
c6233a790f | ||
|
92311d260a | ||
|
af72404259 | ||
|
4a79718fe8 | ||
|
7f35f33b4c | ||
|
bab2f6a664 | ||
|
bb9d0aed5b | ||
|
386708563c | ||
|
ba5f1d8783 | ||
|
d994e6aea6 | ||
|
6e15590e98 | ||
|
d70cc88dab | ||
|
a0b675ec9e | ||
|
784f8a88fb | ||
|
20e7ccd480 | ||
|
210be10c92 | ||
|
421f5fb221 | ||
|
93676f91a0 | ||
|
54e1c2ccbd | ||
|
5b8cfdf2ef | ||
|
8af3e7beeb | ||
|
1f582457cf | ||
|
442209942f | ||
|
43b39e0bc6 | ||
|
261c594458 | ||
|
962a0de01a | ||
|
21b5cf402a | ||
|
d4e4931008 | ||
|
d5a572bd39 | ||
|
424c9a7e70 | ||
|
3a61350286 | ||
|
e4bcd2e2da | ||
|
06cc42441c | ||
|
5dc7161b1d | ||
|
0cf3d5b39a | ||
|
34455844e9 | ||
|
d83357f497 | ||
|
a0038fa161 | ||
|
914851b91a | ||
|
3219c84433 | ||
|
1a0909aa20 | ||
|
bf94df7b00 | ||
|
d537815d43 | ||
|
ac1bd47653 | ||
|
8abb6e1cee | ||
|
df0c8e0f7a | ||
|
7f8e0a1318 | ||
|
499df49f7b | ||
|
728a8bb48e | ||
|
7d7565e7ec | ||
|
38e242953d | ||
|
61d3d4dee7 | ||
|
1afb00a01b | ||
|
cb7dd1ac6e | ||
|
4b3efc73c5 | ||
|
24c04a8b7c | ||
|
3d1a167960 | ||
|
1b99a69dc1 | ||
|
8e0eafc502 | ||
|
e689b1ba11 | ||
|
322c5cc4b9 | ||
|
230356012b | ||
|
4531717f3e | ||
|
f8c18ff797 | ||
|
f803be3d31 | ||
|
2901bb0d2f | ||
|
d61e4f9ad7 | ||
|
b784931e67 | ||
|
fcab2a4358 | ||
|
b814ba98a7 | ||
|
50fecf084d | ||
|
5ffb1032e1 | ||
|
fc1d7acd9a | ||
|
778bdf730f | ||
|
763bb2d3bc | ||
|
9ec656a37d | ||
|
161fee1d82 | ||
|
a2a29a60e5 | ||
|
e2b72b2975 | ||
|
772c7d1d3c | ||
|
6a4643842d | ||
|
a05076a7ee | ||
|
b8f8912db2 | ||
|
86e8ed038f | ||
|
c298439433 | ||
|
495d4f2d11 | ||
|
7b002d609b | ||
|
4daa515700 | ||
|
e07e64458e | ||
|
a44ab7748f | ||
|
ab11bd2085 | ||
|
27cd7ef0c9 | ||
|
9cc614d096 | ||
|
3f09b14381 | ||
|
453128ee0e | ||
|
88b63a00b6 | ||
|
1e513e25d5 | ||
|
d48c11cc3f | ||
|
08595f839b | ||
|
eab5967ef4 | ||
|
280f385cf8 | ||
|
1f4eab176e | ||
|
6d7dc70f66 | ||
|
ffacd2efd1 | ||
|
3b657257ec | ||
|
6bdc45e9ce | ||
|
46d66f4bcc | ||
|
352ceb1117 | ||
|
2c4a06eb54 | ||
|
3b445ec849 | ||
|
8252957392 | ||
|
8637bfb1b7 | ||
|
de95089552 | ||
|
9c00381dfc | ||
|
fb80cbe415 |
4
.github/workflows/ci.yaml
vendored
4
.github/workflows/ci.yaml
vendored
@@ -39,7 +39,7 @@ jobs:
|
||||
mkdir hyprland/assets
|
||||
cp ./LICENSE hyprland/
|
||||
cp build/Hyprland hyprland/
|
||||
cp hyprctl/hyprctl hyprland/
|
||||
cp build/hyprctl/hyprctl hyprland/
|
||||
cp subprojects/wlroots/build/libwlroots.so.12032 hyprland/
|
||||
cp build/Hyprland hyprland/
|
||||
cp -r example/ hyprland/
|
||||
@@ -105,4 +105,4 @@ jobs:
|
||||
- name: Configure
|
||||
run: mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DNO_XWAYLAND:STRING=true -H./ -B./build -G Ninja
|
||||
- name: Compile
|
||||
run: make config && make release
|
||||
run: make release
|
||||
|
7
.github/workflows/release.yaml
vendored
7
.github/workflows/release.yaml
vendored
@@ -15,10 +15,15 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Generate version
|
||||
id: genversion
|
||||
run: |
|
||||
bash -c scripts/generateVersion.sh
|
||||
mv scripts/generateVersion.sh scripts/generateVersion.sh.bak
|
||||
|
||||
- name: Create tarball with submodules
|
||||
id: tar
|
||||
run: |
|
||||
sed -i "1s/^/#define GIT_COMMIT_HASH \"$(git rev-parse HEAD)\"\n#define GIT_TAG \"$(git describe --tags)\"\n/" ./src/macros.hpp
|
||||
mkdir hyprland-source; mv ./* ./hyprland-source || tar -czv --owner=0 --group=0 --no-same-owner --no-same-permissions -f source.tar.gz *
|
||||
|
||||
- id: whatrelease
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -29,3 +29,5 @@ gmon.out
|
||||
*.tar.gz
|
||||
|
||||
PKGBUILD
|
||||
|
||||
src/version.h
|
||||
|
108
CMakeLists.txt
Normal file → Executable file
108
CMakeLists.txt
Normal file → Executable file
@@ -21,37 +21,51 @@ message(STATUS "Gathering git info")
|
||||
# Get git info
|
||||
# hash and branch
|
||||
execute_process(
|
||||
COMMAND git rev-parse --abbrev-ref HEAD
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_BRANCH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
execute_process(
|
||||
COMMAND git rev-parse HEAD
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_COMMIT_HASH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
execute_process(
|
||||
COMMAND sh -c "git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1 | sed -e 's/#//g' -e 's/\"//g'"
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_COMMIT_MESSAGE
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
execute_process(
|
||||
COMMAND sh -c "git diff-index --quiet HEAD -- || echo \"dirty\""
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_DIRTY
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
execute_process(
|
||||
COMMAND sh -c "git describe --tags"
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_TAG
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
COMMAND ./scripts/generateVersion.sh
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
#
|
||||
#
|
||||
|
||||
# udis
|
||||
add_subdirectory("subprojects/udis86")
|
||||
|
||||
# wlroots
|
||||
message(STATUS "Setting up wlroots")
|
||||
|
||||
include(ExternalProject)
|
||||
|
||||
if(CMAKE_BUILD_TYPE)
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER)
|
||||
if(BUILDTYPE_LOWER STREQUAL "release")
|
||||
# Pass.
|
||||
elseif(BUILDTYPE_LOWER STREQUAL "debug")
|
||||
# Pass.
|
||||
elseif(BUILDTYPE_LOWER STREQUAL "relwithdebinfo")
|
||||
set(BUILDTYPE_LOWER "debugoptimized")
|
||||
elseif(BUILDTYPE_LOWER STREQUAL "minsizerel")
|
||||
set(BUILDTYPE_LOWER "minsize")
|
||||
elseif(BUILDTYPE_LOWER STREQUAL "none")
|
||||
set(BUILDTYPE_LOWER "plain")
|
||||
else()
|
||||
set(BUILDTYPE_LOWER "release")
|
||||
endif()
|
||||
else()
|
||||
set(BUILDTYPE_LOWER "release")
|
||||
endif()
|
||||
|
||||
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
|
||||
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
|
||||
INSTALL_COMMAND echo "wlroots: install not needed"
|
||||
)
|
||||
|
||||
find_program(WaylandScanner NAMES wayland-scanner)
|
||||
message(STATUS "Found WaylandScanner at ${WaylandScanner}")
|
||||
execute_process(
|
||||
@@ -93,6 +107,7 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wa
|
||||
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
|
||||
|
||||
add_executable(Hyprland ${SRCFILES})
|
||||
add_dependencies(Hyprland wlroots)
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
message(STATUS "Setting debug flags")
|
||||
@@ -101,7 +116,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
message(STATUS "Enabling ASan")
|
||||
|
||||
target_link_libraries(Hyprland asan)
|
||||
add_compile_options(-fsanitize=address)
|
||||
target_compile_options(Hyprland PUBLIC -fsanitize=address)
|
||||
endif()
|
||||
|
||||
if(USE_TRACY)
|
||||
@@ -123,6 +138,12 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
add_link_options(-pg -no-pie -fno-builtin)
|
||||
endif()
|
||||
|
||||
check_include_file("execinfo.h" EXECINFOH)
|
||||
if(EXECINFOH)
|
||||
message(STATUS "Configuration supports execinfo")
|
||||
add_compile_definitions(HAS_EXECINFO)
|
||||
endif()
|
||||
|
||||
include(CheckLibraryExists)
|
||||
check_library_exists(execinfo backtrace "" HAVE_LIBEXECINFO)
|
||||
if(HAVE_LIBEXECINFO)
|
||||
@@ -147,24 +168,21 @@ if(NO_SYSTEMD)
|
||||
message(STATUS "SYSTEMD support is disabled...")
|
||||
else()
|
||||
message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined) checking deps...")
|
||||
pkg_check_modules(LIBSYSTEMD libsystemd)
|
||||
check_include_file("systemd/sd-daemon.h" SYSTEMDH)
|
||||
if(LIBSYSTEMD_FOUND AND SYSTEMDH)
|
||||
add_compile_definitions(USES_SYSTEMD)
|
||||
target_link_libraries(Hyprland "${LIBSYSTEMD_LIBRARIES}")
|
||||
if(SYSTEMDH)
|
||||
pkg_check_modules(LIBSYSTEMD libsystemd)
|
||||
if (LIBSYSTEMD_FOUND)
|
||||
add_compile_definitions(USES_SYSTEMD)
|
||||
target_link_libraries(Hyprland "${LIBSYSTEMD_LIBRARIES}")
|
||||
message(STATUS "Systemd found")
|
||||
else()
|
||||
message(WARNING "Systemd support requested but systemd libraries were not found")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Systemd support requested but libsystemd or systemd headers were not found")
|
||||
message(WARNING "Systemd support requested but systemd headers were not found")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_compile_definitions(Hyprland
|
||||
PRIVATE
|
||||
"GIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\""
|
||||
"GIT_BRANCH=\"${GIT_BRANCH}\""
|
||||
"GIT_COMMIT_MESSAGE=\"${GIT_COMMIT_MESSAGE}\""
|
||||
"GIT_DIRTY=\"${GIT_DIRTY}\""
|
||||
"GIT_TAG=\"${GIT_TAG}\"")
|
||||
|
||||
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
|
||||
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
|
||||
include(CPack)
|
||||
@@ -202,7 +220,7 @@ target_link_libraries(Hyprland
|
||||
OpenGL::EGL
|
||||
OpenGL::GL
|
||||
Threads::Threads
|
||||
${CMAKE_SOURCE_DIR}/subprojects/udis86/build/libudis86/liblibudis86.a
|
||||
libudis86
|
||||
)
|
||||
|
||||
protocol("protocols/idle.xml" "idle" true)
|
||||
@@ -218,5 +236,9 @@ protocol("stable/xdg-shell/xdg-shell.xml" "xdg-shell" false)
|
||||
protocol("unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml" "linux-dmabuf-unstable-v1" false)
|
||||
protocol("unstable/xdg-output/xdg-output-unstable-v1.xml" "xdg-output-unstable-v1" false)
|
||||
protocol("staging/fractional-scale/fractional-scale-v1.xml" "fractional-scale-v1" false)
|
||||
protocol("staging/tearing-control/tearing-control-v1.xml" "tearing-control-v1" false)
|
||||
protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false)
|
||||
protocol("staging/cursor-shape/cursor-shape-v1.xml" "cursor-shape-v1" false)
|
||||
|
||||
# hyprctl
|
||||
add_subdirectory(hyprctl)
|
||||
|
80
Makefile
80
Makefile
@@ -3,69 +3,56 @@ PREFIX = /usr/local
|
||||
legacyrenderer:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
chmod -R 777 ./build
|
||||
|
||||
legacyrendererdebug:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
chmod -R 777 ./build
|
||||
|
||||
release:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
chmod -R 777 ./build
|
||||
|
||||
debug:
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -S . -B ./build -G Ninja
|
||||
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
chmod -R 777 ./build
|
||||
|
||||
clear:
|
||||
rm -rf build
|
||||
rm -f ./protocols/*-protocol.h ./protocols/*-protocol.c
|
||||
rm -f ./hyprctl/hyprctl
|
||||
rm -rf ./subprojects/wlroots/build
|
||||
|
||||
all:
|
||||
@if [[ "$EUID" = 0 ]]; then echo -en "Avoid running $(MAKE) all as sudo.\n"; fi
|
||||
$(MAKE) clear
|
||||
$(MAKE) fixwlr
|
||||
cd ./subprojects/wlroots && meson setup build/ --buildtype=release && ninja -C build/ && mkdir -p ${PREFIX}/lib/ && cp ./build/libwlroots.so.12032 ${PREFIX}/lib/ || echo "Could not install libwlroots to ${PREFIX}/lib/libwlroots.so.12032"
|
||||
cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B./build -G Ninja && cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
$(MAKE) release
|
||||
$(MAKE) -C hyprctl all
|
||||
|
||||
install:
|
||||
$(MAKE) clear
|
||||
$(MAKE) fixwlr
|
||||
cd ./subprojects/wlroots && meson setup build/ --buildtype=release && ninja -C build/ && mkdir -p ${PREFIX}/lib/ && cp ./build/libwlroots.so.12032 ${PREFIX}/lib/ || echo "Could not install libwlroots to ${PREFIX}/lib/libwlroots.so.12032"
|
||||
cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B./build -G Ninja && cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` && cd ../..
|
||||
$(MAKE) release
|
||||
$(MAKE) -C hyprctl all
|
||||
@if [ ! -f ./build/Hyprland ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi
|
||||
@echo -en "!NOTE: Please note make install does not compile Hyprland and only installs the already built files."
|
||||
|
||||
mkdir -p ${PREFIX}/share/wayland-sessions
|
||||
mkdir -p ${PREFIX}/bin
|
||||
cp -f ./build/Hyprland ${PREFIX}/bin
|
||||
cp -f ./hyprctl/hyprctl ${PREFIX}/bin
|
||||
cp -f ./build/hyprctl/hyprctl ${PREFIX}/bin
|
||||
chmod 755 ${PREFIX}/bin/Hyprland
|
||||
chmod 755 ${PREFIX}/bin/hyprctl
|
||||
if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi
|
||||
mkdir -p ${PREFIX}/share/hyprland
|
||||
cp ./assets/wall_* ${PREFIX}/share/hyprland
|
||||
mkdir -p ${PREFIX}/share/xdg-desktop-portal
|
||||
cp ./assets/hyprland-portals.conf ${PREFIX}/share/xdg-desktop-portal
|
||||
|
||||
mkdir -p ${PREFIX}/share/man/man1
|
||||
install -m644 ./docs/*.1 ${PREFIX}/share/man/man1
|
||||
|
||||
mkdir -p ${PREFIX}/include/hyprland
|
||||
mkdir -p ${PREFIX}/include/hyprland/protocols
|
||||
mkdir -p ${PREFIX}/include/hyprland/wlroots
|
||||
mkdir -p ${PREFIX}/share/pkgconfig
|
||||
mkdir -p ${PREFIX}/share/xdg-desktop-portal
|
||||
|
||||
find src -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland
|
||||
cd subprojects/wlroots/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlroots && cd ../../..
|
||||
cd subprojects/wlroots/build/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlroots && cd ../../../..
|
||||
cp ./protocols/*-protocol.h ${PREFIX}/include/hyprland/protocols
|
||||
cp ./build/hyprland.pc ${PREFIX}/share/pkgconfig
|
||||
cp ./assets/hyprland-portals.conf ${PREFIX}/share/xdg-desktop-portal/
|
||||
if [ -d /usr/share/pkgconfig ]; then cp ./build/hyprland.pc /usr/share/pkgconfig 2>/dev/null || true; fi
|
||||
mkdir -p ${PREFIX}/lib/
|
||||
cp ./subprojects/wlroots/build/libwlroots.so.12032 ${PREFIX}/lib/
|
||||
|
||||
cleaninstall:
|
||||
echo -en "$(MAKE) cleaninstall has been DEPRECATED, you should avoid using it in the future.\nRunning $(MAKE) install instead...\n"
|
||||
$(MAKE) install
|
||||
$(MAKE) installheaders
|
||||
|
||||
uninstall:
|
||||
rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop
|
||||
@@ -76,30 +63,12 @@ uninstall:
|
||||
rm -f ${PREFIX}/share/man/man1/Hyprland.1
|
||||
rm -f ${PREFIX}/share/man/man1/hyprctl.1
|
||||
|
||||
fixwlr:
|
||||
sed -E -i -e 's/(soversion = 12)([^032]|$$)/soversion = 12032/g' subprojects/wlroots/meson.build
|
||||
|
||||
rm -rf ./subprojects/wlroots/build
|
||||
|
||||
config:
|
||||
$(MAKE) fixwlr
|
||||
|
||||
meson setup subprojects/wlroots/build subprojects/wlroots --prefix=${PREFIX} --buildtype=release -Dwerror=false -Dexamples=false -Drenderers="gles2"
|
||||
ninja -C subprojects/wlroots/build/
|
||||
|
||||
ninja -C subprojects/wlroots/build/ install
|
||||
|
||||
cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja && cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
||||
pluginenv:
|
||||
cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja && cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
|
||||
|
||||
$(MAKE) fixwlr
|
||||
|
||||
meson setup subprojects/wlroots/build subprojects/wlroots --prefix=${PREFIX} --buildtype=release -Dwerror=false -Dexamples=false
|
||||
ninja -C subprojects/wlroots/build/
|
||||
|
||||
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja
|
||||
@echo -en "$(MAKE) pluginenv has been deprecated.\nPlease run $(MAKE) all && sudo $(MAKE) installheaders\n"
|
||||
@exit 1
|
||||
|
||||
installheaders:
|
||||
@if [ ! -f ./build/Hyprland ]; 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
|
||||
@@ -113,13 +82,8 @@ pluginenv:
|
||||
cp ./build/hyprland.pc ${PREFIX}/share/pkgconfig
|
||||
if [ -d /usr/share/pkgconfig ]; then cp ./build/hyprland.pc /usr/share/pkgconfig 2>/dev/null || true; fi
|
||||
|
||||
configdebug:
|
||||
$(MAKE) fixwlr
|
||||
|
||||
meson setup subprojects/wlroots/build subprojects/wlroots --prefix=${PREFIX} --buildtype=debug -Dwerror=false -Dexamples=false -Drenderers="gles2" -Db_sanitize=address
|
||||
ninja -C subprojects/wlroots/build/
|
||||
|
||||
ninja -C subprojects/wlroots/build/ install
|
||||
chmod -R 755 ${PREFIX}/include/hyprland
|
||||
chmod 755 ${PREFIX}/share/pkgconfig
|
||||
|
||||
man:
|
||||
pandoc ./docs/Hyprland.1.rst \
|
||||
|
@@ -41,6 +41,7 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more...
|
||||
- Much more QoL stuff than other wlr-based compositors
|
||||
- Custom bezier curves for the best animations
|
||||
- Powerful plugin support
|
||||
- Tearing support for better gaming performance
|
||||
- Easily expandable and readable codebase
|
||||
- Fast and active development
|
||||
- Not scared to provide bleeding-edge features
|
||||
|
@@ -1,2 +1,2 @@
|
||||
[preferred]
|
||||
default=hyprland
|
||||
default=hyprland;gtk
|
@@ -33,8 +33,8 @@ void CCustomDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& offset
|
||||
(m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying());
|
||||
|
||||
// draw the border
|
||||
wlr_box fullBox = {(int)(m_vLastWindowPos.x - *PBORDERSIZE), (int)(m_vLastWindowPos.y - *PBORDERSIZE), (int)(m_vLastWindowSize.x + 2.0 * *PBORDERSIZE),
|
||||
(int)(m_vLastWindowSize.y + 2.0 * *PBORDERSIZE)};
|
||||
CBox fullBox = {(int)(m_vLastWindowPos.x - *PBORDERSIZE), (int)(m_vLastWindowPos.y - *PBORDERSIZE), (int)(m_vLastWindowSize.x + 2.0 * *PBORDERSIZE),
|
||||
(int)(m_vLastWindowSize.y + 2.0 * *PBORDERSIZE)};
|
||||
|
||||
fullBox.x -= pMonitor->vecPosition.x;
|
||||
fullBox.y -= pMonitor->vecPosition.y;
|
||||
@@ -49,9 +49,9 @@ void CCustomDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& offset
|
||||
if (fullBox.width < 1 || fullBox.height < 1)
|
||||
return; // don't draw invisible shadows
|
||||
|
||||
g_pHyprOpenGL->scissor((wlr_box*)nullptr);
|
||||
g_pHyprOpenGL->scissor((CBox*)nullptr);
|
||||
|
||||
scaleBox(&fullBox, pMonitor->scale);
|
||||
fullBox.scale(pMonitor->scale);
|
||||
g_pHyprOpenGL->renderBorder(&fullBox, CColor(*PCOLOR), *PROUNDING * pMonitor->scale + *PBORDERSIZE * 2, a);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ void CCustomDecoration::updateWindow(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
void CCustomDecoration::damageEntire() {
|
||||
wlr_box dm = {(int)(m_vLastWindowPos.x - m_seExtents.topLeft.x), (int)(m_vLastWindowPos.y - m_seExtents.topLeft.y),
|
||||
(int)(m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x), (int)m_seExtents.topLeft.y};
|
||||
CBox dm = {(int)(m_vLastWindowPos.x - m_seExtents.topLeft.x), (int)(m_vLastWindowPos.y - m_seExtents.topLeft.y),
|
||||
(int)(m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x), (int)m_seExtents.topLeft.y};
|
||||
g_pHyprRenderer->damageBox(&dm);
|
||||
}
|
@@ -58,8 +58,8 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
||||
|
||||
HyprlandAPI::addNotification(PHANDLE, "Hello World from an example plugin!", CColor{0.f, 1.f, 1.f, 1.f}, 5000);
|
||||
|
||||
HyprlandAPI::registerCallbackDynamic(PHANDLE, "activeWindow", [&](void* self, std::any data) { onActiveWindowChange(self, data); });
|
||||
HyprlandAPI::registerCallbackDynamic(PHANDLE, "openWindow", [&](void* self, std::any data) { onNewWindow(self, data); });
|
||||
HyprlandAPI::registerCallbackDynamic(PHANDLE, "activeWindow", [&](void* self, SCallbackInfo& info, std::any data) { onActiveWindowChange(self, data); });
|
||||
HyprlandAPI::registerCallbackDynamic(PHANDLE, "openWindow", [&](void* self, SCallbackInfo& info, std::any data) { onNewWindow(self, data); });
|
||||
|
||||
g_pCustomLayout = std::make_unique<CHyprCustomLayout>();
|
||||
|
||||
|
@@ -49,6 +49,9 @@ general {
|
||||
col.inactive_border = rgba(595959aa)
|
||||
|
||||
layout = dwindle
|
||||
|
||||
# Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
|
||||
allow_tearing = false
|
||||
}
|
||||
|
||||
decoration {
|
||||
@@ -60,6 +63,8 @@ decoration {
|
||||
enabled = true
|
||||
size = 3
|
||||
passes = 1
|
||||
|
||||
vibrancy = 0.1696
|
||||
}
|
||||
|
||||
drop_shadow = true
|
||||
@@ -99,6 +104,11 @@ gestures {
|
||||
workspace_swipe = false
|
||||
}
|
||||
|
||||
misc {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
force_default_wallpaper = -1 # Set to 0 to disable the anime mascot wallpapers
|
||||
}
|
||||
|
||||
# Example per-device config
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/#per-device-input-configs for more
|
||||
device:epic-mouse-v1 {
|
||||
@@ -155,6 +165,10 @@ bind = $mainMod SHIFT, 8, movetoworkspace, 8
|
||||
bind = $mainMod SHIFT, 9, movetoworkspace, 9
|
||||
bind = $mainMod SHIFT, 0, movetoworkspace, 10
|
||||
|
||||
# Example special workspace (scratchpad)
|
||||
bind = $mainMod, S, togglespecialworkspace, magic
|
||||
bind = $mainMod SHIFT, S, movetoworkspace, special:magic
|
||||
|
||||
# Scroll through existing workspaces with mainMod + scroll
|
||||
bind = $mainMod, mouse_down, workspace, e+1
|
||||
bind = $mainMod, mouse_up, workspace, e-1
|
||||
|
20
flake.lock
generated
20
flake.lock
generated
@@ -25,11 +25,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1694767346,
|
||||
"narHash": "sha256-5uH27SiVFUwsTsqC5rs3kS7pBoNhtoy9QfTP9BmknGk=",
|
||||
"lastModified": 1698134075,
|
||||
"narHash": "sha256-foCD+nuKzfh49bIoiCBur4+Fx1nozo+4C/6k8BYk4sg=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "ace5093e36ab1e95cb9463863491bee90d5a4183",
|
||||
"rev": "8efd5d1e283604f75a808a20e6cde0ef313d07d4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -67,18 +67,18 @@
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"lastModified": 1695277534,
|
||||
"narHash": "sha256-LEIUGXvKR5DYFQUTavC3yifcObvG4XZUUHfxXmu8nEM=",
|
||||
"lastModified": 1699292815,
|
||||
"narHash": "sha256-HXu98PyBMKEWLqiTb8viuLDznud/SdkdJsx5A5CWx7I=",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "98a745d926d8048bc30aef11b421df207a01c279",
|
||||
"rev": "5de9e1a99d6642c2d09d589aa37ff0a8945dcee1",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "98a745d926d8048bc30aef11b421df207a01c279",
|
||||
"rev": "5de9e1a99d6642c2d09d589aa37ff0a8945dcee1",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
@@ -95,11 +95,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1694628480,
|
||||
"narHash": "sha256-Qg9hstRw0pvjGu5hStkr2UX1D73RYcQ9Ns/KnZMIm9w=",
|
||||
"lastModified": 1697981233,
|
||||
"narHash": "sha256-y8q4XUwx+gVK7i2eLjfR32lVo7TYvEslyzrmzYEaPZU=",
|
||||
"owner": "hyprwm",
|
||||
"repo": "xdg-desktop-portal-hyprland",
|
||||
"rev": "8f45a6435069b9e24ebd3160eda736d7a391cbf2",
|
||||
"rev": "22e7a65ff9633e1dedfa5317fdffc49f68de2ff2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@@ -12,7 +12,7 @@
|
||||
host = "gitlab.freedesktop.org";
|
||||
owner = "wlroots";
|
||||
repo = "wlroots";
|
||||
rev = "98a745d926d8048bc30aef11b421df207a01c279";
|
||||
rev = "5de9e1a99d6642c2d09d589aa37ff0a8945dcee1";
|
||||
flake = false;
|
||||
};
|
||||
|
||||
|
8
hyprctl/CMakeLists.txt
Normal file
8
hyprctl/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
|
||||
project(
|
||||
hyprctl
|
||||
DESCRIPTION "Control utility for Hyprland"
|
||||
)
|
||||
|
||||
add_executable(hyprctl "main.cpp")
|
@@ -29,6 +29,7 @@ commands:
|
||||
monitors
|
||||
workspaces
|
||||
activeworkspace
|
||||
workspacerules
|
||||
clients
|
||||
activewindow
|
||||
layers
|
||||
@@ -273,7 +274,6 @@ bool isNumber(const std::string& str, bool allowfloat) {
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int bflag = 0, sflag = 0, index, c;
|
||||
bool parseArgs = true;
|
||||
|
||||
if (argc < 2) {
|
||||
@@ -287,7 +287,7 @@ int main(int argc, char** argv) {
|
||||
bool json = false;
|
||||
std::string overrideInstance = "";
|
||||
|
||||
for (auto i = 0; i < ARGS.size(); ++i) {
|
||||
for (std::size_t i = 0; i < ARGS.size(); ++i) {
|
||||
if (ARGS[i] == "--") {
|
||||
// Stop parsing arguments after --
|
||||
parseArgs = false;
|
||||
@@ -341,7 +341,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
const auto INSTANCES = instances();
|
||||
|
||||
if (INSTANCENO < 0 || INSTANCENO >= INSTANCES.size()) {
|
||||
if (INSTANCENO < 0 || static_cast<std::size_t>(INSTANCENO) >= INSTANCES.size()) {
|
||||
std::cout << "no such instance\n";
|
||||
return 1;
|
||||
}
|
||||
@@ -370,6 +370,8 @@ int main(int argc, char** argv) {
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/activeworkspace"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/workspacerules"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/activewindow"))
|
||||
request(fullRequest);
|
||||
else if (fullRequest.contains("/layers"))
|
||||
|
16
meson.build
16
meson.build
@@ -20,25 +20,19 @@ else
|
||||
error('Could not configure current C++ compiler (' + cpp_compiler.get_id() + ' ' + cpp_compiler.version() + ') with required C++ standard (C++23)')
|
||||
endif
|
||||
|
||||
GIT_BRANCH = run_command('git', 'rev-parse', '--abbrev-ref', 'HEAD', check: false).stdout().strip()
|
||||
GIT_COMMIT_HASH = run_command('git', 'rev-parse', 'HEAD', check: false).stdout().strip()
|
||||
GIT_COMMIT_MESSAGE = run_command('sh', '-c', 'git show | head -n 5 | tail -n 1', check: false).stdout().strip()
|
||||
GIT_DIRTY = run_command('sh', '-c', 'git diff-index --quiet HEAD -- || echo "dirty"', check: false).stdout().strip()
|
||||
|
||||
add_project_arguments(
|
||||
[
|
||||
'-Wno-unused-parameter',
|
||||
'-Wno-unused-value',
|
||||
'-Wno-missing-field-initializers',
|
||||
'-Wno-narrowing',
|
||||
|
||||
f'-DGIT_BRANCH="@GIT_BRANCH@"',
|
||||
f'-DGIT_COMMIT_HASH="@GIT_COMMIT_HASH@"',
|
||||
f'-DGIT_COMMIT_MESSAGE="@GIT_COMMIT_MESSAGE@"',
|
||||
f'-DGIT_DIRTY="@GIT_DIRTY@"',
|
||||
],
|
||||
language: 'cpp')
|
||||
|
||||
if cpp_compiler.check_header('execinfo.h')
|
||||
add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
|
||||
endif
|
||||
|
||||
wlroots = subproject('wlroots', default_options: ['examples=false', 'renderers=gles2'])
|
||||
have_xwlr = wlroots.get_variable('features').get('xwayland')
|
||||
xcb_dep = dependency('xcb', required: get_option('xwayland'))
|
||||
@@ -75,6 +69,8 @@ if get_option('buildtype') == 'debug'
|
||||
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
|
||||
endif
|
||||
|
||||
version_h = run_command('sh', '-c', 'scripts/generateVersion.sh')
|
||||
|
||||
globber = run_command('find', 'src', '-name', '*.h*', check: true)
|
||||
headers = globber.stdout().strip().split('\n')
|
||||
foreach file : headers
|
||||
|
@@ -90,8 +90,9 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
||||
then "debug"
|
||||
else "release";
|
||||
|
||||
mesonAutoFeatures = "disabled";
|
||||
|
||||
mesonFlags = builtins.concatLists [
|
||||
["-Dauto_features=disabled"]
|
||||
(lib.optional enableXWayland "-Dxwayland=enabled")
|
||||
(lib.optional legacyRenderer "-Dlegacy_renderer=enabled")
|
||||
(lib.optional withSystemd "-Dsystemd=enabled")
|
||||
@@ -105,9 +106,15 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov
|
||||
postPatch = ''
|
||||
# Fix hardcoded paths to /usr installation
|
||||
sed -i "s#/usr#$out#" src/render/OpenGL.cpp
|
||||
substituteInPlace meson.build \
|
||||
--replace "@GIT_COMMIT_HASH@" '${commit}' \
|
||||
--replace "@GIT_DIRTY@" '${
|
||||
|
||||
# Generate version.h
|
||||
cp src/version.h.in src/version.h
|
||||
substituteInPlace src/version.h \
|
||||
--replace "@HASH@" '${commit}' \
|
||||
--replace "@BRANCH@" "" \
|
||||
--replace "@MESSAGE@" "" \
|
||||
--replace "@TAG@" "" \
|
||||
--replace "@DIRTY@" '${
|
||||
if commit == ""
|
||||
then "dirty"
|
||||
else ""
|
||||
|
@@ -1,23 +1,11 @@
|
||||
diff --git a/meson.build b/meson.build
|
||||
index f3802553..6a924a79 100644
|
||||
index 1d2c7f9f..c5ef4e67 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -21,9 +21,9 @@ else
|
||||
@@ -33,20 +33,7 @@ if cpp_compiler.check_header('execinfo.h')
|
||||
add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
|
||||
endif
|
||||
|
||||
GIT_BRANCH = run_command('git', 'rev-parse', '--abbrev-ref', 'HEAD', check: false).stdout().strip()
|
||||
-GIT_COMMIT_HASH = run_command('git', 'rev-parse', 'HEAD', check: false).stdout().strip()
|
||||
+GIT_COMMIT_HASH = '@GIT_COMMIT_HASH@'
|
||||
GIT_COMMIT_MESSAGE = run_command('sh', '-c', 'git show | head -n 5 | tail -n 1', check: false).stdout().strip()
|
||||
-GIT_DIRTY = run_command('sh', '-c', 'git diff-index --quiet HEAD -- || echo "dirty"', check: false).stdout().strip()
|
||||
+GIT_DIRTY = '@GIT_DIRTY@'
|
||||
|
||||
add_project_arguments(
|
||||
[
|
||||
@@ -39,21 +39,8 @@ add_project_arguments(
|
||||
],
|
||||
language: 'cpp')
|
||||
|
||||
-wlroots = subproject('wlroots', default_options: ['examples=false', 'renderers=gles2'])
|
||||
-have_xwlr = wlroots.get_variable('features').get('xwayland')
|
||||
-xcb_dep = dependency('xcb', required: get_option('xwayland'))
|
||||
@@ -32,17 +20,24 @@ index f3802553..6a924a79 100644
|
||||
-have_xwayland = xcb_dep.found() and have_xwlr
|
||||
-
|
||||
-if not have_xwayland
|
||||
- add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
|
||||
+if get_option('xwayland').disabled()
|
||||
+ add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
|
||||
add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
|
||||
endif
|
||||
|
||||
backtrace_dep = cpp_compiler.find_library('execinfo', required: false)
|
||||
@@ -69,8 +56,6 @@ if get_option('buildtype') == 'debug'
|
||||
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
|
||||
endif
|
||||
|
||||
-version_h = run_command('sh', '-c', 'scripts/generateVersion.sh')
|
||||
-
|
||||
globber = run_command('find', 'src', '-name', '*.h*', check: true)
|
||||
headers = globber.stdout().strip().split('\n')
|
||||
foreach file : headers
|
||||
diff --git a/src/meson.build b/src/meson.build
|
||||
index 7b658d31..60aa4057 100644
|
||||
index 0af864b9..38723b8c 100644
|
||||
--- a/src/meson.build
|
||||
+++ b/src/meson.build
|
||||
@@ -7,16 +7,16 @@ executable('Hyprland', src,
|
||||
@@ -9,16 +9,16 @@ executable('Hyprland', src,
|
||||
server_protos,
|
||||
dependency('wayland-server'),
|
||||
dependency('wayland-client'),
|
||||
|
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"version": "0.30.0"
|
||||
"version": "0.32.2"
|
||||
}
|
@@ -25,6 +25,7 @@ protocols = [
|
||||
[wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'],
|
||||
['wlr-foreign-toplevel-management-unstable-v1.xml'],
|
||||
['wlr-layer-shell-unstable-v1.xml'],
|
||||
['wlr-output-power-management-unstable-v1.xml'],
|
||||
|
14
scripts/generateVersion.sh
Executable file
14
scripts/generateVersion.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
cp -fr ./src/version.h.in ./src/version.h
|
||||
|
||||
HASH=$(git rev-parse HEAD)
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
MESSAGE=$(git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1 | sed -e 's/#//g' -e 's/\"//g')
|
||||
DIRTY=$(git diff-index --quiet HEAD -- || echo dirty)
|
||||
TAG=$(git describe --tags)
|
||||
|
||||
sed -i -e "s#@HASH@#${HASH}#" ./src/version.h
|
||||
sed -i -e "s#@BRANCH@#${BRANCH}#" ./src/version.h
|
||||
sed -i -e "s#@MESSAGE@#${MESSAGE}#" ./src/version.h
|
||||
sed -i -e "s#@DIRTY@#${DIRTY}#" ./src/version.h
|
||||
sed -i -e "s#@TAG@#${TAG}#" ./src/version.h
|
@@ -34,6 +34,13 @@ void handleUnrecoverableSignal(int sig) {
|
||||
abort();
|
||||
}
|
||||
|
||||
void handleUserSignal(int sig) {
|
||||
if (sig == SIGUSR1) {
|
||||
// means we have to unwind a timed out event
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
|
||||
CCompositor::CCompositor() {
|
||||
m_iHyprlandPID = getpid();
|
||||
|
||||
@@ -74,6 +81,7 @@ CCompositor::CCompositor() {
|
||||
|
||||
CCompositor::~CCompositor() {
|
||||
cleanup();
|
||||
g_pDecorationPositioner.reset();
|
||||
g_pPluginSystem.reset();
|
||||
g_pHyprNotificationOverlay.reset();
|
||||
g_pDebugOverlay.reset();
|
||||
@@ -92,6 +100,7 @@ CCompositor::~CCompositor() {
|
||||
g_pAnimationManager.reset();
|
||||
g_pKeybindManager.reset();
|
||||
g_pHookSystem.reset();
|
||||
g_pWatchdog.reset();
|
||||
}
|
||||
|
||||
void CCompositor::setRandomSplash() {
|
||||
@@ -112,7 +121,7 @@ void CCompositor::initServer() {
|
||||
wl_event_loop_add_signal(m_sWLEventLoop, SIGTERM, handleCritSignal, nullptr);
|
||||
signal(SIGSEGV, handleUnrecoverableSignal);
|
||||
signal(SIGABRT, handleUnrecoverableSignal);
|
||||
//wl_event_loop_add_signal(m_sWLEventLoop, SIGINT, handleCritSignal, nullptr);
|
||||
signal(SIGUSR1, handleUserSignal);
|
||||
|
||||
initManagers(STAGE_PRIORITY);
|
||||
|
||||
@@ -124,6 +133,8 @@ void CCompositor::initServer() {
|
||||
const auto LOGWLR = getenv("HYPRLAND_LOG_WLR");
|
||||
if (LOGWLR && std::string(LOGWLR) == "1")
|
||||
wlr_log_init(WLR_DEBUG, Debug::wlrLog);
|
||||
else
|
||||
wlr_log_init(WLR_ERROR, Debug::wlrLog);
|
||||
|
||||
m_sWLRBackend = wlr_backend_autocreate(m_sWLDisplay, &m_sWLRSession);
|
||||
|
||||
@@ -204,7 +215,6 @@ void CCompositor::initServer() {
|
||||
|
||||
m_sWLRPresentation = wlr_presentation_create(m_sWLDisplay, m_sWLRBackend);
|
||||
|
||||
m_sWLRIdle = wlr_idle_create(m_sWLDisplay);
|
||||
m_sWLRIdleNotifier = wlr_idle_notifier_v1_create(m_sWLDisplay);
|
||||
|
||||
m_sWLRLayerShell = wlr_layer_shell_v1_create(m_sWLDisplay, 4);
|
||||
@@ -257,6 +267,8 @@ void CCompositor::initServer() {
|
||||
|
||||
m_sWLRCursorShapeMgr = wlr_cursor_shape_manager_v1_create(m_sWLDisplay, 1);
|
||||
|
||||
m_sWLRTearingControlMgr = wlr_tearing_control_manager_v1_create(m_sWLDisplay, 1);
|
||||
|
||||
if (!m_sWLRHeadlessBackend) {
|
||||
Debug::log(CRIT, "Couldn't create the headless backend");
|
||||
throwError("wlr_headless_backend_create() failed!");
|
||||
@@ -315,6 +327,7 @@ void CCompositor::initAllSignals() {
|
||||
addWLSignal(&m_sWLRSessionLockMgr->events.new_lock, &Events::listen_newSessionLock, m_sWLRSessionLockMgr, "SessionLockMgr");
|
||||
addWLSignal(&m_sWLRGammaCtrlMgr->events.set_gamma, &Events::listen_setGamma, m_sWLRGammaCtrlMgr, "GammaCtrlMgr");
|
||||
addWLSignal(&m_sWLRCursorShapeMgr->events.request_set_shape, &Events::listen_setCursorShape, m_sWLRCursorShapeMgr, "CursorShapeMgr");
|
||||
addWLSignal(&m_sWLRTearingControlMgr->events.new_object, &Events::listen_newTearingHint, m_sWLRTearingControlMgr, "TearingControlMgr");
|
||||
|
||||
if (m_sWRLDRMLeaseMgr)
|
||||
addWLSignal(&m_sWRLDRMLeaseMgr->events.request, &Events::listen_leaseRequest, &m_sWRLDRMLeaseMgr, "DRM");
|
||||
@@ -392,6 +405,7 @@ void CCompositor::initManagers(eManagersInitStage stage) {
|
||||
g_pLayoutManager = std::make_unique<CLayoutManager>();
|
||||
|
||||
g_pConfigManager->init();
|
||||
g_pWatchdog = std::make_unique<CWatchdog>(); // requires config
|
||||
} break;
|
||||
case STAGE_LATE: {
|
||||
Debug::log(LOG, "Creating the ThreadManager!");
|
||||
@@ -428,6 +442,9 @@ void CCompositor::initManagers(eManagersInitStage stage) {
|
||||
Debug::log(LOG, "Creating the PluginSystem!");
|
||||
g_pPluginSystem = std::make_unique<CPluginSystem>();
|
||||
g_pConfigManager->handlePluginLoads();
|
||||
|
||||
Debug::log(LOG, "Creating the DecorationPositioner!");
|
||||
g_pDecorationPositioner = std::make_unique<CDecorationPositioner>();
|
||||
} break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
@@ -450,6 +467,25 @@ void CCompositor::removeLockFile() {
|
||||
std::filesystem::remove(PATH);
|
||||
}
|
||||
|
||||
void CCompositor::prepareFallbackOutput() {
|
||||
// create a backup monitor
|
||||
wlr_backend* headless = nullptr;
|
||||
wlr_multi_for_each_backend(
|
||||
m_sWLRBackend,
|
||||
[](wlr_backend* b, void* data) {
|
||||
if (wlr_backend_is_headless(b))
|
||||
*((wlr_backend**)data) = b;
|
||||
},
|
||||
&headless);
|
||||
|
||||
if (!headless) {
|
||||
Debug::log(WARN, "Unsafe state will be ineffective, no fallback output");
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_headless_add_output(headless, 1920, 1080);
|
||||
}
|
||||
|
||||
void CCompositor::startCompositor() {
|
||||
initAllSignals();
|
||||
|
||||
@@ -501,7 +537,9 @@ void CCompositor::startCompositor() {
|
||||
throwError("The backend could not start!");
|
||||
}
|
||||
|
||||
wlr_cursor_set_xcursor(m_sWLRCursor, m_sWLRXCursorMgr, "left_ptr");
|
||||
prepareFallbackOutput();
|
||||
|
||||
g_pHyprRenderer->setCursorFromName("left_ptr");
|
||||
|
||||
#ifdef USES_SYSTEMD
|
||||
if (sd_booted() > 0)
|
||||
@@ -539,7 +577,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).find(desc) == 0)
|
||||
if (m->output->description && std::string(m->output->description).starts_with(desc))
|
||||
return m.get();
|
||||
}
|
||||
return nullptr;
|
||||
@@ -597,38 +635,35 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
|
||||
|
||||
if (PMONITOR->specialWorkspaceID) {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->isHidden() &&
|
||||
!w->m_bNoFocus)
|
||||
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) {
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && !w->m_bIsFloating && !w->isHidden() &&
|
||||
!w->m_bNoFocus)
|
||||
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) {
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && w->m_bIsFloating && !w->isHidden() && w->m_bPinned && !w->m_bNoFocus)
|
||||
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) {
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned &&
|
||||
!w->m_bNoFocus)
|
||||
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) {
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && !w->m_bIsFloating && PMONITOR->activeWorkspace == w->m_iWorkspaceID && !w->isHidden() && !w->m_bNoFocus)
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -640,15 +675,15 @@ CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) {
|
||||
|
||||
if (PMONITOR->specialWorkspaceID) {
|
||||
for (auto& w : m_vWindows) {
|
||||
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus)
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && box.containsPoint(pos) && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus)
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
@@ -666,16 +701,16 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
if (PMONITOR->specialWorkspaceID) {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
const auto BB = w->getWindowInputBox();
|
||||
wlr_box 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 && wlr_box_contains_point(&box, pos.x, pos.y) && !w->isHidden() &&
|
||||
!w->m_bX11ShouldntFocus && !w->m_bNoFocus)
|
||||
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) {
|
||||
wlr_box 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 && wlr_box_contains_point(&box, pos.x, pos.y) && !w->isHidden() &&
|
||||
!w->m_bX11ShouldntFocus && !w->m_bNoFocus)
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -683,9 +718,9 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
// pinned windows on top of floating regardless
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
const auto BB = w->getWindowInputBox();
|
||||
wlr_box box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
||||
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 (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y))
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}))
|
||||
return w.get();
|
||||
|
||||
if (!w->m_bIsX11) {
|
||||
@@ -698,13 +733,13 @@ 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();
|
||||
wlr_box box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA};
|
||||
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)
|
||||
continue;
|
||||
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y)) {
|
||||
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
|
||||
@@ -730,9 +765,9 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) {
|
||||
}
|
||||
}
|
||||
for (auto& w : m_vWindows) {
|
||||
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (!w->m_bIsFloating && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->isHidden() &&
|
||||
!w->m_bX11ShouldntFocus && !w->m_bNoFocus)
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -744,37 +779,36 @@ CWindow* CCompositor::windowFromCursor() {
|
||||
|
||||
if (PMONITOR->specialWorkspaceID) {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) &&
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) &&
|
||||
!w->isHidden() && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && !w->m_bNoFocus)
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
}
|
||||
|
||||
// pinned
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && w->m_bIsFloating && w->m_bPinned && !w->m_bNoFocus)
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
// 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) {
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bPinned &&
|
||||
!w->m_bNoFocus)
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bNoFocus)
|
||||
CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
@@ -783,14 +817,14 @@ CWindow* CCompositor::windowFromCursor() {
|
||||
|
||||
CWindow* CCompositor::windowFloatingFromCursor() {
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && w->m_bIsFloating && !w->isHidden() && w->m_bPinned && !w->m_bNoFocus)
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && !w->isHidden() && w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
|
||||
for (auto& w : m_vWindows | std::views::reverse) {
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() &&
|
||||
CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() &&
|
||||
!w->m_bPinned && !w->m_bNoFocus)
|
||||
return w.get();
|
||||
}
|
||||
@@ -810,8 +844,9 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pW
|
||||
double subx, suby;
|
||||
|
||||
// calc for oversized windows... fucking bullshit, again.
|
||||
wlr_box geom;
|
||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom);
|
||||
CBox geom;
|
||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, geom.pWlr());
|
||||
geom.applyFromWlr();
|
||||
|
||||
const auto PFOUND = wlr_xdg_surface_surface_at(PSURFACE, pos.x - pWindow->m_vRealPosition.vec().x + geom.x, pos.y - pWindow->m_vRealPosition.vec().y + geom.y, &subx, &suby);
|
||||
|
||||
@@ -830,6 +865,38 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pW
|
||||
return PSURFACE->surface;
|
||||
}
|
||||
|
||||
Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, CWindow* pWindow, wlr_surface* pSurface) {
|
||||
if (!windowValidMapped(pWindow))
|
||||
return {};
|
||||
|
||||
if (pWindow->m_bIsX11)
|
||||
return vec - pWindow->m_vRealPosition.goalv();
|
||||
|
||||
const auto PSURFACE = pWindow->m_uSurface.xdg;
|
||||
|
||||
std::tuple<wlr_surface*, int, int> iterData = {pSurface, -1337, -1337};
|
||||
|
||||
wlr_xdg_surface_for_each_surface(
|
||||
PSURFACE,
|
||||
[](wlr_surface* surf, int x, int y, void* data) {
|
||||
const auto PDATA = (std::tuple<wlr_surface*, int, int>*)data;
|
||||
if (surf == std::get<0>(*PDATA)) {
|
||||
std::get<1>(*PDATA) = x;
|
||||
std::get<2>(*PDATA) = y;
|
||||
}
|
||||
},
|
||||
&iterData);
|
||||
|
||||
CBox geom = {};
|
||||
wlr_xdg_surface_get_geometry(PSURFACE, geom.pWlr());
|
||||
geom.applyFromWlr();
|
||||
|
||||
if (std::get<1>(iterData) == -1337 && std::get<2>(iterData) == -1337)
|
||||
return vec - pWindow->m_vRealPosition.goalv();
|
||||
|
||||
return vec - pWindow->m_vRealPosition.goalv() - Vector2D{std::get<1>(iterData), std::get<2>(iterData)} + Vector2D{geom.x, geom.y};
|
||||
}
|
||||
|
||||
CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) {
|
||||
for (auto& m : m_vMonitors) {
|
||||
if (m->output == out) {
|
||||
@@ -842,6 +909,8 @@ CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) {
|
||||
|
||||
void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
|
||||
static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||
|
||||
if (g_pCompositor->m_sSeat.exclusiveClient) {
|
||||
Debug::log(LOG, "Disallowing setting focus to a window due to there being an active input inhibitor layer.");
|
||||
return;
|
||||
@@ -850,6 +919,10 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
g_pLayoutManager->getCurrentLayout()->bringWindowToTop(pWindow);
|
||||
|
||||
if (!pWindow || !windowValidMapped(pWindow)) {
|
||||
|
||||
if (!m_pLastWindow && !pWindow)
|
||||
return;
|
||||
|
||||
const auto PLASTWINDOW = m_pLastWindow;
|
||||
m_pLastWindow = nullptr;
|
||||
|
||||
@@ -961,6 +1034,9 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) {
|
||||
} else {
|
||||
std::rotate(m_vWindowFocusHistory.begin(), HISTORYPIVOT, HISTORYPIVOT + 1);
|
||||
}
|
||||
|
||||
if (*PFOLLOWMOUSE == 0)
|
||||
g_pInputManager->sendMotionEventsToFocused();
|
||||
}
|
||||
|
||||
void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) {
|
||||
@@ -1141,27 +1217,39 @@ void CCompositor::sanityCheckWorkspaces() {
|
||||
auto it = m_vWorkspaces.begin();
|
||||
while (it != m_vWorkspaces.end()) {
|
||||
|
||||
if ((*it)->m_bIndestructible)
|
||||
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(it->get());
|
||||
if (WORKSPACERULE.isPersistent) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto WINDOWSONWORKSPACE = getWindowsOnWorkspace((*it)->m_iID);
|
||||
const auto& WORKSPACE = *it;
|
||||
const auto WINDOWSONWORKSPACE = getWindowsOnWorkspace(WORKSPACE->m_iID);
|
||||
|
||||
if ((WINDOWSONWORKSPACE == 0 && !isWorkspaceVisible((*it)->m_iID))) {
|
||||
if (WINDOWSONWORKSPACE == 0) {
|
||||
if (!isWorkspaceVisible(WORKSPACE->m_iID)) {
|
||||
|
||||
if ((*it)->m_bIsSpecialWorkspace) {
|
||||
if ((*it)->m_fAlpha.fl() > 0.f /* don't abruptly end the fadeout */) {
|
||||
++it;
|
||||
continue;
|
||||
if (WORKSPACE->m_bIsSpecialWorkspace) {
|
||||
if (WORKSPACE->m_fAlpha.fl() > 0.f /* don't abruptly end the fadeout */) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto PMONITOR = getMonitorFromID(WORKSPACE->m_iMonitorID);
|
||||
|
||||
if (PMONITOR && PMONITOR->specialWorkspaceID == WORKSPACE->m_iID)
|
||||
PMONITOR->setSpecialWorkspace(nullptr);
|
||||
}
|
||||
|
||||
const auto PMONITOR = getMonitorFromID((*it)->m_iMonitorID);
|
||||
|
||||
if (PMONITOR && PMONITOR->specialWorkspaceID == (*it)->m_iID)
|
||||
PMONITOR->setSpecialWorkspace(nullptr);
|
||||
it = m_vWorkspaces.erase(it);
|
||||
continue;
|
||||
}
|
||||
if (!WORKSPACE->m_bOnCreatedEmptyExecuted) {
|
||||
if (auto cmd = WORKSPACERULE.onCreatedEmptyRunCmd)
|
||||
g_pKeybindManager->spawn(*cmd);
|
||||
|
||||
it = m_vWorkspaces.erase(it);
|
||||
continue;
|
||||
WORKSPACE->m_bOnCreatedEmptyExecuted = true;
|
||||
}
|
||||
}
|
||||
|
||||
++it;
|
||||
@@ -1417,82 +1505,144 @@ void CCompositor::addToFadingOutSafe(CWindow* pWindow) {
|
||||
|
||||
CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) {
|
||||
|
||||
if (!isDirection(dir))
|
||||
return nullptr;
|
||||
|
||||
// 0 -> history, 1 -> shared length
|
||||
static auto* const PMETHOD = &g_pConfigManager->getConfigValuePtr("binds:focus_preferred_method")->intValue;
|
||||
|
||||
const auto WINDOWIDEALBB = pWindow->getWindowIdealBoundingBoxIgnoreReserved();
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
const auto POSA = Vector2D(WINDOWIDEALBB.x, WINDOWIDEALBB.y);
|
||||
const auto SIZEA = Vector2D(WINDOWIDEALBB.width, WINDOWIDEALBB.height);
|
||||
if (!PMONITOR)
|
||||
return nullptr; // ??
|
||||
|
||||
auto leaderValue = -1;
|
||||
CWindow* leaderWindow = nullptr;
|
||||
const auto WINDOWIDEALBB = pWindow->m_bIsFullscreen ? wlr_box{(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y} :
|
||||
pWindow->getWindowIdealBoundingBoxIgnoreReserved();
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w.get() == pWindow || !w->m_bIsMapped || w->isHidden() || w->m_bIsFloating || !isWorkspaceVisible(w->m_iWorkspaceID))
|
||||
continue;
|
||||
const auto POSA = Vector2D(WINDOWIDEALBB.x, WINDOWIDEALBB.y);
|
||||
const auto SIZEA = Vector2D(WINDOWIDEALBB.width, WINDOWIDEALBB.height);
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID);
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !w->m_bIsFullscreen && !w->m_bCreatedOverFullscreen)
|
||||
continue;
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
auto leaderValue = -1;
|
||||
CWindow* leaderWindow = nullptr;
|
||||
|
||||
const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved();
|
||||
if (!pWindow->m_bIsFloating) {
|
||||
|
||||
const auto POSB = Vector2D(BWINDOWIDEALBB.x, BWINDOWIDEALBB.y);
|
||||
const auto SIZEB = Vector2D(BWINDOWIDEALBB.width, BWINDOWIDEALBB.height);
|
||||
// for tiled windows, we calc edges
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w.get() == pWindow || !w->m_bIsMapped || w->isHidden() || w->m_bIsFloating || !isWorkspaceVisible(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
double intersectLength = -1;
|
||||
if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_iWorkspaceID != w->m_iWorkspaceID)
|
||||
continue;
|
||||
|
||||
switch (dir) {
|
||||
case 'l':
|
||||
if (STICKS(POSA.x, POSB.x + SIZEB.x)) {
|
||||
intersectLength = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
if (STICKS(POSA.x + SIZEA.x, POSB.x)) {
|
||||
intersectLength = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
case 'u':
|
||||
if (STICKS(POSA.y, POSB.y + SIZEB.y)) {
|
||||
intersectLength = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
case 'd':
|
||||
if (STICKS(POSA.y + SIZEA.y, POSB.y)) {
|
||||
intersectLength = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !w->m_bIsFullscreen && !w->m_bCreatedOverFullscreen)
|
||||
continue;
|
||||
|
||||
if (*PMETHOD == 0 /* history */) {
|
||||
if (intersectLength > 0) {
|
||||
const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved();
|
||||
|
||||
// get idx
|
||||
int windowIDX = -1;
|
||||
for (size_t i = 0; i < g_pCompositor->m_vWindowFocusHistory.size(); ++i) {
|
||||
if (g_pCompositor->m_vWindowFocusHistory[i] == w.get()) {
|
||||
windowIDX = i;
|
||||
break;
|
||||
const auto POSB = Vector2D(BWINDOWIDEALBB.x, BWINDOWIDEALBB.y);
|
||||
const auto SIZEB = Vector2D(BWINDOWIDEALBB.width, BWINDOWIDEALBB.height);
|
||||
|
||||
double intersectLength = -1;
|
||||
|
||||
switch (dir) {
|
||||
case 'l':
|
||||
if (STICKS(POSA.x, POSB.x + SIZEB.x)) {
|
||||
intersectLength = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
if (STICKS(POSA.x + SIZEA.x, POSB.x)) {
|
||||
intersectLength = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y));
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
case 'u':
|
||||
if (STICKS(POSA.y, POSB.y + SIZEB.y)) {
|
||||
intersectLength = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
case 'd':
|
||||
if (STICKS(POSA.y + SIZEA.y, POSB.y)) {
|
||||
intersectLength = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (*PMETHOD == 0 /* history */) {
|
||||
if (intersectLength > 0) {
|
||||
|
||||
// get idx
|
||||
int windowIDX = -1;
|
||||
for (size_t i = 0; i < g_pCompositor->m_vWindowFocusHistory.size(); ++i) {
|
||||
if (g_pCompositor->m_vWindowFocusHistory[i] == w.get()) {
|
||||
windowIDX = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
windowIDX = g_pCompositor->m_vWindowFocusHistory.size() - windowIDX;
|
||||
|
||||
if (windowIDX > leaderValue) {
|
||||
leaderValue = windowIDX;
|
||||
leaderWindow = w.get();
|
||||
}
|
||||
}
|
||||
|
||||
windowIDX = g_pCompositor->m_vWindowFocusHistory.size() - windowIDX;
|
||||
|
||||
if (windowIDX > leaderValue) {
|
||||
leaderValue = windowIDX;
|
||||
} else /* length */ {
|
||||
if (intersectLength > leaderValue) {
|
||||
leaderValue = intersectLength;
|
||||
leaderWindow = w.get();
|
||||
}
|
||||
}
|
||||
} else /* length */ {
|
||||
if (intersectLength > leaderValue) {
|
||||
leaderValue = intersectLength;
|
||||
}
|
||||
} else {
|
||||
// for floating windows, we calculate best distance and angle.
|
||||
// if there is a window with angle better than THRESHOLD, only distance counts
|
||||
|
||||
if (dir == 'u')
|
||||
dir = 't';
|
||||
if (dir == 'd')
|
||||
dir = 'b';
|
||||
|
||||
static const std::unordered_map<char, Vector2D> VECTORS = {{'r', {1, 0}}, {'t', {0, -1}}, {'b', {0, 1}}, {'l', {-1, 0}}};
|
||||
|
||||
//
|
||||
auto vectorAngles = [](Vector2D a, Vector2D b) -> double {
|
||||
double dot = a.x * b.x + a.y * b.y;
|
||||
double ang = std::acos(dot / (a.size() * b.size()));
|
||||
return ang;
|
||||
};
|
||||
|
||||
float bestAngleAbs = 2.0 * M_PI;
|
||||
constexpr float THRESHOLD = 0.3 * M_PI;
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
if (w.get() == pWindow || !w->m_bIsMapped || w->isHidden() || !w->m_bIsFloating || !isWorkspaceVisible(w->m_iWorkspaceID))
|
||||
continue;
|
||||
|
||||
if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_iWorkspaceID != w->m_iWorkspaceID)
|
||||
continue;
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !w->m_bIsFullscreen && !w->m_bCreatedOverFullscreen)
|
||||
continue;
|
||||
|
||||
const auto DIST = w->middle().distance(pWindow->middle());
|
||||
const auto ANGLE = vectorAngles(Vector2D{w->middle() - pWindow->middle()}, VECTORS.at(dir));
|
||||
|
||||
if (ANGLE > M_PI_2)
|
||||
continue; // if the angle is over 90 degrees, ignore. Wrong direction entirely.
|
||||
|
||||
if ((bestAngleAbs < THRESHOLD && DIST < leaderValue && ANGLE < THRESHOLD) || (ANGLE < bestAngleAbs && bestAngleAbs > THRESHOLD) || leaderValue == -1) {
|
||||
leaderValue = DIST;
|
||||
bestAngleAbs = ANGLE;
|
||||
leaderWindow = w.get();
|
||||
}
|
||||
}
|
||||
|
||||
if (!leaderWindow && PWORKSPACE->m_bHasFullscreenWindow)
|
||||
leaderWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
}
|
||||
|
||||
if (leaderValue != -1)
|
||||
@@ -1567,7 +1717,7 @@ CWorkspace* CCompositor::getWorkspaceByName(const std::string& name) {
|
||||
}
|
||||
|
||||
CWorkspace* CCompositor::getWorkspaceByString(const std::string& str) {
|
||||
if (str.find("name:") == 0) {
|
||||
if (str.starts_with("name:")) {
|
||||
return getWorkspaceByName(str.substr(str.find_first_of(':') + 1));
|
||||
}
|
||||
|
||||
@@ -1694,10 +1844,10 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
|
||||
static auto* const INACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.inactive_border")->data.get();
|
||||
static auto* const NOGROUPACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.nogroup_border_active")->data.get();
|
||||
static auto* const NOGROUPINACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.nogroup_border")->data.get();
|
||||
static auto* const GROUPACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.group_border_active")->data.get();
|
||||
static auto* const GROUPINACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.group_border")->data.get();
|
||||
static auto* const GROUPACTIVELOCKEDCOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.group_border_locked_active")->data.get();
|
||||
static auto* const GROUPINACTIVELOCKEDCOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.group_border_locked")->data.get();
|
||||
static auto* const GROUPACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:col.border_active")->data.get();
|
||||
static auto* const GROUPINACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:col.border_inactive")->data.get();
|
||||
static auto* const GROUPACTIVELOCKEDCOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:col.border_locked_active")->data.get();
|
||||
static auto* const GROUPINACTIVELOCKEDCOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:col.border_locked_inactive")->data.get();
|
||||
static auto* const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue;
|
||||
static auto* const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue;
|
||||
static auto* const PFULLSCREENALPHA = &g_pConfigManager->getConfigValuePtr("decoration:fullscreen_opacity")->floatValue;
|
||||
@@ -1774,8 +1924,7 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
|
||||
pWindow->m_cRealShadowColor.setValueAndWarp(CColor(0, 0, 0, 0)); // no shadow
|
||||
}
|
||||
|
||||
for (auto& d : pWindow->m_dWindowDecorations)
|
||||
d->updateWindow(pWindow);
|
||||
pWindow->updateWindowDecos();
|
||||
}
|
||||
|
||||
int CCompositor::getNextAvailableMonitorID(std::string const& name) {
|
||||
@@ -1926,14 +2075,14 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) {
|
||||
Debug::log(ERR, "Error in getMonitorFromString: invalid arg 1");
|
||||
return nullptr;
|
||||
}
|
||||
} else if (name.find("desc:") == 0) {
|
||||
} else if (name.starts_with("desc:")) {
|
||||
const auto DESCRIPTION = name.substr(5);
|
||||
|
||||
for (auto& m : m_vMonitors) {
|
||||
if (!m->output)
|
||||
continue;
|
||||
|
||||
if (m->output->description && std::string(m->output->description).find(DESCRIPTION) == 0) {
|
||||
if (m->output->description && std::string(m->output->description).starts_with(DESCRIPTION)) {
|
||||
return m.get();
|
||||
}
|
||||
}
|
||||
@@ -2108,7 +2257,7 @@ void CCompositor::updateFullscreenFadeOnWorkspace(CWorkspace* pWorkspace) {
|
||||
}
|
||||
|
||||
void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode mode) {
|
||||
if (!windowValidMapped(pWindow))
|
||||
if (!windowValidMapped(pWindow) || g_pCompositor->m_bUnsafeState)
|
||||
return;
|
||||
|
||||
if (pWindow->m_bPinned) {
|
||||
@@ -2120,14 +2269,16 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode
|
||||
|
||||
const auto PWORKSPACE = getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
const auto MODE = mode == FULLSCREEN_INVALID ? PWORKSPACE->m_efFullscreenMode : mode;
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && on) {
|
||||
Debug::log(LOG, "Rejecting fullscreen ON on a fullscreen workspace");
|
||||
return;
|
||||
}
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(pWindow, mode, on);
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(pWindow, MODE, on);
|
||||
|
||||
g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->m_bIsFullscreen && mode == FULLSCREEN_FULL);
|
||||
g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->m_bIsFullscreen && MODE == FULLSCREEN_FULL);
|
||||
|
||||
pWindow->updateDynamicRules();
|
||||
updateWindowAnimatedDecorationValues(pWindow);
|
||||
@@ -2193,15 +2344,30 @@ CWindow* CCompositor::getWindowByRegex(const std::string& regexp) {
|
||||
|
||||
std::regex regexCheck(regexp);
|
||||
std::string matchCheck;
|
||||
if (regexp.find("title:") == 0) {
|
||||
if (regexp.starts_with("title:")) {
|
||||
mode = MODE_TITLE_REGEX;
|
||||
regexCheck = std::regex(regexp.substr(6));
|
||||
} else if (regexp.find("address:") == 0) {
|
||||
} else if (regexp.starts_with("address:")) {
|
||||
mode = MODE_ADDRESS;
|
||||
matchCheck = regexp.substr(8);
|
||||
} else if (regexp.find("pid:") == 0) {
|
||||
} else if (regexp.starts_with("pid:")) {
|
||||
mode = MODE_PID;
|
||||
matchCheck = regexp.substr(4);
|
||||
} else if (regexp.starts_with("floating") || regexp.starts_with("tiled")) {
|
||||
// first floating on the current ws
|
||||
if (!m_pLastWindow)
|
||||
return nullptr;
|
||||
|
||||
const bool FLOAT = regexp.starts_with("floating");
|
||||
|
||||
for (auto& w : m_vWindows) {
|
||||
if (!w->m_bIsMapped || w->m_bIsFloating != FLOAT || w->m_iWorkspaceID != m_pLastWindow->m_iWorkspaceID || w->isHidden())
|
||||
continue;
|
||||
|
||||
return w.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
@@ -2445,7 +2611,13 @@ int CCompositor::getNewSpecialID() {
|
||||
}
|
||||
|
||||
void CCompositor::performUserChecks() {
|
||||
// empty
|
||||
const auto atomicEnv = getenv("WLR_DRM_NO_ATOMIC");
|
||||
const auto atomicEnvStr = std::string(atomicEnv ? atomicEnv : "");
|
||||
if (g_pConfigManager->getInt("general:allow_tearing") == 1 && atomicEnvStr != "1") {
|
||||
g_pHyprNotificationOverlay->addNotification("You have enabled tearing, but immediate presentations are not available on your configuration. Try adding "
|
||||
"env = WLR_DRM_NO_ATOMIC,1 to your config.",
|
||||
CColor(0), 15000, ICON_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
void CCompositor::moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorkspace) {
|
||||
@@ -2510,12 +2682,10 @@ CWindow* CCompositor::getForceFocus() {
|
||||
}
|
||||
|
||||
void CCompositor::notifyIdleActivity() {
|
||||
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
|
||||
wlr_idle_notifier_v1_notify_activity(g_pCompositor->m_sWLRIdleNotifier, g_pCompositor->m_sSeat.seat);
|
||||
}
|
||||
|
||||
void CCompositor::setIdleActivityInhibit(bool enabled) {
|
||||
wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, enabled);
|
||||
wlr_idle_notifier_v1_set_inhibited(g_pCompositor->m_sWLRIdleNotifier, !enabled);
|
||||
}
|
||||
void CCompositor::arrangeMonitors() {
|
||||
@@ -2576,3 +2746,50 @@ void CCompositor::arrangeMonitors() {
|
||||
m->xwaylandScale = 1.f;
|
||||
}
|
||||
}
|
||||
|
||||
void CCompositor::enterUnsafeState() {
|
||||
if (m_bUnsafeState)
|
||||
return;
|
||||
|
||||
Debug::log(LOG, "Entering unsafe state");
|
||||
|
||||
if (!m_pUnsafeOutput->m_bEnabled)
|
||||
m_pUnsafeOutput->onConnect(false);
|
||||
|
||||
m_bUnsafeState = true;
|
||||
}
|
||||
|
||||
void CCompositor::leaveUnsafeState() {
|
||||
if (!m_bUnsafeState)
|
||||
return;
|
||||
|
||||
Debug::log(LOG, "Leaving unsafe state");
|
||||
|
||||
m_bUnsafeState = false;
|
||||
|
||||
CMonitor* pNewMonitor = nullptr;
|
||||
for (auto& pMonitor : m_vMonitors) {
|
||||
if (pMonitor->output != m_pUnsafeOutput->output) {
|
||||
pNewMonitor = pMonitor.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RASSERT(pNewMonitor, "Tried to leave unsafe without a monitor");
|
||||
|
||||
if (m_pUnsafeOutput->m_bEnabled)
|
||||
m_pUnsafeOutput->onDisconnect();
|
||||
|
||||
for (auto& m : m_vMonitors) {
|
||||
scheduleFrameForMonitor(m.get());
|
||||
}
|
||||
}
|
||||
|
||||
void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scale) {
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(pSurface, scale);
|
||||
wlr_surface_set_preferred_buffer_scale(pSurface, static_cast<int32_t>(std::ceil(scale)));
|
||||
}
|
||||
|
||||
void CCompositor::setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform) {
|
||||
wlr_surface_set_preferred_buffer_transform(pSurface, transform);
|
||||
}
|
@@ -27,8 +27,10 @@
|
||||
#include "render/OpenGL.hpp"
|
||||
#include "hyprerror/HyprError.hpp"
|
||||
#include "plugins/PluginSystem.hpp"
|
||||
#include "helpers/Watchdog.hpp"
|
||||
|
||||
enum eManagersInitStage {
|
||||
enum eManagersInitStage
|
||||
{
|
||||
STAGE_PRIORITY = 0,
|
||||
STAGE_LATE
|
||||
};
|
||||
@@ -52,7 +54,6 @@ class CCompositor {
|
||||
wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr;
|
||||
wlr_xdg_activation_v1* m_sWLRXDGActivation;
|
||||
wlr_output_layout* m_sWLROutputLayout;
|
||||
wlr_idle* m_sWLRIdle;
|
||||
wlr_idle_notifier_v1* m_sWLRIdleNotifier;
|
||||
wlr_layer_shell_v1* m_sWLRLayerShell;
|
||||
wlr_xdg_shell* m_sWLRXDGShell;
|
||||
@@ -84,6 +85,7 @@ class CCompositor {
|
||||
wlr_session_lock_manager_v1* m_sWLRSessionLockMgr;
|
||||
wlr_gamma_control_manager_v1* m_sWLRGammaCtrlMgr;
|
||||
wlr_cursor_shape_manager_v1* m_sWLRCursorShapeMgr;
|
||||
wlr_tearing_control_manager_v1* m_sWLRTearingControlMgr;
|
||||
// ------------------------------------------------- //
|
||||
|
||||
std::string m_szWLDisplaySocket = "";
|
||||
@@ -118,7 +120,9 @@ class CCompositor {
|
||||
bool m_bReadyToProcess = false;
|
||||
bool m_bSessionActive = true;
|
||||
bool m_bDPMSStateON = true;
|
||||
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
|
||||
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
|
||||
bool m_bNextIsUnsafe = false; // because wlroots
|
||||
CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state
|
||||
bool m_bIsShuttingDown = false;
|
||||
|
||||
// ------------------------------------------------- //
|
||||
@@ -138,6 +142,7 @@ class CCompositor {
|
||||
CWindow* vectorToWindowTiled(const Vector2D&);
|
||||
wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector<std::unique_ptr<SLayerSurface>>*, Vector2D*, SLayerSurface**);
|
||||
wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
|
||||
Vector2D vectorToSurfaceLocal(const Vector2D&, CWindow*, wlr_surface*);
|
||||
CWindow* windowFromCursor();
|
||||
CWindow* windowFloatingFromCursor();
|
||||
CMonitor* getMonitorFromOutput(wlr_output*);
|
||||
@@ -200,6 +205,10 @@ class CCompositor {
|
||||
void notifyIdleActivity();
|
||||
void setIdleActivityInhibit(bool inhibit);
|
||||
void arrangeMonitors();
|
||||
void enterUnsafeState();
|
||||
void leaveUnsafeState();
|
||||
void setPreferredScaleForSurface(wlr_surface* pSurface, double scale);
|
||||
void setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform);
|
||||
|
||||
std::string explicitConfigPath;
|
||||
|
||||
@@ -207,6 +216,7 @@ class CCompositor {
|
||||
void initAllSignals();
|
||||
void setRandomSplash();
|
||||
void initManagers(eManagersInitStage stage);
|
||||
void prepareFallbackOutput();
|
||||
|
||||
uint64_t m_iHyprlandPID = 0;
|
||||
};
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "helpers/Vector2D.hpp"
|
||||
|
||||
enum eIcons
|
||||
{
|
||||
ICON_WARNING = 0,
|
||||
@@ -22,4 +24,26 @@ enum eRenderStage
|
||||
RENDER_POST_MIRROR, /* After rendering a mirror */
|
||||
RENDER_PRE_WINDOW, /* Before rendering a window (any pass) Note some windows (e.g. tiled) may have 2 passes (main & popup) */
|
||||
RENDER_POST_WINDOW, /* After rendering a window (any pass) */
|
||||
};
|
||||
|
||||
struct SCallbackInfo {
|
||||
bool cancelled = false; /* on cancellable events, will cancel the event. */
|
||||
};
|
||||
|
||||
struct SWindowDecorationExtents {
|
||||
Vector2D topLeft;
|
||||
Vector2D bottomRight;
|
||||
|
||||
//
|
||||
SWindowDecorationExtents operator*(const double& scale) const {
|
||||
return SWindowDecorationExtents{topLeft * scale, bottomRight * scale};
|
||||
}
|
||||
|
||||
SWindowDecorationExtents round() {
|
||||
return {topLeft.round(), bottomRight.round()};
|
||||
}
|
||||
|
||||
bool operator==(const SWindowDecorationExtents& other) const {
|
||||
return topLeft == other.topLeft && bottomRight == other.bottomRight;
|
||||
}
|
||||
};
|
185
src/Window.cpp
185
src/Window.cpp
@@ -13,7 +13,7 @@ CWindow::CWindow() {
|
||||
m_cRealShadowColor.create(AVARTYPE_COLOR, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), (void*)this, AVARDAMAGE_SHADOW);
|
||||
m_fDimPercent.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), (void*)this, AVARDAMAGE_ENTIRE);
|
||||
|
||||
m_dWindowDecorations.emplace_back(std::make_unique<CHyprDropShadowDecoration>(this)); // put the shadow so it's the first deco (has to be rendered first)
|
||||
addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(this));
|
||||
}
|
||||
|
||||
CWindow::~CWindow() {
|
||||
@@ -37,30 +37,27 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() {
|
||||
|
||||
SWindowDecorationExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}};
|
||||
|
||||
for (auto& wd : m_dWindowDecorations) {
|
||||
const auto EXTENTS = g_pDecorationPositioner->getWindowDecorationExtents(this);
|
||||
|
||||
const auto EXTENTS = wd->getWindowDecorationExtents();
|
||||
if (EXTENTS.topLeft.x > maxExtents.topLeft.x)
|
||||
maxExtents.topLeft.x = EXTENTS.topLeft.x;
|
||||
|
||||
if (EXTENTS.topLeft.x > maxExtents.topLeft.x)
|
||||
maxExtents.topLeft.x = EXTENTS.topLeft.x;
|
||||
if (EXTENTS.topLeft.y > maxExtents.topLeft.y)
|
||||
maxExtents.topLeft.y = EXTENTS.topLeft.y;
|
||||
|
||||
if (EXTENTS.topLeft.y > maxExtents.topLeft.y)
|
||||
maxExtents.topLeft.y = EXTENTS.topLeft.y;
|
||||
if (EXTENTS.bottomRight.x > maxExtents.bottomRight.x)
|
||||
maxExtents.bottomRight.x = EXTENTS.bottomRight.x;
|
||||
|
||||
if (EXTENTS.bottomRight.x > maxExtents.bottomRight.x)
|
||||
maxExtents.bottomRight.x = EXTENTS.bottomRight.x;
|
||||
|
||||
if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y)
|
||||
maxExtents.bottomRight.y = EXTENTS.bottomRight.y;
|
||||
}
|
||||
if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y)
|
||||
maxExtents.bottomRight.y = EXTENTS.bottomRight.y;
|
||||
|
||||
if (m_pWLSurface.exists() && !m_bIsX11) {
|
||||
wlr_box surfaceExtents = {0, 0, 0, 0};
|
||||
CBox surfaceExtents = {0, 0, 0, 0};
|
||||
// TODO: this could be better, perhaps make a getFullWindowRegion?
|
||||
wlr_xdg_surface_for_each_popup_surface(
|
||||
m_uSurface.xdg,
|
||||
[](wlr_surface* surf, int sx, int sy, void* data) {
|
||||
wlr_box* pSurfaceExtents = (wlr_box*)data;
|
||||
CBox* pSurfaceExtents = (CBox*)data;
|
||||
if (sx < pSurfaceExtents->x)
|
||||
pSurfaceExtents->x = sx;
|
||||
if (sy < pSurfaceExtents->y)
|
||||
@@ -88,21 +85,21 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() {
|
||||
return maxExtents;
|
||||
}
|
||||
|
||||
wlr_box CWindow::getFullWindowBoundingBox() {
|
||||
CBox CWindow::getFullWindowBoundingBox() {
|
||||
if (m_sAdditionalConfigData.dimAround) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||
}
|
||||
|
||||
auto maxExtents = getFullWindowExtents();
|
||||
auto maxExtents = getFullWindowExtents();
|
||||
|
||||
wlr_box finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y,
|
||||
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
||||
CBox finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y,
|
||||
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
||||
|
||||
return finalBox;
|
||||
}
|
||||
|
||||
wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
||||
CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
|
||||
@@ -113,7 +110,7 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
||||
POS = PMONITOR->vecPosition;
|
||||
SIZE = PMONITOR->vecSize;
|
||||
|
||||
return wlr_box{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
||||
return CBox{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
||||
}
|
||||
|
||||
if (DELTALESSTHAN(POS.y - PMONITOR->vecPosition.y, PMONITOR->vecReservedTopLeft.y, 1)) {
|
||||
@@ -131,10 +128,10 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
||||
SIZE.y += PMONITOR->vecReservedBottomRight.y;
|
||||
}
|
||||
|
||||
return wlr_box{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
||||
return CBox{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
||||
}
|
||||
|
||||
wlr_box CWindow::getWindowInputBox() {
|
||||
CBox CWindow::getWindowInputBox() {
|
||||
const int BORDERSIZE = getRealBorderSize();
|
||||
|
||||
if (m_sAdditionalConfigData.dimAround) {
|
||||
@@ -144,58 +141,45 @@ wlr_box CWindow::getWindowInputBox() {
|
||||
|
||||
SWindowDecorationExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}};
|
||||
|
||||
for (auto& wd : m_dWindowDecorations) {
|
||||
const auto EXTENTS = g_pDecorationPositioner->getWindowDecorationExtents(this, true);
|
||||
|
||||
if (!wd->allowsInput())
|
||||
continue;
|
||||
if (EXTENTS.topLeft.x > maxExtents.topLeft.x)
|
||||
maxExtents.topLeft.x = EXTENTS.topLeft.x;
|
||||
|
||||
const auto EXTENTS = wd->getWindowDecorationExtents();
|
||||
if (EXTENTS.topLeft.y > maxExtents.topLeft.y)
|
||||
maxExtents.topLeft.y = EXTENTS.topLeft.y;
|
||||
|
||||
if (EXTENTS.topLeft.x > maxExtents.topLeft.x)
|
||||
maxExtents.topLeft.x = EXTENTS.topLeft.x;
|
||||
if (EXTENTS.bottomRight.x > maxExtents.bottomRight.x)
|
||||
maxExtents.bottomRight.x = EXTENTS.bottomRight.x;
|
||||
|
||||
if (EXTENTS.topLeft.y > maxExtents.topLeft.y)
|
||||
maxExtents.topLeft.y = EXTENTS.topLeft.y;
|
||||
|
||||
if (EXTENTS.bottomRight.x > maxExtents.bottomRight.x)
|
||||
maxExtents.bottomRight.x = EXTENTS.bottomRight.x;
|
||||
|
||||
if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y)
|
||||
maxExtents.bottomRight.y = EXTENTS.bottomRight.y;
|
||||
}
|
||||
if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y)
|
||||
maxExtents.bottomRight.y = EXTENTS.bottomRight.y;
|
||||
|
||||
// Add extents to the real base BB and return
|
||||
wlr_box finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y,
|
||||
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
||||
CBox finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y,
|
||||
m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
||||
|
||||
return finalBox;
|
||||
}
|
||||
|
||||
CBox CWindow::getWindowMainSurfaceBox() {
|
||||
return {m_vRealPosition.vec().x, m_vRealPosition.vec().y, m_vRealSize.vec().x, m_vRealSize.vec().y};
|
||||
}
|
||||
|
||||
SWindowDecorationExtents CWindow::getFullWindowReservedArea() {
|
||||
SWindowDecorationExtents extents;
|
||||
|
||||
for (auto& wd : m_dWindowDecorations) {
|
||||
const auto RESERVED = wd->getWindowDecorationReservedArea();
|
||||
|
||||
if (RESERVED.bottomRight == Vector2D{} && RESERVED.topLeft == Vector2D{})
|
||||
continue;
|
||||
|
||||
extents.topLeft = extents.topLeft + RESERVED.topLeft;
|
||||
extents.bottomRight = extents.bottomRight + RESERVED.bottomRight;
|
||||
}
|
||||
|
||||
return extents;
|
||||
return g_pDecorationPositioner->getWindowDecorationReserved(this);
|
||||
}
|
||||
|
||||
void CWindow::updateWindowDecos() {
|
||||
for (auto& wd : m_dWindowDecorations)
|
||||
wd->updateWindow(this);
|
||||
|
||||
bool recalc = false;
|
||||
|
||||
if (!m_bIsMapped || isHidden())
|
||||
return;
|
||||
|
||||
for (auto& wd : m_vDecosToRemove) {
|
||||
for (auto it = m_dWindowDecorations.begin(); it != m_dWindowDecorations.end(); it++) {
|
||||
if (it->get() == wd) {
|
||||
g_pDecorationPositioner->uncacheDecoration(it->get());
|
||||
it = m_dWindowDecorations.erase(it);
|
||||
recalc = true;
|
||||
if (it == m_dWindowDecorations.end())
|
||||
@@ -204,10 +188,26 @@ void CWindow::updateWindowDecos() {
|
||||
}
|
||||
}
|
||||
|
||||
g_pDecorationPositioner->onWindowUpdate(this);
|
||||
|
||||
if (recalc)
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(this);
|
||||
|
||||
m_vDecosToRemove.clear();
|
||||
|
||||
for (auto& wd : m_dWindowDecorations) {
|
||||
wd->updateWindow(this);
|
||||
}
|
||||
}
|
||||
|
||||
void CWindow::addWindowDeco(std::unique_ptr<IHyprWindowDecoration> deco) {
|
||||
m_dWindowDecorations.emplace_back(std::move(deco));
|
||||
updateWindowDecos();
|
||||
}
|
||||
|
||||
void CWindow::removeWindowDeco(IHyprWindowDecoration* deco) {
|
||||
m_vDecosToRemove.push_back(deco);
|
||||
updateWindowDecos();
|
||||
}
|
||||
|
||||
pid_t CWindow::getPID() {
|
||||
@@ -219,6 +219,9 @@ pid_t CWindow::getPID() {
|
||||
|
||||
wl_client_get_credentials(wl_resource_get_client(m_uSurface.xdg->resource), &PID, nullptr, nullptr);
|
||||
} else {
|
||||
if (!m_bIsMapped || !m_bMappedX11)
|
||||
return -1;
|
||||
|
||||
PID = m_uSurface.xwayland->pid;
|
||||
}
|
||||
|
||||
@@ -325,7 +328,8 @@ void CWindow::updateSurfaceOutputs() {
|
||||
m_pWLSurface.wlr(),
|
||||
[](wlr_surface* surf, int x, int y, void* data) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(((CWindow*)data)->m_iMonitorID);
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(surf, PMONITOR ? PMONITOR->scale : 1.f);
|
||||
g_pCompositor->setPreferredScaleForSurface(surf, PMONITOR ? PMONITOR->scale : 1.f);
|
||||
g_pCompositor->setPreferredTransformForSurface(surf, PMONITOR->transform);
|
||||
},
|
||||
this);
|
||||
}
|
||||
@@ -334,6 +338,10 @@ void CWindow::moveToWorkspace(int workspaceID) {
|
||||
if (m_iWorkspaceID == workspaceID)
|
||||
return;
|
||||
|
||||
static auto* const PCLOSEONLASTSPECIAL = &g_pConfigManager->getConfigValuePtr("misc:close_special_on_empty")->intValue;
|
||||
|
||||
const int OLDWORKSPACE = m_iWorkspaceID;
|
||||
|
||||
m_iWorkspaceID = workspaceID;
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
|
||||
@@ -352,6 +360,15 @@ void CWindow::moveToWorkspace(int workspaceID) {
|
||||
|
||||
// update xwayland coords
|
||||
g_pXWaylandManager->setWindowSize(this, m_vRealSize.vec());
|
||||
|
||||
if (g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE) && g_pCompositor->getWindowsOnWorkspace(OLDWORKSPACE) == 0 && *PCLOSEONLASTSPECIAL) {
|
||||
const auto PWS = g_pCompositor->getWorkspaceByID(OLDWORKSPACE);
|
||||
|
||||
if (PWS) {
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWS->m_iMonitorID); PMONITOR)
|
||||
PMONITOR->setSpecialWorkspace(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CWindow* CWindow::X11TransientFor() {
|
||||
@@ -414,11 +431,17 @@ void CWindow::onUnmap() {
|
||||
if (PMONITOR && PMONITOR->specialWorkspaceID == m_iWorkspaceID)
|
||||
PMONITOR->setSpecialWorkspace(nullptr);
|
||||
}
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
|
||||
if (PMONITOR && PMONITOR->solitaryClient == this)
|
||||
PMONITOR->solitaryClient = nullptr;
|
||||
}
|
||||
|
||||
void CWindow::onMap() {
|
||||
|
||||
m_pWLSurface.assign(g_pXWaylandManager->getWindowSurface(this));
|
||||
m_pWLSurface.m_pOwner = this;
|
||||
|
||||
// JIC, reset the callbacks. If any are set, we'll make sure they are cleared so we don't accidentally unset them. (In case a window got remapped)
|
||||
m_vRealPosition.resetAllCallbacks();
|
||||
@@ -448,6 +471,8 @@ void CWindow::onMap() {
|
||||
|
||||
hyprListener_unmapWindow.initCallback(m_bIsX11 ? &m_uSurface.xwayland->surface->events.unmap : &m_uSurface.xdg->surface->events.unmap, &Events::listener_unmapWindow, this,
|
||||
"CWindow");
|
||||
|
||||
m_vReportedSize = m_vPendingReportedSize;
|
||||
}
|
||||
|
||||
void CWindow::onBorderAngleAnimEnd(void* ptr) {
|
||||
@@ -492,15 +517,19 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
} else if (r.szRule == "opaque") {
|
||||
if (!m_sAdditionalConfigData.forceOpaqueOverridden)
|
||||
m_sAdditionalConfigData.forceOpaque = true;
|
||||
} else if (r.szRule.find("rounding") == 0) {
|
||||
} else if (r.szRule == "immediate") {
|
||||
m_sAdditionalConfigData.forceTearing = true;
|
||||
} else if (r.szRule == "nearestneighbor") {
|
||||
m_sAdditionalConfigData.nearestNeighbor = true;
|
||||
} else if (r.szRule.starts_with("rounding")) {
|
||||
try {
|
||||
m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Rounding rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
||||
} else if (r.szRule.find("bordersize") == 0) {
|
||||
} else if (r.szRule.starts_with("bordersize")) {
|
||||
try {
|
||||
m_sAdditionalConfigData.borderSize = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Bordersize rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
||||
} else if (r.szRule.find("opacity") == 0) {
|
||||
} else if (r.szRule.starts_with("opacity")) {
|
||||
try {
|
||||
CVarList vars(r.szRule, 0, ' ');
|
||||
|
||||
@@ -533,10 +562,10 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Opacity rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
||||
} else if (r.szRule == "noanim") {
|
||||
m_sAdditionalConfigData.forceNoAnims = true;
|
||||
} else if (r.szRule.find("animation") == 0) {
|
||||
} else if (r.szRule.starts_with("animation")) {
|
||||
auto STYLE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
||||
m_sAdditionalConfigData.animationStyle = STYLE;
|
||||
} else if (r.szRule.find("bordercolor") == 0) {
|
||||
} else if (r.szRule.starts_with("bordercolor")) {
|
||||
try {
|
||||
std::string colorPart = removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find_first_of(' ') + 1));
|
||||
|
||||
@@ -552,7 +581,7 @@ void CWindow::applyDynamicRule(const SWindowRule& r) {
|
||||
m_sAdditionalConfigData.dimAround = true;
|
||||
} else if (r.szRule == "keepaspectratio") {
|
||||
m_sAdditionalConfigData.keepAspectRatio = true;
|
||||
} else if (r.szRule.find("xray") == 0) {
|
||||
} else if (r.szRule.starts_with("xray")) {
|
||||
CVarList vars(r.szRule, 0, ' ');
|
||||
|
||||
try {
|
||||
@@ -580,6 +609,8 @@ void CWindow::updateDynamicRules() {
|
||||
m_sAdditionalConfigData.borderSize = -1;
|
||||
m_sAdditionalConfigData.keepAspectRatio = false;
|
||||
m_sAdditionalConfigData.xray = -1;
|
||||
m_sAdditionalConfigData.forceTearing = false;
|
||||
m_sAdditionalConfigData.nearestNeighbor = false;
|
||||
|
||||
const auto WINDOWRULES = g_pConfigManager->getMatchingRules(this);
|
||||
for (auto& r : WINDOWRULES) {
|
||||
@@ -622,9 +653,9 @@ bool CWindow::isInCurvedCorner(double x, double y) {
|
||||
void findExtensionForVector2D(wlr_surface* surface, int x, int y, void* data) {
|
||||
const auto DATA = (SExtensionFindingData*)data;
|
||||
|
||||
wlr_box box = {DATA->origin.x + x, DATA->origin.y + y, surface->current.width, surface->current.height};
|
||||
CBox box = {DATA->origin.x + x, DATA->origin.y + y, surface->current.width, surface->current.height};
|
||||
|
||||
if (wlr_box_contains_point(&box, DATA->vec.x, DATA->vec.y))
|
||||
if (box.containsPoint(DATA->vec))
|
||||
*DATA->found = surface;
|
||||
}
|
||||
|
||||
@@ -654,14 +685,14 @@ void CWindow::createGroup() {
|
||||
Debug::log(LOG, "createGroup: window:{:x},title:{} is denied as a group, ignored", (uintptr_t)this, this->m_szTitle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_sGroupData.pNextWindow) {
|
||||
m_sGroupData.pNextWindow = this;
|
||||
m_sGroupData.head = true;
|
||||
m_sGroupData.locked = false;
|
||||
m_sGroupData.deny = false;
|
||||
|
||||
m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(this));
|
||||
updateWindowDecos();
|
||||
addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(this));
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(this);
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
@@ -735,6 +766,15 @@ int CWindow::getGroupSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
bool CWindow::canBeGroupedInto(CWindow* pWindow) {
|
||||
return !g_pKeybindManager->m_bGroupsLocked // global group lock disengaged
|
||||
&& ((m_eGroupRules & GROUP_INVADE && m_bFirstMap) // window ignore local group locks, or
|
||||
|| (!pWindow->getGroupHead()->m_sGroupData.locked // target unlocked
|
||||
&& !(m_sGroupData.pNextWindow && getGroupHead()->m_sGroupData.locked))) // source unlocked or isn't group
|
||||
&& !m_sGroupData.deny // source is not denied entry
|
||||
&& !(m_eGroupRules & GROUP_BARRED && m_bFirstMap); // group rule doesn't prevent adding window
|
||||
}
|
||||
|
||||
CWindow* CWindow::getGroupWindowByIndex(int index) {
|
||||
const int SIZE = getGroupSize();
|
||||
index = ((index % SIZE) + SIZE) % SIZE;
|
||||
@@ -791,6 +831,8 @@ void CWindow::setGroupCurrent(CWindow* pWindow) {
|
||||
g_pCompositor->setWindowFullscreen(pWindow, true, WORKSPACE->m_efFullscreenMode);
|
||||
|
||||
g_pHyprRenderer->damageWindow(pWindow);
|
||||
|
||||
pWindow->updateWindowDecos();
|
||||
}
|
||||
|
||||
void CWindow::insertWindowToGroup(CWindow* pWindow) {
|
||||
@@ -798,7 +840,7 @@ void CWindow::insertWindowToGroup(CWindow* pWindow) {
|
||||
const auto ENDAT = m_sGroupData.pNextWindow;
|
||||
|
||||
if (!pWindow->getDecorationByType(DECORATION_GROUPBAR))
|
||||
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
pWindow->addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
|
||||
if (!pWindow->m_sGroupData.pNextWindow) {
|
||||
BEGINAT->m_sGroupData.pNextWindow = pWindow;
|
||||
@@ -874,6 +916,9 @@ bool CWindow::opaque() {
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID);
|
||||
|
||||
if (m_pWLSurface.small() && !m_pWLSurface.m_bFillIgnoreSmall)
|
||||
return false;
|
||||
|
||||
if (PWORKSPACE->m_fAlpha.fl() != 1.f)
|
||||
return false;
|
||||
|
||||
@@ -925,3 +970,7 @@ int CWindow::getRealBorderSize() {
|
||||
|
||||
return g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
}
|
||||
|
||||
bool CWindow::canBeTorn() {
|
||||
return (m_sAdditionalConfigData.forceTearing.toUnderlying() || m_bTearingHint) && g_pHyprRenderer->m_bTearingEnvSatisfied;
|
||||
}
|
||||
|
@@ -11,14 +11,16 @@
|
||||
#include "macros.hpp"
|
||||
#include "managers/XWaylandManager.hpp"
|
||||
|
||||
enum eIdleInhibitMode {
|
||||
enum eIdleInhibitMode
|
||||
{
|
||||
IDLEINHIBIT_NONE = 0,
|
||||
IDLEINHIBIT_ALWAYS,
|
||||
IDLEINHIBIT_FULLSCREEN,
|
||||
IDLEINHIBIT_FOCUS
|
||||
};
|
||||
|
||||
enum eGroupRules {
|
||||
enum eGroupRules
|
||||
{
|
||||
// effective only during first map, except for _ALWAYS variant
|
||||
GROUP_NONE = 0,
|
||||
GROUP_SET = 1 << 0, // Open as new group or add to focused group
|
||||
@@ -30,6 +32,8 @@ enum eGroupRules {
|
||||
GROUP_OVERRIDE = 1 << 6, // Override other rules
|
||||
};
|
||||
|
||||
class IWindowTransformer;
|
||||
|
||||
template <typename T>
|
||||
class CWindowOverridableVar {
|
||||
public:
|
||||
@@ -138,6 +142,8 @@ struct SWindowAdditionalConfigData {
|
||||
CWindowOverridableVar<bool> keepAspectRatio = false;
|
||||
CWindowOverridableVar<int> xray = -1; // -1 means unset, takes precedence over the renderdata one
|
||||
CWindowOverridableVar<int> borderSize = -1; // -1 means unset, takes precedence over the renderdata one
|
||||
CWindowOverridableVar<bool> forceTearing = false;
|
||||
CWindowOverridableVar<bool> nearestNeighbor = false;
|
||||
};
|
||||
|
||||
struct SWindowRule {
|
||||
@@ -179,6 +185,7 @@ class CWindow {
|
||||
DYNLISTENER(setOverrideRedirect);
|
||||
DYNLISTENER(associateX11);
|
||||
DYNLISTENER(dissociateX11);
|
||||
DYNLISTENER(ackConfigure);
|
||||
// DYNLISTENER(newSubsurfaceWindow);
|
||||
|
||||
CWLSurface m_pWLSurface;
|
||||
@@ -198,8 +205,11 @@ class CWindow {
|
||||
CAnimatedVariable m_vRealSize;
|
||||
|
||||
// for not spamming the protocols
|
||||
Vector2D m_vReportedPosition;
|
||||
Vector2D m_vReportedSize;
|
||||
Vector2D m_vReportedPosition;
|
||||
Vector2D m_vReportedSize;
|
||||
Vector2D m_vPendingReportedSize;
|
||||
std::optional<std::pair<uint32_t, Vector2D>> m_pPendingSizeAck;
|
||||
std::vector<std::pair<uint32_t, Vector2D>> m_vPendingSizeAcks;
|
||||
|
||||
// for restoring floating statuses
|
||||
Vector2D m_vLastFloatingSize;
|
||||
@@ -286,6 +296,9 @@ class CWindow {
|
||||
SWindowSpecialRenderData m_sSpecialRenderData;
|
||||
SWindowAdditionalConfigData m_sAdditionalConfigData;
|
||||
|
||||
// Transformers
|
||||
std::vector<std::unique_ptr<IWindowTransformer>> m_vTransformers;
|
||||
|
||||
// for alpha
|
||||
CAnimatedVariable m_fActiveInactiveAlpha;
|
||||
|
||||
@@ -317,6 +330,8 @@ class CWindow {
|
||||
} m_sGroupData;
|
||||
uint16_t m_eGroupRules = GROUP_NONE;
|
||||
|
||||
bool m_bTearingHint = false;
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const CWindow& rhs) {
|
||||
return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize &&
|
||||
@@ -324,11 +339,14 @@ class CWindow {
|
||||
}
|
||||
|
||||
// methods
|
||||
wlr_box getFullWindowBoundingBox();
|
||||
CBox getFullWindowBoundingBox();
|
||||
SWindowDecorationExtents getFullWindowExtents();
|
||||
wlr_box getWindowInputBox();
|
||||
wlr_box getWindowIdealBoundingBoxIgnoreReserved();
|
||||
CBox getWindowInputBox();
|
||||
CBox getWindowMainSurfaceBox();
|
||||
CBox getWindowIdealBoundingBoxIgnoreReserved();
|
||||
void addWindowDeco(std::unique_ptr<IHyprWindowDecoration> deco);
|
||||
void updateWindowDecos();
|
||||
void removeWindowDeco(IHyprWindowDecoration* deco);
|
||||
pid_t getPID();
|
||||
IHyprWindowDecoration* getDecorationByType(eDecorationType);
|
||||
void removeDecorationByType(eDecorationType);
|
||||
@@ -348,6 +366,7 @@ class CWindow {
|
||||
Vector2D middle();
|
||||
bool opaque();
|
||||
float rounding();
|
||||
bool canBeTorn();
|
||||
|
||||
int getRealBorderSize();
|
||||
void updateSpecialRenderData();
|
||||
@@ -365,6 +384,7 @@ class CWindow {
|
||||
CWindow* getGroupPrevious();
|
||||
CWindow* getGroupWindowByIndex(int);
|
||||
int getGroupSize();
|
||||
bool canBeGroupedInto(CWindow* pWindow);
|
||||
void setGroupCurrent(CWindow* pWindow);
|
||||
void insertWindowToGroup(CWindow* pWindow);
|
||||
void updateGroupOutputs();
|
||||
@@ -414,4 +434,4 @@ struct std::formatter<CWindow*, CharT> : std::formatter<CharT> {
|
||||
std::format_to(out, ", class: {}", g_pXWaylandManager->getAppIDClass(w));
|
||||
return std::format_to(out, "]");
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#include "../managers/KeybindManager.hpp"
|
||||
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
@@ -15,14 +16,20 @@
|
||||
extern "C" char** environ;
|
||||
|
||||
CConfigManager::CConfigManager() {
|
||||
configValues["general:col.active_border"].data = std::make_shared<CGradientValueData>(0xffffffff);
|
||||
configValues["general:col.inactive_border"].data = std::make_shared<CGradientValueData>(0xff444444);
|
||||
configValues["general:col.nogroup_border"].data = std::make_shared<CGradientValueData>(0xffffaaff);
|
||||
configValues["general:col.nogroup_border_active"].data = std::make_shared<CGradientValueData>(0xffff00ff);
|
||||
configValues["general:col.group_border"].data = std::make_shared<CGradientValueData>(0x66777700);
|
||||
configValues["general:col.group_border_active"].data = std::make_shared<CGradientValueData>(0x66ffff00);
|
||||
configValues["general:col.group_border_locked"].data = std::make_shared<CGradientValueData>(0x66775500);
|
||||
configValues["general:col.group_border_locked_active"].data = std::make_shared<CGradientValueData>(0x66ff5500);
|
||||
configValues["general:col.active_border"].data = std::make_shared<CGradientValueData>(0xffffffff);
|
||||
configValues["general:col.inactive_border"].data = std::make_shared<CGradientValueData>(0xff444444);
|
||||
configValues["general:col.nogroup_border"].data = std::make_shared<CGradientValueData>(0xffffaaff);
|
||||
configValues["general:col.nogroup_border_active"].data = std::make_shared<CGradientValueData>(0xffff00ff);
|
||||
|
||||
configValues["group:col.border_active"].data = std::make_shared<CGradientValueData>(0x66ffff00);
|
||||
configValues["group:col.border_inactive"].data = std::make_shared<CGradientValueData>(0x66777700);
|
||||
configValues["group:col.border_locked_active"].data = std::make_shared<CGradientValueData>(0x66ff5500);
|
||||
configValues["group:col.border_locked_inactive"].data = std::make_shared<CGradientValueData>(0x66775500);
|
||||
|
||||
configValues["group:groupbar:col.active"].data = std::make_shared<CGradientValueData>(0x66ffff00);
|
||||
configValues["group:groupbar:col.inactive"].data = std::make_shared<CGradientValueData>(0x66777700);
|
||||
configValues["group:groupbar:col.locked_active"].data = std::make_shared<CGradientValueData>(0x66ff5500);
|
||||
configValues["group:groupbar:col.locked_inactive"].data = std::make_shared<CGradientValueData>(0x66775500);
|
||||
|
||||
setDefaultVars();
|
||||
setDefaultAnimationVars();
|
||||
@@ -76,10 +83,6 @@ void CConfigManager::setDefaultVars() {
|
||||
((CGradientValueData*)configValues["general:col.inactive_border"].data.get())->reset(0xff444444);
|
||||
((CGradientValueData*)configValues["general:col.nogroup_border"].data.get())->reset(0xff444444);
|
||||
((CGradientValueData*)configValues["general:col.nogroup_border_active"].data.get())->reset(0xffff00ff);
|
||||
((CGradientValueData*)configValues["general:col.group_border"].data.get())->reset(0x66777700);
|
||||
((CGradientValueData*)configValues["general:col.group_border_active"].data.get())->reset(0x66ffff00);
|
||||
((CGradientValueData*)configValues["general:col.group_border_locked"].data.get())->reset(0x66775500);
|
||||
((CGradientValueData*)configValues["general:col.group_border_locked_active"].data.get())->reset(0x66ff5500);
|
||||
configValues["general:cursor_inactive_timeout"].intValue = 0;
|
||||
configValues["general:no_cursor_warps"].intValue = 0;
|
||||
configValues["general:no_focus_fallback"].intValue = 0;
|
||||
@@ -87,41 +90,56 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["general:extend_border_grab_area"].intValue = 15;
|
||||
configValues["general:hover_icon_on_border"].intValue = 1;
|
||||
configValues["general:layout"].strValue = "dwindle";
|
||||
configValues["general:allow_tearing"].intValue = 0;
|
||||
|
||||
configValues["misc:disable_hyprland_logo"].intValue = 0;
|
||||
configValues["misc:disable_splash_rendering"].intValue = 0;
|
||||
configValues["misc:disable_hypr_chan"].intValue = 0;
|
||||
configValues["misc:force_hypr_chan"].intValue = 0;
|
||||
configValues["misc:vfr"].intValue = 1;
|
||||
configValues["misc:vrr"].intValue = 0;
|
||||
configValues["misc:mouse_move_enables_dpms"].intValue = 0;
|
||||
configValues["misc:key_press_enables_dpms"].intValue = 0;
|
||||
configValues["misc:always_follow_on_dnd"].intValue = 1;
|
||||
configValues["misc:layers_hog_keyboard_focus"].intValue = 1;
|
||||
configValues["misc:animate_manual_resizes"].intValue = 0;
|
||||
configValues["misc:animate_mouse_windowdragging"].intValue = 0;
|
||||
configValues["misc:disable_autoreload"].intValue = 0;
|
||||
configValues["misc:enable_swallow"].intValue = 0;
|
||||
configValues["misc:swallow_regex"].strValue = STRVAL_EMPTY;
|
||||
configValues["misc:swallow_exception_regex"].strValue = STRVAL_EMPTY;
|
||||
configValues["misc:focus_on_activate"].intValue = 0;
|
||||
configValues["misc:no_direct_scanout"].intValue = 1;
|
||||
configValues["misc:hide_cursor_on_touch"].intValue = 1;
|
||||
configValues["misc:mouse_move_focuses_monitor"].intValue = 1;
|
||||
configValues["misc:render_ahead_of_time"].intValue = 0;
|
||||
configValues["misc:render_ahead_safezone"].intValue = 1;
|
||||
configValues["misc:cursor_zoom_factor"].floatValue = 1.f;
|
||||
configValues["misc:cursor_zoom_rigid"].intValue = 0;
|
||||
configValues["misc:allow_session_lock_restore"].intValue = 0;
|
||||
configValues["misc:groupbar_scrolling"].intValue = 1;
|
||||
configValues["misc:group_insert_after_current"].intValue = 1;
|
||||
configValues["misc:group_focus_removed_window"].intValue = 1;
|
||||
configValues["misc:render_titles_in_groupbar"].intValue = 1;
|
||||
configValues["misc:groupbar_titles_font_size"].intValue = 8;
|
||||
configValues["misc:groupbar_gradients"].intValue = 1;
|
||||
configValues["misc:close_special_on_empty"].intValue = 1;
|
||||
configValues["misc:groupbar_text_color"].intValue = 0xffffffff;
|
||||
configValues["misc:background_color"].intValue = 0xff111111;
|
||||
configValues["misc:disable_hyprland_logo"].intValue = 0;
|
||||
configValues["misc:disable_splash_rendering"].intValue = 0;
|
||||
configValues["misc:force_hypr_chan"].intValue = 0;
|
||||
configValues["misc:force_default_wallpaper"].intValue = -1;
|
||||
configValues["misc:vfr"].intValue = 1;
|
||||
configValues["misc:vrr"].intValue = 0;
|
||||
configValues["misc:mouse_move_enables_dpms"].intValue = 0;
|
||||
configValues["misc:key_press_enables_dpms"].intValue = 0;
|
||||
configValues["misc:always_follow_on_dnd"].intValue = 1;
|
||||
configValues["misc:layers_hog_keyboard_focus"].intValue = 1;
|
||||
configValues["misc:animate_manual_resizes"].intValue = 0;
|
||||
configValues["misc:animate_mouse_windowdragging"].intValue = 0;
|
||||
configValues["misc:disable_autoreload"].intValue = 0;
|
||||
configValues["misc:enable_swallow"].intValue = 0;
|
||||
configValues["misc:swallow_regex"].strValue = STRVAL_EMPTY;
|
||||
configValues["misc:swallow_exception_regex"].strValue = STRVAL_EMPTY;
|
||||
configValues["misc:focus_on_activate"].intValue = 0;
|
||||
configValues["misc:no_direct_scanout"].intValue = 1;
|
||||
configValues["misc:hide_cursor_on_touch"].intValue = 1;
|
||||
configValues["misc:mouse_move_focuses_monitor"].intValue = 1;
|
||||
configValues["misc:render_ahead_of_time"].intValue = 0;
|
||||
configValues["misc:render_ahead_safezone"].intValue = 1;
|
||||
configValues["misc:cursor_zoom_factor"].floatValue = 1.f;
|
||||
configValues["misc:cursor_zoom_rigid"].intValue = 0;
|
||||
configValues["misc:allow_session_lock_restore"].intValue = 0;
|
||||
configValues["misc:close_special_on_empty"].intValue = 1;
|
||||
configValues["misc:background_color"].intValue = 0xff111111;
|
||||
configValues["misc:new_window_takes_over_fullscreen"].intValue = 0;
|
||||
|
||||
((CGradientValueData*)configValues["group:col.border_active"].data.get())->reset(0x66ffff00);
|
||||
((CGradientValueData*)configValues["group:col.border_inactive"].data.get())->reset(0x66777700);
|
||||
((CGradientValueData*)configValues["group:col.border_locked_active"].data.get())->reset(0x66ff5500);
|
||||
((CGradientValueData*)configValues["group:col.border_locked_inactive"].data.get())->reset(0x66775500);
|
||||
|
||||
configValues["group:insert_after_current"].intValue = 1;
|
||||
configValues["group:focus_removed_window"].intValue = 1;
|
||||
|
||||
configValues["group:groupbar:font_family"].strValue = "Sans";
|
||||
configValues["group:groupbar:font_size"].intValue = 8;
|
||||
configValues["group:groupbar:gradients"].intValue = 1;
|
||||
configValues["group:groupbar:render_titles"].intValue = 1;
|
||||
configValues["group:groupbar:scrolling"].intValue = 1;
|
||||
configValues["group:groupbar:text_color"].intValue = 0xffffffff;
|
||||
|
||||
((CGradientValueData*)configValues["group:groupbar:col.active"].data.get())->reset(0x66ffff00);
|
||||
((CGradientValueData*)configValues["group:groupbar:col.inactive"].data.get())->reset(0x66777700);
|
||||
((CGradientValueData*)configValues["group:groupbar:col.locked_active"].data.get())->reset(0x66ff5500);
|
||||
((CGradientValueData*)configValues["group:groupbar:col.locked_inactive"].data.get())->reset(0x66775500);
|
||||
|
||||
configValues["debug:int"].intValue = 0;
|
||||
configValues["debug:log_damage"].intValue = 0;
|
||||
@@ -133,36 +151,38 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["debug:damage_tracking"].intValue = DAMAGE_TRACKING_FULL;
|
||||
configValues["debug:manual_crash"].intValue = 0;
|
||||
configValues["debug:suppress_errors"].intValue = 0;
|
||||
configValues["debug:watchdog_timeout"].intValue = 5;
|
||||
|
||||
configValues["decoration:rounding"].intValue = 0;
|
||||
configValues["decoration:blur:enabled"].intValue = 1;
|
||||
configValues["decoration:blur:size"].intValue = 8;
|
||||
configValues["decoration:blur:passes"].intValue = 1;
|
||||
configValues["decoration:blur:ignore_opacity"].intValue = 0;
|
||||
configValues["decoration:blur:new_optimizations"].intValue = 1;
|
||||
configValues["decoration:blur:xray"].intValue = 0;
|
||||
configValues["decoration:blur:noise"].floatValue = 0.0117;
|
||||
configValues["decoration:blur:contrast"].floatValue = 0.8916;
|
||||
configValues["decoration:blur:brightness"].floatValue = 0.8172;
|
||||
configValues["decoration:blur:special"].intValue = 0;
|
||||
configValues["decoration:active_opacity"].floatValue = 1;
|
||||
configValues["decoration:inactive_opacity"].floatValue = 1;
|
||||
configValues["decoration:fullscreen_opacity"].floatValue = 1;
|
||||
configValues["decoration:multisample_edges"].intValue = 1;
|
||||
configValues["decoration:no_blur_on_oversized"].intValue = 0;
|
||||
configValues["decoration:drop_shadow"].intValue = 1;
|
||||
configValues["decoration:shadow_range"].intValue = 4;
|
||||
configValues["decoration:shadow_render_power"].intValue = 3;
|
||||
configValues["decoration:shadow_ignore_window"].intValue = 1;
|
||||
configValues["decoration:shadow_offset"].vecValue = Vector2D();
|
||||
configValues["decoration:shadow_scale"].floatValue = 1.f;
|
||||
configValues["decoration:col.shadow"].intValue = 0xee1a1a1a;
|
||||
configValues["decoration:col.shadow_inactive"].intValue = INT_MAX;
|
||||
configValues["decoration:dim_inactive"].intValue = 0;
|
||||
configValues["decoration:dim_strength"].floatValue = 0.5f;
|
||||
configValues["decoration:dim_special"].floatValue = 0.2f;
|
||||
configValues["decoration:dim_around"].floatValue = 0.4f;
|
||||
configValues["decoration:screen_shader"].strValue = STRVAL_EMPTY;
|
||||
configValues["decoration:rounding"].intValue = 0;
|
||||
configValues["decoration:blur:enabled"].intValue = 1;
|
||||
configValues["decoration:blur:size"].intValue = 8;
|
||||
configValues["decoration:blur:passes"].intValue = 1;
|
||||
configValues["decoration:blur:ignore_opacity"].intValue = 0;
|
||||
configValues["decoration:blur:new_optimizations"].intValue = 1;
|
||||
configValues["decoration:blur:xray"].intValue = 0;
|
||||
configValues["decoration:blur:contrast"].floatValue = 0.8916;
|
||||
configValues["decoration:blur:brightness"].floatValue = 1.0;
|
||||
configValues["decoration:blur:vibrancy"].floatValue = 0.1696;
|
||||
configValues["decoration:blur:vibrancy_darkness"].floatValue = 0.0;
|
||||
configValues["decoration:blur:noise"].floatValue = 0.0117;
|
||||
configValues["decoration:blur:special"].intValue = 0;
|
||||
configValues["decoration:active_opacity"].floatValue = 1;
|
||||
configValues["decoration:inactive_opacity"].floatValue = 1;
|
||||
configValues["decoration:fullscreen_opacity"].floatValue = 1;
|
||||
configValues["decoration:no_blur_on_oversized"].intValue = 0;
|
||||
configValues["decoration:drop_shadow"].intValue = 1;
|
||||
configValues["decoration:shadow_range"].intValue = 4;
|
||||
configValues["decoration:shadow_render_power"].intValue = 3;
|
||||
configValues["decoration:shadow_ignore_window"].intValue = 1;
|
||||
configValues["decoration:shadow_offset"].vecValue = Vector2D();
|
||||
configValues["decoration:shadow_scale"].floatValue = 1.f;
|
||||
configValues["decoration:col.shadow"].intValue = 0xee1a1a1a;
|
||||
configValues["decoration:col.shadow_inactive"].intValue = INT_MAX;
|
||||
configValues["decoration:dim_inactive"].intValue = 0;
|
||||
configValues["decoration:dim_strength"].floatValue = 0.5f;
|
||||
configValues["decoration:dim_special"].floatValue = 0.2f;
|
||||
configValues["decoration:dim_around"].floatValue = 0.4f;
|
||||
configValues["decoration:screen_shader"].strValue = STRVAL_EMPTY;
|
||||
|
||||
configValues["dwindle:pseudotile"].intValue = 0;
|
||||
configValues["dwindle:force_split"].intValue = 0;
|
||||
@@ -186,6 +206,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["master:inherit_fullscreen"].intValue = 1;
|
||||
configValues["master:allow_small_split"].intValue = 0;
|
||||
configValues["master:smart_resizing"].intValue = 1;
|
||||
configValues["master:drop_at_cursor"].intValue = 1;
|
||||
|
||||
configValues["animations:enabled"].intValue = 1;
|
||||
|
||||
@@ -222,13 +243,17 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["input:touchdevice:output"].strValue = STRVAL_EMPTY;
|
||||
configValues["input:tablet:transform"].intValue = 0;
|
||||
configValues["input:tablet:output"].strValue = STRVAL_EMPTY;
|
||||
configValues["input:tablet:region_position"].vecValue = Vector2D();
|
||||
configValues["input:tablet:region_size"].vecValue = Vector2D();
|
||||
|
||||
configValues["binds:pass_mouse_when_bound"].intValue = 0;
|
||||
configValues["binds:scroll_event_delay"].intValue = 300;
|
||||
configValues["binds:workspace_back_and_forth"].intValue = 0;
|
||||
configValues["binds:allow_workspace_cycles"].intValue = 0;
|
||||
configValues["binds:focus_preferred_method"].intValue = 0;
|
||||
configValues["binds:ignore_group_lock"].intValue = 0;
|
||||
configValues["binds:pass_mouse_when_bound"].intValue = 0;
|
||||
configValues["binds:scroll_event_delay"].intValue = 300;
|
||||
configValues["binds:workspace_back_and_forth"].intValue = 0;
|
||||
configValues["binds:allow_workspace_cycles"].intValue = 0;
|
||||
configValues["binds:workspace_center_on"].intValue = 1;
|
||||
configValues["binds:focus_preferred_method"].intValue = 0;
|
||||
configValues["binds:ignore_group_lock"].intValue = 0;
|
||||
configValues["binds:movefocus_cycles_fullscreen"].intValue = 1;
|
||||
|
||||
configValues["gestures:workspace_swipe"].intValue = 0;
|
||||
configValues["gestures:workspace_swipe_fingers"].intValue = 3;
|
||||
@@ -277,7 +302,9 @@ void CConfigManager::setDeviceDefaultVars(const std::string& dev) {
|
||||
cfgValues["scroll_button_lock"].intValue = 0;
|
||||
cfgValues["transform"].intValue = 0;
|
||||
cfgValues["output"].strValue = STRVAL_EMPTY;
|
||||
cfgValues["enabled"].intValue = 1; // only for mice / touchpads
|
||||
cfgValues["enabled"].intValue = 1; // only for mice / touchpads
|
||||
cfgValues["region_position"].vecValue = Vector2D(); // only for tablets
|
||||
cfgValues["region_size"].vecValue = Vector2D(); // only for tablets
|
||||
}
|
||||
|
||||
void CConfigManager::setDefaultAnimationVars() {
|
||||
@@ -347,8 +374,8 @@ void CConfigManager::init() {
|
||||
}
|
||||
|
||||
void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::string& VALUE) {
|
||||
if (configValues.find(COMMAND) == configValues.end()) {
|
||||
if (COMMAND.find("device:") != 0 /* devices parsed later */ && COMMAND.find("plugin:") != 0 /* plugins parsed later */) {
|
||||
if (!configValues.contains(COMMAND)) {
|
||||
if (!COMMAND.starts_with("device:") /* devices parsed later */ && !COMMAND.starts_with("plugin:") /* plugins parsed later */) {
|
||||
if (COMMAND[0] == '$') {
|
||||
// register a dynamic var
|
||||
Debug::log(LOG, "Registered dynamic var \"{}\" -> {}", COMMAND, VALUE);
|
||||
@@ -365,7 +392,7 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
|
||||
|
||||
SConfigValue* CONFIGENTRY = nullptr;
|
||||
|
||||
if (COMMAND.find("device:") == 0) {
|
||||
if (COMMAND.starts_with("device:")) {
|
||||
const auto DEVICE = COMMAND.substr(7).substr(0, COMMAND.find_last_of(':') - 7);
|
||||
const auto CONFIGVAR = COMMAND.substr(COMMAND.find_last_of(':') + 1);
|
||||
|
||||
@@ -385,7 +412,7 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s
|
||||
}
|
||||
|
||||
CONFIGENTRY = &it->second.at(CONFIGVAR);
|
||||
} else if (COMMAND.find("plugin:") == 0) {
|
||||
} else if (COMMAND.starts_with("plugin:")) {
|
||||
for (auto& [handle, pMap] : pluginConfigs) {
|
||||
auto it = std::find_if(pMap->begin(), pMap->end(), [&](const auto& other) { return other.first == COMMAND; });
|
||||
if (it == pMap->end()) {
|
||||
@@ -623,11 +650,11 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
||||
return;
|
||||
}
|
||||
|
||||
if (ARGS[1].find("pref") == 0) {
|
||||
if (ARGS[1].starts_with("pref")) {
|
||||
newrule.resolution = Vector2D();
|
||||
} else if (ARGS[1].find("highrr") == 0) {
|
||||
} else if (ARGS[1].starts_with("highrr")) {
|
||||
newrule.resolution = Vector2D(-1, -1);
|
||||
} else if (ARGS[1].find("highres") == 0) {
|
||||
} else if (ARGS[1].starts_with("highres")) {
|
||||
newrule.resolution = Vector2D(-1, -2);
|
||||
} else if (parseModeLine(ARGS[1], newrule.drmMode)) {
|
||||
newrule.resolution = Vector2D(newrule.drmMode.hdisplay, newrule.drmMode.vdisplay);
|
||||
@@ -640,14 +667,14 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
||||
newrule.refreshRate = stof(ARGS[1].substr(ARGS[1].find_first_of('@') + 1));
|
||||
}
|
||||
|
||||
if (ARGS[2].find("auto") == 0) {
|
||||
if (ARGS[2].starts_with("auto")) {
|
||||
newrule.offset = Vector2D(-INT32_MAX, -INT32_MAX);
|
||||
} else {
|
||||
newrule.offset.x = stoi(ARGS[2].substr(0, ARGS[2].find_first_of('x')));
|
||||
newrule.offset.y = stoi(ARGS[2].substr(ARGS[2].find_first_of('x') + 1));
|
||||
}
|
||||
|
||||
if (ARGS[3].find("auto") == 0) {
|
||||
if (ARGS[3].starts_with("auto")) {
|
||||
newrule.scale = -1;
|
||||
} else {
|
||||
newrule.scale = stof(ARGS[3]);
|
||||
@@ -810,6 +837,7 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
bool mouse = false;
|
||||
bool nonConsuming = false;
|
||||
bool transparent = false;
|
||||
bool ignoreMods = false;
|
||||
const auto BINDARGS = command.substr(4);
|
||||
|
||||
for (auto& arg : BINDARGS) {
|
||||
@@ -825,6 +853,8 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
nonConsuming = true;
|
||||
} else if (arg == 't') {
|
||||
transparent = true;
|
||||
} else if (arg == 'i') {
|
||||
ignoreMods = true;
|
||||
} else {
|
||||
parseError = "bind: invalid flag";
|
||||
return;
|
||||
@@ -882,12 +912,13 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
|
||||
if (KEY != "") {
|
||||
if (isNumber(KEY) && std::stoi(KEY) > 9)
|
||||
g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent});
|
||||
else if (KEY.find("code:") == 0 && isNumber(KEY.substr(5)))
|
||||
g_pKeybindManager->addKeybind(
|
||||
SKeybind{"", std::stoi(KEY.substr(5)), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent});
|
||||
SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods});
|
||||
else if (KEY.starts_with("code:") && isNumber(KEY.substr(5)))
|
||||
g_pKeybindManager->addKeybind(
|
||||
SKeybind{"", std::stoi(KEY.substr(5)), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods});
|
||||
else
|
||||
g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent});
|
||||
g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -902,17 +933,17 @@ void CConfigManager::handleUnbind(const std::string& command, const std::string&
|
||||
}
|
||||
|
||||
bool windowRuleValid(const std::string& RULE) {
|
||||
return !(RULE != "float" && RULE != "tile" && RULE.find("opacity") != 0 && RULE.find("move") != 0 && RULE.find("size") != 0 && RULE.find("minsize") != 0 &&
|
||||
RULE.find("maxsize") != 0 && RULE.find("pseudo") != 0 && RULE.find("monitor") != 0 && RULE.find("idleinhibit") != 0 && RULE != "nofocus" && RULE != "noblur" &&
|
||||
RULE != "noshadow" && RULE != "nodim" && RULE != "noborder" && RULE != "opaque" && RULE != "forceinput" && RULE != "fullscreen" && RULE != "nofullscreenrequest" &&
|
||||
RULE != "nomaximizerequest" && RULE != "fakefullscreen" && RULE != "nomaxsize" && RULE != "pin" && RULE != "noanim" && RULE != "dimaround" && RULE != "windowdance" &&
|
||||
RULE != "maximize" && RULE != "keepaspectratio" && RULE.find("animation") != 0 && RULE.find("rounding") != 0 && RULE.find("workspace") != 0 &&
|
||||
RULE.find("bordercolor") != 0 && RULE != "forcergbx" && RULE != "noinitialfocus" && RULE != "stayfocused" && RULE.find("bordersize") != 0 && RULE.find("xray") != 0 &&
|
||||
RULE.find("center") != 0 && RULE.find("group") != 0);
|
||||
return RULE == "float" || RULE == "tile" || RULE.starts_with("opacity") || RULE.starts_with("move") || RULE.starts_with("size") || RULE.starts_with("minsize") ||
|
||||
RULE.starts_with("maxsize") || RULE.starts_with("pseudo") || RULE.starts_with("monitor") || RULE.starts_with("idleinhibit") || RULE == "nofocus" || RULE == "noblur" ||
|
||||
RULE == "noshadow" || RULE == "nodim" || RULE == "noborder" || RULE == "opaque" || RULE == "forceinput" || RULE == "fullscreen" || RULE == "nofullscreenrequest" ||
|
||||
RULE == "nomaximizerequest" || RULE == "fakefullscreen" || RULE == "nomaxsize" || RULE == "pin" || RULE == "noanim" || RULE == "dimaround" || RULE == "windowdance" ||
|
||||
RULE == "maximize" || RULE == "keepaspectratio" || RULE.starts_with("animation") || RULE.starts_with("rounding") || RULE.starts_with("workspace") ||
|
||||
RULE.starts_with("bordercolor") || RULE == "forcergbx" || RULE == "noinitialfocus" || RULE == "stayfocused" || RULE.starts_with("bordersize") || RULE.starts_with("xray") ||
|
||||
RULE.starts_with("center") || RULE.starts_with("group") || RULE == "immediate" || RULE == "nearestneighbor";
|
||||
}
|
||||
|
||||
bool layerRuleValid(const std::string& RULE) {
|
||||
return !(RULE != "noanim" && RULE != "blur" && RULE.find("ignorealpha") != 0 && RULE.find("ignorezero") != 0 && RULE.find("xray") != 0);
|
||||
return RULE == "noanim" || RULE == "blur" || RULE.starts_with("ignorealpha") || RULE.starts_with("ignorezero") || RULE.starts_with("xray");
|
||||
}
|
||||
|
||||
void CConfigManager::handleWindowRule(const std::string& command, const std::string& value) {
|
||||
@@ -936,7 +967,7 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str
|
||||
return;
|
||||
}
|
||||
|
||||
if (RULE.find("size") == 0 || RULE.find("maxsize") == 0 || RULE.find("minsize") == 0)
|
||||
if (RULE.starts_with("size") || RULE.starts_with("maxsize") || RULE.starts_with("minsize"))
|
||||
m_dWindowRules.push_front({RULE, VALUE});
|
||||
else
|
||||
m_dWindowRules.push_back({RULE, VALUE});
|
||||
@@ -970,7 +1001,7 @@ void CConfigManager::handleLayerRule(const std::string& command, const std::stri
|
||||
}
|
||||
|
||||
void CConfigManager::handleWindowRuleV2(const std::string& command, const std::string& value) {
|
||||
const auto RULE = value.substr(0, value.find_first_of(','));
|
||||
const auto RULE = removeBeginEndSpacesTabs(value.substr(0, value.find_first_of(',')));
|
||||
const auto VALUE = value.substr(value.find_first_of(',') + 1);
|
||||
|
||||
if (!windowRuleValid(RULE) && RULE != "unset") {
|
||||
@@ -1083,14 +1114,14 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s
|
||||
return;
|
||||
}
|
||||
|
||||
if (RULE.find("size") == 0 || RULE.find("maxsize") == 0 || RULE.find("minsize") == 0)
|
||||
if (RULE.starts_with("size") || RULE.starts_with("maxsize") || RULE.starts_with("minsize"))
|
||||
m_dWindowRules.push_front(rule);
|
||||
else
|
||||
m_dWindowRules.push_back(rule);
|
||||
}
|
||||
|
||||
void CConfigManager::updateBlurredLS(const std::string& name, const bool forceBlur) {
|
||||
const bool BYADDRESS = name.find("address:") == 0;
|
||||
const bool BYADDRESS = name.starts_with("address:");
|
||||
std::string matchName = name;
|
||||
|
||||
if (BYADDRESS) {
|
||||
@@ -1111,7 +1142,7 @@ void CConfigManager::updateBlurredLS(const std::string& name, const bool forceBl
|
||||
}
|
||||
|
||||
void CConfigManager::handleBlurLS(const std::string& command, const std::string& value) {
|
||||
if (value.find("remove,") == 0) {
|
||||
if (value.starts_with("remove,")) {
|
||||
const auto TOREMOVE = removeBeginEndSpacesTabs(value.substr(7));
|
||||
if (std::erase_if(m_dBlurLSNamespaces, [&](const auto& other) { return other == TOREMOVE; }))
|
||||
updateBlurredLS(TOREMOVE, false);
|
||||
@@ -1150,7 +1181,10 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std:
|
||||
rules = value.substr(WORKSPACE_DELIM + 1);
|
||||
}
|
||||
|
||||
auto assignRule = [&](std::string rule) {
|
||||
const static std::string ruleOnCreatedEmtpy = "on-created-empty:";
|
||||
const static int ruleOnCreatedEmtpyLen = ruleOnCreatedEmtpy.length();
|
||||
|
||||
auto assignRule = [&](std::string rule) {
|
||||
size_t delim = std::string::npos;
|
||||
if ((delim = rule.find("gapsin:")) != std::string::npos)
|
||||
wsRule.gapsIn = std::stoi(rule.substr(delim + 7));
|
||||
@@ -1170,6 +1204,10 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std:
|
||||
wsRule.monitor = rule.substr(delim + 8);
|
||||
else if ((delim = rule.find("default:")) != std::string::npos)
|
||||
wsRule.isDefault = configStringToInt(rule.substr(delim + 8));
|
||||
else if ((delim = rule.find("persistent:")) != std::string::npos)
|
||||
wsRule.isPersistent = configStringToInt(rule.substr(delim + 11));
|
||||
else if ((delim = rule.find(ruleOnCreatedEmtpy)) != std::string::npos)
|
||||
wsRule.onCreatedEmptyRunCmd = cleanCmdForWorkspace(name, rule.substr(delim + ruleOnCreatedEmtpyLen));
|
||||
};
|
||||
|
||||
size_t pos = 0;
|
||||
@@ -1239,6 +1277,8 @@ void CConfigManager::handleSource(const std::string& command, const std::string&
|
||||
std::string line = "";
|
||||
int linenum = 1;
|
||||
if (ifs.is_open()) {
|
||||
auto configCurrentPathBackup = configCurrentPath;
|
||||
|
||||
while (std::getline(ifs, line)) {
|
||||
// Read line by line.
|
||||
try {
|
||||
@@ -1251,7 +1291,7 @@ void CConfigManager::handleSource(const std::string& command, const std::string&
|
||||
parseError += "Config error at line " + std::to_string(linenum) + " (" + configCurrentPath + "): Line parsing error.";
|
||||
}
|
||||
|
||||
if (parseError != "" && parseError.find("Config error at line") != 0) {
|
||||
if (parseError != "" && !parseError.starts_with("Config error at line")) {
|
||||
parseError = "Config error at line " + std::to_string(linenum) + " (" + configCurrentPath + "): " + parseError;
|
||||
}
|
||||
|
||||
@@ -1259,6 +1299,8 @@ void CConfigManager::handleSource(const std::string& command, const std::string&
|
||||
}
|
||||
|
||||
ifs.close();
|
||||
|
||||
configCurrentPath = configCurrentPathBackup;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1322,7 +1364,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
|
||||
}
|
||||
} else if (COMMAND == "monitor")
|
||||
handleMonitor(COMMAND, VALUE);
|
||||
else if (COMMAND.find("bind") == 0)
|
||||
else if (COMMAND.starts_with("bind"))
|
||||
handleBind(COMMAND, VALUE);
|
||||
else if (COMMAND == "unbind")
|
||||
handleUnbind(COMMAND, VALUE);
|
||||
@@ -1346,13 +1388,20 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
|
||||
handleBlurLS(COMMAND, VALUE);
|
||||
else if (COMMAND == "wsbind")
|
||||
handleBindWS(COMMAND, VALUE);
|
||||
else if (COMMAND.find("env") == 0)
|
||||
handleEnv(COMMAND, VALUE);
|
||||
else if (COMMAND.find("plugin") == 0)
|
||||
else if (COMMAND == "plugin")
|
||||
handlePlugin(COMMAND, VALUE);
|
||||
else if (COMMAND.starts_with("env"))
|
||||
handleEnv(COMMAND, VALUE);
|
||||
else {
|
||||
configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE);
|
||||
needsLayoutRecalc = 2;
|
||||
// try config
|
||||
const auto IT = std::find_if(pluginKeywords.begin(), pluginKeywords.end(), [&](const auto& other) { return other.name == COMMAND; });
|
||||
|
||||
if (IT != pluginKeywords.end()) {
|
||||
IT->fn(COMMAND, VALUE);
|
||||
} else {
|
||||
configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE);
|
||||
needsLayoutRecalc = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (dynamic) {
|
||||
@@ -1361,7 +1410,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
|
||||
|
||||
// invalidate layouts if they changed
|
||||
if (needsLayoutRecalc) {
|
||||
if (needsLayoutRecalc == 1 || COMMAND.contains("gaps_") || COMMAND.find("dwindle:") == 0 || COMMAND.find("master:") == 0) {
|
||||
if (needsLayoutRecalc == 1 || COMMAND.contains("gaps_") || COMMAND.starts_with("dwindle:") || COMMAND.starts_with("master:")) {
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||
}
|
||||
@@ -1396,7 +1445,7 @@ void CConfigManager::applyUserDefinedVars(std::string& line, const size_t equals
|
||||
const auto STRAFTERDOLLAR = line.substr(dollarPlace + 1);
|
||||
bool found = false;
|
||||
for (auto& [var, value] : configDynamicVars) {
|
||||
if (STRAFTERDOLLAR.find(var) == 0) {
|
||||
if (STRAFTERDOLLAR.starts_with(var)) {
|
||||
line.replace(dollarPlace, var.length() + 1, value);
|
||||
found = true;
|
||||
break;
|
||||
@@ -1406,7 +1455,7 @@ void CConfigManager::applyUserDefinedVars(std::string& line, const size_t equals
|
||||
if (!found) {
|
||||
// maybe env?
|
||||
for (auto& [var, value] : environmentVariables) {
|
||||
if (STRAFTERDOLLAR.find(var) == 0) {
|
||||
if (STRAFTERDOLLAR.starts_with(var)) {
|
||||
line.replace(dollarPlace, var.length() + 1, value);
|
||||
break;
|
||||
}
|
||||
@@ -1486,6 +1535,8 @@ void CConfigManager::parseLine(std::string& line) {
|
||||
}
|
||||
|
||||
void CConfigManager::loadConfigLoadVars() {
|
||||
EMIT_HOOK_EVENT("preConfigReload", nullptr);
|
||||
|
||||
Debug::log(LOG, "Reloading the config!");
|
||||
parseError = ""; // reset the error
|
||||
currentCategory = ""; // reset the category
|
||||
@@ -1572,7 +1623,7 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
parseError += "Config error at line " + std::to_string(linenum) + " (" + mainConfigPath + "): Line parsing error.";
|
||||
}
|
||||
|
||||
if (parseError != "" && parseError.find("Config error at line") != 0) {
|
||||
if (parseError != "" && !parseError.starts_with("Config error at line")) {
|
||||
parseError = "Config error at line " + std::to_string(linenum) + " (" + mainConfigPath + "): " + parseError;
|
||||
}
|
||||
|
||||
@@ -1733,6 +1784,10 @@ float CConfigManager::getFloat(const std::string& v) {
|
||||
return getConfigValueSafe(v).floatValue;
|
||||
}
|
||||
|
||||
Vector2D CConfigManager::getVec(const std::string& v) {
|
||||
return getConfigValueSafe(v).vecValue;
|
||||
}
|
||||
|
||||
std::string CConfigManager::getString(const std::string& v) {
|
||||
auto VAL = getConfigValueSafe(v).strValue;
|
||||
|
||||
@@ -1750,6 +1805,10 @@ float CConfigManager::getDeviceFloat(const std::string& dev, const std::string&
|
||||
return getConfigValueSafeDevice(dev, v, fallback).floatValue;
|
||||
}
|
||||
|
||||
Vector2D CConfigManager::getDeviceVec(const std::string& dev, const std::string& v, const std::string& fallback) {
|
||||
return getConfigValueSafeDevice(dev, v, fallback).vecValue;
|
||||
}
|
||||
|
||||
std::string CConfigManager::getDeviceString(const std::string& dev, const std::string& v, const std::string& fallback) {
|
||||
auto VAL = getConfigValueSafeDevice(dev, v, fallback).strValue;
|
||||
|
||||
@@ -1767,6 +1826,10 @@ void CConfigManager::setFloat(const std::string& v, float val) {
|
||||
configValues[v].floatValue = val;
|
||||
}
|
||||
|
||||
void CConfigManager::setVec(const std::string& v, Vector2D val) {
|
||||
configValues[v].vecValue = val;
|
||||
}
|
||||
|
||||
void CConfigManager::setString(const std::string& v, const std::string& val) {
|
||||
configValues[v].strValue = val;
|
||||
}
|
||||
@@ -1776,7 +1839,7 @@ SMonitorRule CConfigManager::getMonitorRuleFor(const std::string& name, const st
|
||||
|
||||
for (auto& r : m_dMonitorRules) {
|
||||
if (r.name == name ||
|
||||
(r.name.find("desc:") == 0 &&
|
||||
(r.name.starts_with("desc:") &&
|
||||
(r.name.substr(5) == displayName || r.name.substr(5) == removeBeginEndSpacesTabs(displayName.substr(0, displayName.find_first_of('(')))))) {
|
||||
found = &r;
|
||||
break;
|
||||
@@ -1804,7 +1867,13 @@ SMonitorRule CConfigManager::getMonitorRuleFor(const std::string& name, const st
|
||||
}
|
||||
|
||||
SWorkspaceRule CConfigManager::getWorkspaceRuleFor(CWorkspace* pWorkspace) {
|
||||
const auto IT = std::find_if(m_dWorkspaceRules.begin(), m_dWorkspaceRules.end(), [&](const auto& other) { return other.workspaceName == pWorkspace->m_szName; });
|
||||
const auto WORKSPACEIDSTR = std::to_string(pWorkspace->m_iID);
|
||||
const auto IT = std::find_if(m_dWorkspaceRules.begin(), m_dWorkspaceRules.end(), [&](const auto& other) {
|
||||
return other.workspaceName == pWorkspace->m_szName /* name matches */
|
||||
|| (pWorkspace->m_bIsSpecialWorkspace && other.workspaceName.starts_with("special:") &&
|
||||
other.workspaceName.substr(8) == pWorkspace->m_szName) /* special and special:name */
|
||||
|| (pWorkspace->m_iID > 0 && WORKSPACEIDSTR == other.workspaceName); /* id matches and workspace is numerical */
|
||||
});
|
||||
if (IT == m_dWorkspaceRules.end())
|
||||
return SWorkspaceRule{};
|
||||
return *IT;
|
||||
@@ -1829,7 +1898,7 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(CWindow* pWindow) {
|
||||
// check if we have a matching rule
|
||||
if (!rule.v2) {
|
||||
try {
|
||||
if (rule.szValue.find("title:") == 0) {
|
||||
if (rule.szValue.starts_with("title:")) {
|
||||
// we have a title rule.
|
||||
std::regex RULECHECK(rule.szValue.substr(6));
|
||||
|
||||
@@ -1887,7 +1956,7 @@ std::vector<SWindowRule> CConfigManager::getMatchingRules(CWindow* pWindow) {
|
||||
if (!PWORKSPACE)
|
||||
continue;
|
||||
|
||||
if (rule.szWorkspace.find("name:") == 0) {
|
||||
if (rule.szWorkspace.starts_with("name:")) {
|
||||
if (PWORKSPACE->m_szName != rule.szWorkspace.substr(5))
|
||||
continue;
|
||||
} else {
|
||||
@@ -1945,7 +2014,7 @@ std::vector<SLayerRule> CConfigManager::getMatchingRules(SLayerSurface* pLS) {
|
||||
return returns;
|
||||
|
||||
for (auto& lr : m_dLayerRules) {
|
||||
if (lr.targetNamespace.find("address:0x") == 0) {
|
||||
if (lr.targetNamespace.starts_with("address:0x")) {
|
||||
if (std::format("address:0x{:x}", (uintptr_t)pLS) != lr.targetNamespace)
|
||||
continue;
|
||||
} else {
|
||||
@@ -2001,7 +2070,7 @@ void CConfigManager::performMonitorReload() {
|
||||
bool overAgain = false;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
if (!m->output)
|
||||
if (!m->output || m->isUnsafeFallback)
|
||||
continue;
|
||||
|
||||
auto rule = getMonitorRuleFor(m->szName, m->output->description ? m->output->description : "");
|
||||
@@ -2020,9 +2089,6 @@ void CConfigManager::performMonitorReload() {
|
||||
if (overAgain)
|
||||
performMonitorReload();
|
||||
|
||||
if (!g_pCompositor->m_vMonitors.empty()) // reset unsafe state if we have monitors
|
||||
g_pCompositor->m_bUnsafeState = false;
|
||||
|
||||
m_bWantsMonitorReload = false;
|
||||
|
||||
EMIT_HOOK_EVENT("monitorLayoutChanged", nullptr);
|
||||
@@ -2070,9 +2136,7 @@ bool CConfigManager::deviceConfigExists(const std::string& dev) {
|
||||
auto copy = dev;
|
||||
std::replace(copy.begin(), copy.end(), ' ', '-');
|
||||
|
||||
const auto it = deviceConfigs.find(copy);
|
||||
|
||||
return it != deviceConfigs.end();
|
||||
return deviceConfigs.contains(copy);
|
||||
}
|
||||
|
||||
bool CConfigManager::shouldBlurLS(const std::string& ns) {
|
||||
@@ -2087,15 +2151,13 @@ bool CConfigManager::shouldBlurLS(const std::string& ns) {
|
||||
|
||||
void CConfigManager::ensureMonitorStatus() {
|
||||
for (auto& rm : g_pCompositor->m_vRealMonitors) {
|
||||
if (!rm->output)
|
||||
if (!rm->output || rm->isUnsafeFallback)
|
||||
continue;
|
||||
|
||||
auto rule = getMonitorRuleFor(rm->szName, rm->output->description ? rm->output->description : "");
|
||||
|
||||
if (rule.disabled == rm->m_bEnabled) {
|
||||
rm->m_pThisWrap = &rm;
|
||||
if (rule.disabled == rm->m_bEnabled)
|
||||
g_pHyprRenderer->applyMonitorRule(rm.get(), &rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2193,7 +2255,7 @@ CMonitor* CConfigManager::getBoundMonitorForWS(const std::string& wsname) {
|
||||
|
||||
std::string CConfigManager::getBoundMonitorStringForWS(const std::string& wsname) {
|
||||
for (auto& wr : m_dWorkspaceRules) {
|
||||
const auto WSNAME = wr.workspaceName.find("name:") == 0 ? wr.workspaceName.substr(5) : wr.workspaceName;
|
||||
const auto WSNAME = wr.workspaceName.starts_with("name:") ? wr.workspaceName.substr(5) : wr.workspaceName;
|
||||
|
||||
if (WSNAME == wsname) {
|
||||
return wr.monitor;
|
||||
@@ -2261,8 +2323,13 @@ void CConfigManager::addPluginConfigVar(HANDLE handle, const std::string& name,
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigManager::addPluginKeyword(HANDLE handle, const std::string& name, std::function<void(const std::string&, const std::string&)> fn) {
|
||||
pluginKeywords.emplace_back(SPluginKeyword{handle, name, fn});
|
||||
}
|
||||
|
||||
void CConfigManager::removePluginConfig(HANDLE handle) {
|
||||
std::erase_if(pluginConfigs, [&](const auto& other) { return other.first == handle; });
|
||||
std::erase_if(pluginKeywords, [&](const auto& other) { return other.handle == handle; });
|
||||
}
|
||||
|
||||
std::string CConfigManager::getDefaultWorkspaceFor(const std::string& name) {
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include <algorithm>
|
||||
#include <regex>
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
#include <xf86drmMode.h>
|
||||
#include "../Window.hpp"
|
||||
#include "../helpers/WLClasses.hpp"
|
||||
@@ -36,18 +37,20 @@ struct SConfigValue {
|
||||
};
|
||||
|
||||
struct SWorkspaceRule {
|
||||
std::string monitor = "";
|
||||
std::string workspaceString = "";
|
||||
std::string workspaceName = "";
|
||||
int workspaceId = -1;
|
||||
bool isDefault = 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::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;
|
||||
};
|
||||
|
||||
struct SMonitorAdditionalReservedArea {
|
||||
@@ -69,6 +72,12 @@ struct SAnimationPropertyConfig {
|
||||
SAnimationPropertyConfig* pParentAnimation = nullptr;
|
||||
};
|
||||
|
||||
struct SPluginKeyword {
|
||||
HANDLE handle = 0;
|
||||
std::string name = "";
|
||||
std::function<void(const std::string&, const std::string&)> fn;
|
||||
};
|
||||
|
||||
struct SExecRequestedRule {
|
||||
std::string szRule = "";
|
||||
uint64_t iPid = 0;
|
||||
@@ -83,13 +92,16 @@ class CConfigManager {
|
||||
|
||||
int getInt(const std::string&);
|
||||
float getFloat(const std::string&);
|
||||
Vector2D getVec(const std::string&);
|
||||
std::string getString(const std::string&);
|
||||
void setFloat(const std::string&, float);
|
||||
void setInt(const std::string&, int);
|
||||
void setVec(const std::string&, Vector2D);
|
||||
void setString(const std::string&, const std::string&);
|
||||
|
||||
int getDeviceInt(const std::string&, const std::string&, const std::string& fallback = "");
|
||||
float getDeviceFloat(const std::string&, const std::string&, const std::string& fallback = "");
|
||||
Vector2D getDeviceVec(const std::string&, const std::string&, const std::string& fallback = "");
|
||||
std::string getDeviceString(const std::string&, const std::string&, const std::string& fallback = "");
|
||||
bool deviceConfigExists(const std::string&);
|
||||
bool shouldBlurLS(const std::string&);
|
||||
@@ -115,7 +127,8 @@ class CConfigManager {
|
||||
std::unordered_map<std::string, SAnimationPropertyConfig> getAnimationConfig();
|
||||
|
||||
void addPluginConfigVar(HANDLE handle, const std::string& name, const SConfigValue& value);
|
||||
void removePluginConfig(HANDLE handle);
|
||||
void addPluginKeyword(HANDLE handle, const std::string& name, std::function<void(const std::string& cmd, const std::string& val)> fun);
|
||||
void removePluginConfig(HANDLE handle);
|
||||
|
||||
// no-op when done.
|
||||
void dispatchExecOnce();
|
||||
@@ -158,6 +171,7 @@ class CConfigManager {
|
||||
|
||||
std::vector<std::string> m_vDeclaredPlugins;
|
||||
std::unordered_map<HANDLE, std::unique_ptr<std::unordered_map<std::string, SConfigValue>>> pluginConfigs; // stores plugin configs
|
||||
std::vector<SPluginKeyword> pluginKeywords;
|
||||
|
||||
bool isFirstLaunch = true; // For exec-once
|
||||
|
||||
|
@@ -58,6 +58,9 @@ general {
|
||||
col.inactive_border = rgba(595959aa)
|
||||
|
||||
layout = dwindle
|
||||
|
||||
# Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on
|
||||
allow_tearing = false
|
||||
}
|
||||
|
||||
decoration {
|
||||
@@ -108,6 +111,11 @@ gestures {
|
||||
workspace_swipe = off
|
||||
}
|
||||
|
||||
misc {
|
||||
# See https://wiki.hyprland.org/Configuring/Variables/ for more
|
||||
force_default_wallpaper = -1 # Set to 0 to disable the anime mascot wallpapers
|
||||
}
|
||||
|
||||
# Example per-device config
|
||||
# See https://wiki.hyprland.org/Configuring/Keywords/#executing for more
|
||||
device:epic-mouse-v1 {
|
||||
@@ -164,6 +172,10 @@ bind = $mainMod SHIFT, 8, movetoworkspace, 8
|
||||
bind = $mainMod SHIFT, 9, movetoworkspace, 9
|
||||
bind = $mainMod SHIFT, 0, movetoworkspace, 10
|
||||
|
||||
# Example special workspace (scratchpad)
|
||||
bind = $mainMod, S, togglespecialworkspace, magic
|
||||
bind = $mainMod SHIFT, S, movetoworkspace, special:magic
|
||||
|
||||
# Scroll through existing workspaces with mainMod + scroll
|
||||
bind = $mainMod, mouse_down, workspace, e+1
|
||||
bind = $mainMod, mouse_up, workspace, e-1
|
||||
|
@@ -1,7 +1,6 @@
|
||||
#include "CrashReporter.hpp"
|
||||
#include <random>
|
||||
#include <sys/utsname.h>
|
||||
#include <execinfo.h>
|
||||
#include <fstream>
|
||||
#include <signal.h>
|
||||
|
||||
@@ -14,19 +13,19 @@
|
||||
std::string getRandomMessage() {
|
||||
|
||||
const std::vector<std::string> MESSAGES = {"Sorry, didn't mean to...",
|
||||
"This was an accident, I swear!",
|
||||
"Calm down, it was a misinput! MISINPUT!",
|
||||
"Oops",
|
||||
"Vaxry is going to be upset.",
|
||||
"Who tried dividing by zero?!",
|
||||
"Maybe you should try dusting your PC in the meantime?",
|
||||
"I tried so hard, and got so far...",
|
||||
"I don't feel so good...",
|
||||
"*thud*",
|
||||
"Well this is awkward.",
|
||||
"\"stable\"",
|
||||
"I hope you didn't have any unsaved progress.",
|
||||
"All these computers..."};
|
||||
"This was an accident, I swear!",
|
||||
"Calm down, it was a misinput! MISINPUT!",
|
||||
"Oops",
|
||||
"Vaxry is going to be upset.",
|
||||
"Who tried dividing by zero?!",
|
||||
"Maybe you should try dusting your PC in the meantime?",
|
||||
"I tried so hard, and got so far...",
|
||||
"I don't feel so good...",
|
||||
"*thud*",
|
||||
"Well this is awkward.",
|
||||
"\"stable\"",
|
||||
"I hope you didn't have any unsaved progress.",
|
||||
"All these computers..."};
|
||||
|
||||
std::random_device dev;
|
||||
std::mt19937 engine(dev());
|
||||
@@ -130,7 +129,7 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
|
||||
std::ofstream ofs;
|
||||
std::string path;
|
||||
if (!CACHE_HOME) {
|
||||
if (!CACHE_HOME || std::string(CACHE_HOME).empty()) {
|
||||
if (!std::filesystem::exists(std::string(HOME) + "/.hyprland")) {
|
||||
std::filesystem::create_directory(std::string(HOME) + "/.hyprland");
|
||||
std::filesystem::permissions(std::string(HOME) + "/.hyprland", std::filesystem::perms::all, std::filesystem::perm_options::replace);
|
||||
@@ -139,7 +138,7 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
path = std::string(HOME) + "/.hyprland/hyprlandCrashReport" + std::to_string(PID) + ".txt";
|
||||
ofs.open(path, std::ios::trunc);
|
||||
|
||||
} else if (CACHE_HOME) {
|
||||
} else {
|
||||
if (!std::filesystem::exists(std::string(CACHE_HOME) + "/hyprland")) {
|
||||
std::filesystem::create_directory(std::string(CACHE_HOME) + "/hyprland");
|
||||
std::filesystem::permissions(std::string(CACHE_HOME) + "/hyprland", std::filesystem::perms::all, std::filesystem::perm_options::replace);
|
||||
@@ -147,8 +146,6 @@ void CrashReporter::createAndSaveCrash(int sig) {
|
||||
|
||||
path = std::string(CACHE_HOME) + "/hyprland/hyprlandCrashReport" + std::to_string(PID) + ".txt";
|
||||
ofs.open(path, std::ios::trunc);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
ofs << finalCrashReport;
|
||||
|
@@ -63,14 +63,16 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
"transform": {},
|
||||
"focused": {},
|
||||
"dpmsStatus": {},
|
||||
"vrr": {}
|
||||
"vrr": {},
|
||||
"activelyTearing": {}
|
||||
}},)#",
|
||||
m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->output->description ? m->output->description : ""), (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->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->dpmsStatus ? "true" : "false"), (m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED ? "true" : "false"),
|
||||
m->tearingState.activelyTearing ? "true" : "false");
|
||||
}
|
||||
|
||||
trimTrailingComma(result);
|
||||
@@ -85,13 +87,13 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
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\n",
|
||||
"{}\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));
|
||||
(int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED), m->tearingState.activelyTearing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,33 +105,34 @@ static std::string getGroupedData(CWindow* w, HyprCtl::eHyprCtlOutputFormat form
|
||||
if (!w->m_sGroupData.pNextWindow)
|
||||
return isJson ? "" : "0";
|
||||
|
||||
std::vector<CWindow*> groupMembers;
|
||||
|
||||
CWindow* curr = w;
|
||||
do {
|
||||
groupMembers.push_back(curr);
|
||||
curr = curr->m_sGroupData.pNextWindow;
|
||||
} while (curr != w);
|
||||
|
||||
const auto comma = isJson ? ", " : ",";
|
||||
std::ostringstream result;
|
||||
|
||||
bool first = true;
|
||||
for (auto& gw : groupMembers) {
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
result << comma;
|
||||
CWindow* head = w->getGroupHead();
|
||||
CWindow* curr = head;
|
||||
while (true) {
|
||||
if (isJson)
|
||||
result << std::format("\"0x{:x}\"", (uintptr_t)gw);
|
||||
result << std::format("\"0x{:x}\"", (uintptr_t)curr);
|
||||
else
|
||||
result << std::format("{:x}", (uintptr_t)gw);
|
||||
result << std::format("{:x}", (uintptr_t)curr);
|
||||
curr = curr->m_sGroupData.pNextWindow;
|
||||
// We've wrapped around to the start, break out without trailing comma
|
||||
if (curr == head)
|
||||
break;
|
||||
result << (isJson ? ", " : ",");
|
||||
}
|
||||
|
||||
return result.str();
|
||||
}
|
||||
|
||||
static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat format) {
|
||||
auto getFocusHistoryID = [](CWindow* wnd) -> int {
|
||||
for (size_t i = 0; i < g_pCompositor->m_vWindowFocusHistory.size(); ++i) {
|
||||
if (g_pCompositor->m_vWindowFocusHistory[i] == wnd)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
return std::format(
|
||||
R"#({{
|
||||
@@ -155,7 +158,8 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma
|
||||
"fullscreenMode": {},
|
||||
"fakeFullscreen": {},
|
||||
"grouped": [{}],
|
||||
"swallowing": "0x{:x}"
|
||||
"swallowing": "0x{:x}",
|
||||
"focusHistoryID": {}
|
||||
}},)#",
|
||||
(uintptr_t)w, (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y,
|
||||
(int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y, w->m_iWorkspaceID,
|
||||
@@ -166,13 +170,13 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma
|
||||
escapeJSONStrings(g_pXWaylandManager->getTitle(w)), escapeJSONStrings(w->m_szInitialClass), escapeJSONStrings(w->m_szInitialTitle), w->getPID(),
|
||||
((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"), (w->m_bIsFullscreen ? "true" : "false"),
|
||||
(w->m_bIsFullscreen ? (g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? (int)g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_efFullscreenMode : 0) : 0),
|
||||
w->m_bFakeFullscreenState ? "true" : "false", getGroupedData(w, format), (uintptr_t)w->m_pSwallowed);
|
||||
w->m_bFakeFullscreenState ? "true" : "false", getGroupedData(w, format), (uintptr_t)w->m_pSwallowed, getFocusHistoryID(w));
|
||||
} else {
|
||||
return std::format(
|
||||
"Window {:x} -> {}:\n\tmapped: {}\n\thidden: {}\n\tat: {},{}\n\tsize: {},{}\n\tworkspace: {} ({})\n\tfloating: {}\n\tmonitor: {}\n\tclass: {}\n\ttitle: "
|
||||
"{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: "
|
||||
"{}\n\txwayland: {}\n\tpinned: "
|
||||
"{}\n\tfullscreen: {}\n\tfullscreenmode: {}\n\tfakefullscreen: {}\n\tgrouped: {}\n\tswallowing: {:x}\n\n",
|
||||
"{}\n\tfullscreen: {}\n\tfullscreenmode: {}\n\tfakefullscreen: {}\n\tgrouped: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\n",
|
||||
(uintptr_t)w, w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y,
|
||||
(int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y, w->m_iWorkspaceID,
|
||||
(w->m_iWorkspaceID == -1 ? "" :
|
||||
@@ -181,7 +185,7 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma
|
||||
(int)w->m_bIsFloating, (int64_t)w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w), g_pXWaylandManager->getTitle(w), w->m_szInitialClass, w->m_szInitialTitle,
|
||||
w->getPID(), (int)w->m_bIsX11, (int)w->m_bPinned, (int)w->m_bIsFullscreen,
|
||||
(w->m_bIsFullscreen ? (g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_efFullscreenMode : 0) : 0),
|
||||
(int)w->m_bFakeFullscreenState, getGroupedData(w, format), (uintptr_t)w->m_pSwallowed);
|
||||
(int)w->m_bFakeFullscreenState, getGroupedData(w, format), (uintptr_t)w->m_pSwallowed, getFocusHistoryID(w));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,23 +217,70 @@ static std::string getWorkspaceData(CWorkspace* w, HyprCtl::eHyprCtlOutputFormat
|
||||
"id": {},
|
||||
"name": "{}",
|
||||
"monitor": "{}",
|
||||
"monitorID": {},
|
||||
"windows": {},
|
||||
"hasfullscreen": {},
|
||||
"lastwindow": "0x{:x}",
|
||||
"lastwindowtitle": "{}"
|
||||
}})#",
|
||||
w->m_iID, escapeJSONStrings(w->m_szName), escapeJSONStrings(PMONITOR ? PMONITOR->szName : "?"), g_pCompositor->getWindowsOnWorkspace(w->m_iID),
|
||||
w->m_iID, escapeJSONStrings(w->m_szName), escapeJSONStrings(PMONITOR ? PMONITOR->szName : "?"),
|
||||
escapeJSONStrings(PMONITOR ? std::to_string(PMONITOR->ID) : "null"), g_pCompositor->getWindowsOnWorkspace(w->m_iID),
|
||||
((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false"), (uintptr_t)PLASTW, PLASTW ? escapeJSONStrings(PLASTW->m_szTitle) : "");
|
||||
} else {
|
||||
return std::format("workspace ID {} ({}) on monitor {}:\n\twindows: {}\n\thasfullscreen: {}\n\tlastwindow: 0x{:x}\n\tlastwindowtitle: {}\n\n", w->m_iID, w->m_szName,
|
||||
PMONITOR ? PMONITOR->szName : "?", g_pCompositor->getWindowsOnWorkspace(w->m_iID), (int)w->m_bHasFullscreenWindow, (uintptr_t)PLASTW,
|
||||
PLASTW ? PLASTW->m_szTitle : "");
|
||||
return std::format("workspace ID {} ({}) on monitor {}:\n\tmonitorID: {}\n\twindows: {}\n\thasfullscreen: {}\n\tlastwindow: 0x{:x}\n\tlastwindowtitle: {}\n\n", w->m_iID,
|
||||
w->m_szName, PMONITOR ? PMONITOR->szName : "?", PMONITOR ? std::to_string(PMONITOR->ID) : "null", g_pCompositor->getWindowsOnWorkspace(w->m_iID),
|
||||
(int)w->m_bHasFullscreenWindow, (uintptr_t)PLASTW, PLASTW ? PLASTW->m_szTitle : "");
|
||||
}
|
||||
}
|
||||
|
||||
static std::string getWorkspaceRuleData(const SWorkspaceRule& r, HyprCtl::eHyprCtlOutputFormat format) {
|
||||
const auto boolToString = [](const bool b) -> std::string { return b ? "true" : "false"; };
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
const std::string monitor = r.monitor.empty() ? "" : std::format(",\n \"monitor\": \"{}\"", escapeJSONStrings(r.monitor));
|
||||
const std::string default_ = (bool)(r.isDefault) ? std::format(",\n \"default\": {}", boolToString(r.isDefault)) : "";
|
||||
const std::string persistent = (bool)(r.isPersistent) ? std::format(",\n \"persistent\": {}", boolToString(r.isPersistent)) : "";
|
||||
const std::string gapsIn = (bool)(r.gapsIn) ? std::format(",\n \"gapsIn\": {}", r.gapsIn.value()) : "";
|
||||
const std::string gapsOut = (bool)(r.gapsOut) ? std::format(",\n \"gapsOut\": {}", r.gapsOut.value()) : "";
|
||||
const std::string borderSize = (bool)(r.borderSize) ? std::format(",\n \"borderSize\": {}", r.borderSize.value()) : "";
|
||||
const std::string border = (bool)(r.border) ? std::format(",\n \"border\": {}", boolToString(r.border.value())) : "";
|
||||
const std::string rounding = (bool)(r.rounding) ? std::format(",\n \"rounding\": {}", boolToString(r.rounding.value())) : "";
|
||||
const std::string decorate = (bool)(r.decorate) ? std::format(",\n \"decorate\": {}", boolToString(r.decorate.value())) : "";
|
||||
const std::string shadow = (bool)(r.shadow) ? std::format(",\n \"shadow\": {}", boolToString(r.shadow.value())) : "";
|
||||
|
||||
std::string result = std::format(R"#({{
|
||||
"workspaceString": "{}"{}{}{}{}{}{}{}{}
|
||||
}})#",
|
||||
escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow);
|
||||
|
||||
return result;
|
||||
} else {
|
||||
const std::string monitor = std::format("\tmonitor: {}\n", r.monitor.empty() ? "<unset>" : escapeJSONStrings(r.monitor));
|
||||
const std::string default_ = std::format("\tdefault: {}\n", (bool)(r.isDefault) ? boolToString(r.isDefault) : "<unset>");
|
||||
const std::string persistent = std::format("\tpersistent: {}\n", (bool)(r.isPersistent) ? boolToString(r.isPersistent) : "<unset>");
|
||||
const std::string gapsIn = std::format("\tgapsIn: {}\n", (bool)(r.gapsIn) ? std::to_string(r.gapsIn.value()) : "<unset>");
|
||||
const std::string gapsOut = std::format("\tgapsOut: {}\n", (bool)(r.gapsOut) ? std::to_string(r.gapsOut.value()) : "<unset>");
|
||||
const std::string borderSize = std::format("\tborderSize: {}\n", (bool)(r.borderSize) ? std::to_string(r.borderSize.value()) : "<unset>");
|
||||
const std::string border = std::format("\tborder: {}\n", (bool)(r.border) ? boolToString(r.border.value()) : "<unset>");
|
||||
const std::string rounding = std::format("\trounding: {}\n", (bool)(r.rounding) ? boolToString(r.rounding.value()) : "<unset>");
|
||||
const std::string decorate = std::format("\tdecorate: {}\n", (bool)(r.decorate) ? boolToString(r.decorate.value()) : "<unset>");
|
||||
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);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
std::string activeWorkspaceRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
if (!g_pCompositor->m_pLastMonitor)
|
||||
return "unsafe state";
|
||||
|
||||
std::string result = "";
|
||||
auto w = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
|
||||
|
||||
if (!w)
|
||||
return "internal error";
|
||||
|
||||
return getWorkspaceData(w, format);
|
||||
}
|
||||
|
||||
@@ -254,6 +305,26 @@ std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string workspaceRulesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string result = "";
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
result += "[";
|
||||
for (auto& r : g_pConfigManager->getAllWorkspaceRules()) {
|
||||
result += getWorkspaceRuleData(r, format);
|
||||
result += ",";
|
||||
}
|
||||
|
||||
trimTrailingComma(result);
|
||||
result += "]";
|
||||
} else {
|
||||
for (auto& r : g_pConfigManager->getAllWorkspaceRules()) {
|
||||
result += getWorkspaceRuleData(r, format);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string activeWindowRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
@@ -835,7 +906,8 @@ std::string dispatchSetCursor(std::string request) {
|
||||
std::string theme = "";
|
||||
for (size_t i = 1; i < vars.size() - 1; ++i)
|
||||
theme += vars[i] + " ";
|
||||
theme.pop_back();
|
||||
if (!theme.empty())
|
||||
theme.pop_back();
|
||||
|
||||
int size = 0;
|
||||
try {
|
||||
@@ -951,7 +1023,7 @@ std::string dispatchSetProp(std::string request) {
|
||||
bool lock = false;
|
||||
|
||||
if (vars.size() > 4) {
|
||||
if (vars[4].find("lock") == 0) {
|
||||
if (vars[4].starts_with("lock")) {
|
||||
lock = true;
|
||||
}
|
||||
}
|
||||
@@ -1001,6 +1073,10 @@ std::string dispatchSetProp(std::string request) {
|
||||
PWINDOW->m_sSpecialRenderData.borderSize.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "keepaspectratio") {
|
||||
PWINDOW->m_sAdditionalConfigData.keepAspectRatio.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "immediate") {
|
||||
PWINDOW->m_sAdditionalConfigData.forceTearing.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else if (PROP == "nearestneighbor") {
|
||||
PWINDOW->m_sAdditionalConfigData.nearestNeighbor.forceSetIgnoreLocked(configStringToInt(VAL), lock);
|
||||
} else {
|
||||
return "prop not found";
|
||||
}
|
||||
@@ -1247,6 +1323,8 @@ std::string getReply(std::string request) {
|
||||
return monitorsRequest(format);
|
||||
else if (request == "workspaces")
|
||||
return workspacesRequest(format);
|
||||
else if (request == "workspacerules")
|
||||
return workspaceRulesRequest(format);
|
||||
else if (request == "activeworkspace")
|
||||
return activeWorkspaceRequest(format);
|
||||
else if (request == "clients")
|
||||
@@ -1259,7 +1337,7 @@ std::string getReply(std::string request) {
|
||||
return layersRequest(format);
|
||||
else if (request == "version")
|
||||
return versionRequest(format);
|
||||
else if (request.find("reload") == 0)
|
||||
else if (request.starts_with("reload"))
|
||||
return reloadRequest(request);
|
||||
else if (request == "devices")
|
||||
return devicesRequest(format);
|
||||
@@ -1273,27 +1351,27 @@ std::string getReply(std::string request) {
|
||||
return globalShortcutsRequest(format);
|
||||
else if (request == "animations")
|
||||
return animationsRequest(format);
|
||||
else if (request.find("plugin") == 0)
|
||||
else if (request.starts_with("plugin"))
|
||||
return dispatchPlugin(request);
|
||||
else if (request.find("notify") == 0)
|
||||
else if (request.starts_with("notify"))
|
||||
return dispatchNotify(request);
|
||||
else if (request.find("setprop") == 0)
|
||||
else if (request.starts_with("setprop"))
|
||||
return dispatchSetProp(request);
|
||||
else if (request.find("seterror") == 0)
|
||||
else if (request.starts_with("seterror"))
|
||||
return dispatchSeterror(request);
|
||||
else if (request.find("switchxkblayout") == 0)
|
||||
else if (request.starts_with("switchxkblayout"))
|
||||
return switchXKBLayoutRequest(request);
|
||||
else if (request.find("output") == 0)
|
||||
else if (request.starts_with("output"))
|
||||
return dispatchOutput(request);
|
||||
else if (request.find("dispatch") == 0)
|
||||
else if (request.starts_with("dispatch"))
|
||||
return dispatchRequest(request);
|
||||
else if (request.find("keyword") == 0)
|
||||
else if (request.starts_with("keyword"))
|
||||
return dispatchKeyword(request);
|
||||
else if (request.find("setcursor") == 0)
|
||||
else if (request.starts_with("setcursor"))
|
||||
return dispatchSetCursor(request);
|
||||
else if (request.find("getoption") == 0)
|
||||
else if (request.starts_with("getoption"))
|
||||
return dispatchGetOption(request, format);
|
||||
else if (request.find("[[BATCH]]") == 0)
|
||||
else if (request.starts_with("[[BATCH]]"))
|
||||
return dispatchBatch(request);
|
||||
|
||||
return "unknown request";
|
||||
|
@@ -233,6 +233,6 @@ void CHyprDebugOverlay::draw() {
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||
|
||||
wlr_box pMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
CBox pMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ class CHyprMonitorDebugOverlay {
|
||||
std::deque<float> m_dLastAnimationTicks;
|
||||
std::chrono::high_resolution_clock::time_point m_tpLastFrame;
|
||||
CMonitor* m_pMonitor = nullptr;
|
||||
wlr_box m_wbLastDrawnBox;
|
||||
CBox m_wbLastDrawnBox;
|
||||
|
||||
friend class CHyprRenderer;
|
||||
};
|
||||
|
@@ -3,7 +3,7 @@
|
||||
#include <pango/pangocairo.h>
|
||||
|
||||
CHyprNotificationOverlay::CHyprNotificationOverlay() {
|
||||
g_pHookSystem->hookDynamic("focusedMon", [&](void* self, std::any param) {
|
||||
g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) {
|
||||
if (m_dNotifications.size() == 0)
|
||||
return;
|
||||
|
||||
@@ -44,9 +44,13 @@ void CHyprNotificationOverlay::addNotification(const std::string& text, const CC
|
||||
PNOTIF->started.reset();
|
||||
PNOTIF->timeMs = timeMs;
|
||||
PNOTIF->icon = icon;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
g_pCompositor->scheduleFrameForMonitor(m.get());
|
||||
}
|
||||
}
|
||||
|
||||
wlr_box CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
|
||||
CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
|
||||
static constexpr auto ANIM_DURATION_MS = 600.0;
|
||||
static constexpr auto ANIM_LAG_MS = 100.0;
|
||||
static constexpr auto NOTIF_LEFTBAR_SIZE = 5.0;
|
||||
@@ -166,7 +170,7 @@ wlr_box CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
|
||||
// cleanup notifs
|
||||
std::erase_if(m_dNotifications, [](const auto& notif) { return notif->started.getMillis() > notif->timeMs; });
|
||||
|
||||
return wlr_box{(int)(pMonitor->vecPosition.x + pMonitor->vecSize.x - maxWidth - 20), (int)pMonitor->vecPosition.y, (int)maxWidth + 20, (int)offsetY + 10};
|
||||
return CBox{(int)(pMonitor->vecPosition.x + pMonitor->vecSize.x - maxWidth - 20), (int)pMonitor->vecPosition.y, (int)maxWidth + 20, (int)offsetY + 10};
|
||||
}
|
||||
|
||||
void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
|
||||
@@ -197,7 +201,7 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
|
||||
|
||||
cairo_surface_flush(m_pCairoSurface);
|
||||
|
||||
wlr_box damage = drawNotifications(pMonitor);
|
||||
CBox damage = drawNotifications(pMonitor);
|
||||
|
||||
g_pHyprRenderer->damageBox(&damage);
|
||||
g_pHyprRenderer->damageBox(&m_bLastDamage);
|
||||
@@ -220,6 +224,6 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||
|
||||
wlr_box pMonBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
||||
CBox pMonBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y};
|
||||
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
|
||||
}
|
@@ -44,8 +44,8 @@ class CHyprNotificationOverlay {
|
||||
void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE);
|
||||
|
||||
private:
|
||||
wlr_box drawNotifications(CMonitor* pMonitor);
|
||||
wlr_box m_bLastDamage;
|
||||
CBox drawNotifications(CMonitor* pMonitor);
|
||||
CBox m_bLastDamage;
|
||||
|
||||
std::deque<std::unique_ptr<SNotification>> m_dNotifications;
|
||||
|
||||
|
@@ -10,6 +10,12 @@ 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;
|
||||
|
@@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <wlr/util/log.h>
|
||||
#include <format>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <chrono>
|
||||
#include "../includes.hpp"
|
||||
#include "../helpers/MiscFunctions.hpp"
|
||||
|
||||
#define LOGMESSAGESIZE 1024
|
||||
@@ -79,4 +79,4 @@ namespace Debug {
|
||||
}
|
||||
|
||||
void wlrLog(wlr_log_importance level, const char* fmt, va_list args);
|
||||
};
|
||||
};
|
||||
|
@@ -62,6 +62,7 @@ namespace Events {
|
||||
DYNLISTENFUNC(setOverrideRedirect);
|
||||
DYNLISTENFUNC(associateX11);
|
||||
DYNLISTENFUNC(dissociateX11);
|
||||
DYNLISTENFUNC(ackConfigure);
|
||||
|
||||
// Window subsurfaces
|
||||
// LISTENER(newSubsurfaceWindow);
|
||||
@@ -174,4 +175,7 @@ namespace Events {
|
||||
|
||||
// Cursor shape
|
||||
LISTENER(setCursorShape);
|
||||
|
||||
// Tearing hints
|
||||
LISTENER(newTearingHint);
|
||||
};
|
||||
|
@@ -95,8 +95,8 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
|
||||
PMONITOR->scheduledRecalc = true;
|
||||
|
||||
// and damage
|
||||
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
|
||||
layersurface->geometry.height};
|
||||
CBox geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
|
||||
layersurface->geometry.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||
|
||||
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
|
||||
|
||||
const bool GRABSFOCUS = layersurface->layerSurface->current.keyboard_interactive &&
|
||||
const bool GRABSFOCUS = layersurface->layerSurface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE &&
|
||||
// don't focus if constrained
|
||||
(!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint);
|
||||
|
||||
@@ -157,8 +157,8 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||
|
||||
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
|
||||
|
||||
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
|
||||
layersurface->geometry.height};
|
||||
CBox geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
|
||||
layersurface->geometry.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
const auto WORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
||||
@@ -171,7 +171,8 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"openlayer", std::string(layersurface->layerSurface->_namespace ? layersurface->layerSurface->_namespace : "")});
|
||||
EMIT_HOOK_EVENT("openLayer", layersurface);
|
||||
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(layersurface->layerSurface->surface, PMONITOR->scale);
|
||||
g_pCompositor->setPreferredScaleForSurface(layersurface->layerSurface->surface, PMONITOR->scale);
|
||||
g_pCompositor->setPreferredTransformForSurface(layersurface->layerSurface->surface, PMONITOR->transform);
|
||||
}
|
||||
|
||||
void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
||||
@@ -246,8 +247,8 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
||||
}
|
||||
}
|
||||
|
||||
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
|
||||
layersurface->geometry.height};
|
||||
CBox geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width,
|
||||
layersurface->geometry.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
|
||||
geomFixed = {layersurface->geometry.x + (int)PMONITOR->vecPosition.x, layersurface->geometry.y + (int)PMONITOR->vecPosition.y,
|
||||
@@ -269,7 +270,7 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
|
||||
if (layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM)
|
||||
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd
|
||||
|
||||
wlr_box geomFixed = {layersurface->geometry.x, layersurface->geometry.y, layersurface->geometry.width, layersurface->geometry.height};
|
||||
CBox geomFixed = {layersurface->geometry.x, layersurface->geometry.y, layersurface->geometry.width, layersurface->geometry.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
|
||||
// fix if it changed its mon
|
||||
@@ -342,5 +343,6 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
|
||||
|
||||
g_pHyprRenderer->damageSurface(layersurface->layerSurface->surface, layersurface->position.x, layersurface->position.y);
|
||||
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(layersurface->layerSurface->surface, PMONITOR->scale);
|
||||
g_pCompositor->setPreferredScaleForSurface(layersurface->layerSurface->surface, PMONITOR->scale);
|
||||
g_pCompositor->setPreferredTransformForSurface(layersurface->layerSurface->surface, PMONITOR->transform);
|
||||
}
|
||||
|
@@ -237,3 +237,43 @@ void Events::listener_setCursorShape(wl_listener* listener, void* data) {
|
||||
|
||||
g_pInputManager->processMouseRequest(E);
|
||||
}
|
||||
|
||||
void Events::listener_newTearingHint(wl_listener* listener, void* data) {
|
||||
const auto TCTL = (wlr_tearing_control_v1*)data;
|
||||
|
||||
const auto PWINDOW = g_pCompositor->getWindowFromSurface(TCTL->surface);
|
||||
|
||||
if (!PWINDOW) {
|
||||
Debug::log(ERR, "Tearing hint {} was attached to an unknown surface", (uintptr_t)data);
|
||||
return;
|
||||
}
|
||||
|
||||
Debug::log(LOG, "New tearing hint for window {} at {}", PWINDOW, (uintptr_t)data);
|
||||
|
||||
const auto NEWCTRL = g_pHyprRenderer->m_vTearingControllers.emplace_back(std::make_unique<STearingController>()).get();
|
||||
NEWCTRL->pWlrHint = (wlr_tearing_control_v1*)data;
|
||||
|
||||
NEWCTRL->hyprListener_destroy.initCallback(
|
||||
&NEWCTRL->pWlrHint->events.destroy,
|
||||
[&](void* owner, void* data) {
|
||||
Debug::log(LOG, "Destroyed {} tearing hint", (uintptr_t)((STearingController*)owner)->pWlrHint);
|
||||
|
||||
std::erase_if(g_pHyprRenderer->m_vTearingControllers, [&](const auto& other) { return other.get() == owner; });
|
||||
},
|
||||
NEWCTRL, "TearingController");
|
||||
|
||||
NEWCTRL->hyprListener_set.initCallback(
|
||||
&NEWCTRL->pWlrHint->events.set_hint,
|
||||
[&](void* owner, void* data) {
|
||||
const auto TEARINGHINT = (STearingController*)owner;
|
||||
|
||||
const auto PWINDOW = g_pCompositor->getWindowFromSurface(TEARINGHINT->pWlrHint->surface);
|
||||
|
||||
if (PWINDOW) {
|
||||
PWINDOW->m_bTearingHint = TEARINGHINT->pWlrHint->hint;
|
||||
|
||||
Debug::log(LOG, "Hint {} (window {}) set tearing hint to {}", (uintptr_t)TEARINGHINT->pWlrHint, PWINDOW, (uint32_t)TEARINGHINT->pWlrHint->hint);
|
||||
}
|
||||
},
|
||||
NEWCTRL, "TearingController");
|
||||
}
|
||||
|
@@ -28,8 +28,9 @@ void Events::listener_change(wl_listener* listener, void* data) {
|
||||
|
||||
const auto CONFIGHEAD = wlr_output_configuration_head_v1_create(CONFIG, m->output);
|
||||
|
||||
wlr_box BOX;
|
||||
wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m->output, &BOX);
|
||||
CBox BOX;
|
||||
wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m->output, BOX.pWlr());
|
||||
BOX.applyFromWlr();
|
||||
|
||||
//m->vecSize.x = BOX.width;
|
||||
// m->vecSize.y = BOX.height;
|
||||
@@ -67,45 +68,31 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_pCompositor->m_bUnsafeState)
|
||||
Debug::log(WARN, "Recovering from an unsafe state. May you be lucky.");
|
||||
|
||||
// add it to real
|
||||
std::shared_ptr<CMonitor>* PNEWMONITORWRAP = nullptr;
|
||||
|
||||
PNEWMONITORWRAP = &g_pCompositor->m_vRealMonitors.emplace_back(std::make_shared<CMonitor>());
|
||||
if (std::string("HEADLESS-1") == OUTPUT->name)
|
||||
g_pCompositor->m_pUnsafeOutput = PNEWMONITORWRAP->get();
|
||||
|
||||
(*PNEWMONITORWRAP)->ID = g_pCompositor->getNextAvailableMonitorID(OUTPUT->name);
|
||||
(*PNEWMONITORWRAP)->output = OUTPUT;
|
||||
const bool FALLBACK = g_pCompositor->m_pUnsafeOutput ? OUTPUT == g_pCompositor->m_pUnsafeOutput->output : false;
|
||||
(*PNEWMONITORWRAP)->ID = FALLBACK ? -1 : g_pCompositor->getNextAvailableMonitorID(OUTPUT->name);
|
||||
const auto PNEWMONITOR = PNEWMONITORWRAP->get();
|
||||
PNEWMONITOR->isUnsafeFallback = FALLBACK;
|
||||
|
||||
const auto PNEWMONITOR = PNEWMONITORWRAP->get();
|
||||
if (!FALLBACK)
|
||||
PNEWMONITOR->onConnect(false);
|
||||
|
||||
PNEWMONITOR->output = OUTPUT;
|
||||
PNEWMONITOR->m_pThisWrap = PNEWMONITORWRAP;
|
||||
if (!PNEWMONITOR->m_bEnabled || FALLBACK)
|
||||
return;
|
||||
|
||||
PNEWMONITOR->onConnect(false);
|
||||
// ready to process if we have a real monitor
|
||||
|
||||
if ((!g_pHyprRenderer->m_pMostHzMonitor || PNEWMONITOR->refreshRate > g_pHyprRenderer->m_pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled)
|
||||
g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR;
|
||||
|
||||
// ready to process cuz we have a monitor
|
||||
if (PNEWMONITOR->m_bEnabled) {
|
||||
|
||||
if (g_pCompositor->m_bUnsafeState) {
|
||||
// recover workspaces
|
||||
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||
g_pCompositor->moveWorkspaceToMonitor(ws.get(), PNEWMONITOR);
|
||||
}
|
||||
|
||||
g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR;
|
||||
|
||||
const auto POS = PNEWMONITOR->middle();
|
||||
if (g_pCompositor->m_sSeat.mouse)
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, POS.x, POS.y);
|
||||
}
|
||||
|
||||
g_pCompositor->m_bReadyToProcess = true;
|
||||
g_pCompositor->m_bUnsafeState = false;
|
||||
}
|
||||
g_pCompositor->m_bReadyToProcess = true;
|
||||
|
||||
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||
g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR);
|
||||
@@ -131,8 +118,12 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) {
|
||||
Debug::log(WARN, "Attempted to render frame on inactive session!");
|
||||
|
||||
if (g_pCompositor->m_bUnsafeState)
|
||||
g_pConfigManager->performMonitorReload();
|
||||
if (g_pCompositor->m_bUnsafeState && std::ranges::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& m) {
|
||||
return m->output != g_pCompositor->m_pUnsafeOutput->output;
|
||||
})) {
|
||||
// restore from unsafe state
|
||||
g_pCompositor->leaveUnsafeState();
|
||||
}
|
||||
|
||||
return; // cannot draw on session inactive (different tty)
|
||||
}
|
||||
@@ -140,12 +131,25 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
if (!PMONITOR->m_bEnabled)
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->recheckSolitaryForMonitor(PMONITOR);
|
||||
|
||||
PMONITOR->tearingState.busy = false;
|
||||
|
||||
if (PMONITOR->tearingState.activelyTearing && PMONITOR->solitaryClient /* can be invalidated by a recheck */) {
|
||||
|
||||
if (!PMONITOR->tearingState.frameScheduledWhileBusy)
|
||||
return; // we did not schedule a frame yet to be displayed, but we are tearing. Why render?
|
||||
|
||||
PMONITOR->tearingState.nextRenderTorn = true;
|
||||
PMONITOR->tearingState.frameScheduledWhileBusy = false;
|
||||
}
|
||||
|
||||
static auto* const PENABLERAT = &g_pConfigManager->getConfigValuePtr("misc:render_ahead_of_time")->intValue;
|
||||
static auto* const PRATSAFE = &g_pConfigManager->getConfigValuePtr("misc:render_ahead_safezone")->intValue;
|
||||
|
||||
PMONITOR->lastPresentationTimer.reset();
|
||||
|
||||
if (*PENABLERAT) {
|
||||
if (*PENABLERAT && !PMONITOR->tearingState.nextRenderTorn) {
|
||||
if (!PMONITOR->RATScheduled) {
|
||||
// render
|
||||
g_pHyprRenderer->renderMonitor(PMONITOR);
|
||||
@@ -226,7 +230,7 @@ void Events::listener_monitorCommit(void* owner, void* data) {
|
||||
|
||||
const auto E = (wlr_output_event_commit*)data;
|
||||
|
||||
if (E->committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
if (E->state->committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
g_pProtocolManager->m_pScreencopyProtocolManager->onOutputCommit(PMONITOR, E);
|
||||
g_pProtocolManager->m_pToplevelExportProtocolManager->onOutputCommit(PMONITOR, E);
|
||||
}
|
||||
|
@@ -64,9 +64,9 @@ void createNewPopup(wlr_xdg_popup* popup, SXDGPopup* pHyprPopup) {
|
||||
|
||||
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||
|
||||
wlr_box box = {.x = PMONITOR->vecPosition.x - pHyprPopup->lx, .y = PMONITOR->vecPosition.y - pHyprPopup->ly, .width = PMONITOR->vecSize.x, .height = PMONITOR->vecSize.y};
|
||||
CBox box = {PMONITOR->vecPosition.x - pHyprPopup->lx, PMONITOR->vecPosition.y - pHyprPopup->ly, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||
|
||||
wlr_xdg_popup_unconstrain_from_box(popup, &box);
|
||||
wlr_xdg_popup_unconstrain_from_box(popup, box.pWlr());
|
||||
|
||||
pHyprPopup->monitor = PMONITOR;
|
||||
|
||||
@@ -159,13 +159,16 @@ void Events::listener_mapPopupXDG(void* owner, void* data) {
|
||||
int lx = 0, ly = 0;
|
||||
addPopupGlobalCoords(PPOPUP, &lx, &ly);
|
||||
|
||||
wlr_box extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents);
|
||||
CBox extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr());
|
||||
extents.applyFromWlr();
|
||||
|
||||
g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2);
|
||||
|
||||
if (PPOPUP->monitor)
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->scale);
|
||||
if (PPOPUP->monitor) {
|
||||
g_pCompositor->setPreferredScaleForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->scale);
|
||||
g_pCompositor->setPreferredTransformForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->transform);
|
||||
}
|
||||
|
||||
Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode {:x}", (uintptr_t)PPOPUP->pSurfaceTree);
|
||||
}
|
||||
@@ -178,11 +181,18 @@ void Events::listener_repositionPopupXDG(void* owner, void* data) {
|
||||
int lx = 0, ly = 0;
|
||||
addPopupGlobalCoords(PPOPUP, &lx, &ly);
|
||||
|
||||
wlr_box extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents);
|
||||
CBox extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr());
|
||||
extents.applyFromWlr();
|
||||
|
||||
PPOPUP->lastPos = {lx - extents.x, ly - extents.y};
|
||||
PPOPUP->repositionRequested = true;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||
|
||||
CBox box = {PMONITOR->vecPosition.x - lx + PPOPUP->popup->current.geometry.x, PMONITOR->vecPosition.y - ly + PPOPUP->popup->current.geometry.y, PMONITOR->vecSize.x,
|
||||
PMONITOR->vecSize.y};
|
||||
wlr_xdg_popup_unconstrain_from_box(PPOPUP->popup, box.pWlr());
|
||||
}
|
||||
|
||||
void Events::listener_unmapPopupXDG(void* owner, void* data) {
|
||||
@@ -199,8 +209,9 @@ void Events::listener_unmapPopupXDG(void* owner, void* data) {
|
||||
int lx = 0, ly = 0;
|
||||
addPopupGlobalCoords(PPOPUP, &lx, &ly);
|
||||
|
||||
wlr_box extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents);
|
||||
CBox extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr());
|
||||
extents.applyFromWlr();
|
||||
|
||||
g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2);
|
||||
|
||||
@@ -225,8 +236,9 @@ void Events::listener_commitPopupXDG(void* owner, void* data) {
|
||||
int lx = 0, ly = 0;
|
||||
addPopupGlobalCoords(PPOPUP, &lx, &ly);
|
||||
|
||||
wlr_box extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents);
|
||||
CBox extents;
|
||||
wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr());
|
||||
extents.applyFromWlr();
|
||||
|
||||
if (PPOPUP->repositionRequested)
|
||||
g_pHyprRenderer->damageBox(PPOPUP->lastPos.x, PPOPUP->lastPos.y, extents.width + 2, extents.height + 2);
|
||||
|
@@ -46,6 +46,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
static auto* const PSWALLOW = &g_pConfigManager->getConfigValuePtr("misc:enable_swallow")->intValue;
|
||||
static auto* const PSWALLOWREGEX = &g_pConfigManager->getConfigValuePtr("misc:swallow_regex")->strValue;
|
||||
static auto* const PSWALLOWEXREGEX = &g_pConfigManager->getConfigValuePtr("misc:swallow_exception_regex")->strValue;
|
||||
static auto* const PNEWTAKESOVERFS = &g_pConfigManager->getConfigValuePtr("misc:new_window_takes_over_fullscreen")->intValue;
|
||||
|
||||
auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||
const auto PWORKSPACE =
|
||||
@@ -95,7 +96,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
|
||||
if (PWORKSPACE->m_bDefaultPseudo) {
|
||||
PWINDOW->m_bIsPseudotiled = true;
|
||||
wlr_box desiredGeometry = {0};
|
||||
CBox desiredGeometry = {0};
|
||||
g_pXWaylandManager->getGeometryForWindow(PWINDOW, &desiredGeometry);
|
||||
PWINDOW->m_vPseudoSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
|
||||
}
|
||||
@@ -116,7 +117,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->m_szInitialClass = g_pXWaylandManager->getAppIDClass(PWINDOW);
|
||||
|
||||
for (auto& r : WINDOWRULES) {
|
||||
if (r.szRule.find("monitor") == 0) {
|
||||
if (r.szRule.starts_with("monitor")) {
|
||||
try {
|
||||
const auto MONITORSTR = removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find(' ')));
|
||||
|
||||
@@ -150,7 +151,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
|
||||
Debug::log(LOG, "Rule monitor, applying to {:mw}", PWINDOW);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Rule monitor failed, rule: {} -> {} | err: {}", r.szRule, r.szValue, e.what()); }
|
||||
} else if (r.szRule.find("workspace") == 0) {
|
||||
} else if (r.szRule.starts_with("workspace")) {
|
||||
// check if it isnt unset
|
||||
const auto WORKSPACERQ = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
||||
|
||||
@@ -166,19 +167,19 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
requestedWorkspace = "";
|
||||
|
||||
Debug::log(LOG, "Rule workspace matched by {}, {} applied.", PWINDOW, r.szValue);
|
||||
} else if (r.szRule.find("float") == 0) {
|
||||
} else if (r.szRule.starts_with("float")) {
|
||||
PWINDOW->m_bIsFloating = true;
|
||||
} else if (r.szRule.find("tile") == 0) {
|
||||
} else if (r.szRule.starts_with("tile")) {
|
||||
PWINDOW->m_bIsFloating = false;
|
||||
} else if (r.szRule.find("pseudo") == 0) {
|
||||
} else if (r.szRule.starts_with("pseudo")) {
|
||||
PWINDOW->m_bIsPseudotiled = true;
|
||||
} else if (r.szRule.find("nofocus") == 0) {
|
||||
} else if (r.szRule.starts_with("nofocus")) {
|
||||
PWINDOW->m_bNoFocus = true;
|
||||
} else if (r.szRule.find("noinitialfocus") == 0) {
|
||||
} else if (r.szRule.starts_with("noinitialfocus")) {
|
||||
PWINDOW->m_bNoInitialFocus = true;
|
||||
} else if (r.szRule.find("nofullscreenrequest") == 0) {
|
||||
} else if (r.szRule.starts_with("nofullscreenrequest")) {
|
||||
PWINDOW->m_bNoFullscreenRequest = true;
|
||||
} else if (r.szRule.find("nomaximizerequest") == 0) {
|
||||
} else if (r.szRule.starts_with("nomaximizerequest")) {
|
||||
PWINDOW->m_bNoMaximizeRequest = true;
|
||||
} else if (r.szRule == "fullscreen") {
|
||||
requestsFullscreen = true;
|
||||
@@ -198,7 +199,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
overridingNoMaximize = true;
|
||||
} else if (r.szRule == "stayfocused") {
|
||||
PWINDOW->m_bStayFocused = true;
|
||||
} else if (r.szRule.find("group") == 0) {
|
||||
} else if (r.szRule.starts_with("group")) {
|
||||
if (PWINDOW->m_eGroupRules & GROUP_OVERRIDE)
|
||||
continue;
|
||||
|
||||
@@ -245,7 +246,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
}
|
||||
vPrev = v;
|
||||
}
|
||||
} else if (r.szRule.find("idleinhibit") == 0) {
|
||||
} else if (r.szRule.starts_with("idleinhibit")) {
|
||||
auto IDLERULE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
||||
|
||||
if (IDLERULE == "none") {
|
||||
@@ -263,13 +264,6 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->applyDynamicRule(r);
|
||||
}
|
||||
|
||||
CWindow* pFullscreenWindow = nullptr;
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFloating) {
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
pFullscreenWindow = PFULLWINDOW;
|
||||
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, PWORKSPACE->m_efFullscreenMode);
|
||||
}
|
||||
|
||||
PWINDOW->updateSpecialRenderData();
|
||||
|
||||
// disallow tiled pinned
|
||||
@@ -279,7 +273,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
const CVarList WORKSPACEARGS = CVarList(requestedWorkspace, 0, ' ');
|
||||
|
||||
if (!WORKSPACEARGS[0].empty()) {
|
||||
if (WORKSPACEARGS[WORKSPACEARGS.size() - 1].find("silent") == 0)
|
||||
if (WORKSPACEARGS[WORKSPACEARGS.size() - 1].starts_with("silent"))
|
||||
workspaceSilent = true;
|
||||
|
||||
std::string requestedWorkspaceName;
|
||||
@@ -315,7 +309,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
|
||||
// size and move rules
|
||||
for (auto& r : WINDOWRULES) {
|
||||
if (r.szRule.find("size") == 0) {
|
||||
if (r.szRule.starts_with("size")) {
|
||||
try {
|
||||
const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1);
|
||||
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
|
||||
@@ -337,7 +331,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
|
||||
PWINDOW->setHidden(false);
|
||||
} catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r.szRule, r.szValue); }
|
||||
} else if (r.szRule.find("minsize") == 0) {
|
||||
} else if (r.szRule.starts_with("minsize")) {
|
||||
try {
|
||||
const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1);
|
||||
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
|
||||
@@ -351,7 +345,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
|
||||
PWINDOW->setHidden(false);
|
||||
} catch (...) { Debug::log(LOG, "Rule minsize failed, rule: {} -> {}", r.szRule, r.szValue); }
|
||||
} else if (r.szRule.find("maxsize") == 0) {
|
||||
} else if (r.szRule.starts_with("maxsize")) {
|
||||
try {
|
||||
const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1);
|
||||
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
|
||||
@@ -365,16 +359,16 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
|
||||
PWINDOW->setHidden(false);
|
||||
} catch (...) { Debug::log(LOG, "Rule maxsize failed, rule: {} -> {}", r.szRule, r.szValue); }
|
||||
} else if (r.szRule.find("move") == 0) {
|
||||
} else if (r.szRule.starts_with("move")) {
|
||||
try {
|
||||
auto value = r.szRule.substr(r.szRule.find(' ') + 1);
|
||||
|
||||
const bool ONSCREEN = value.find("onscreen") == 0;
|
||||
const bool ONSCREEN = value.starts_with("onscreen");
|
||||
|
||||
if (ONSCREEN)
|
||||
value = value.substr(value.find_first_of(' ') + 1);
|
||||
|
||||
const bool CURSOR = value.find("cursor") == 0;
|
||||
const bool CURSOR = value.starts_with("cursor");
|
||||
|
||||
if (CURSOR)
|
||||
value = value.substr(value.find_first_of(' ') + 1);
|
||||
@@ -385,7 +379,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
int posX = 0;
|
||||
int posY = 0;
|
||||
|
||||
if (POSXSTR.find("100%-") == 0) {
|
||||
if (POSXSTR.starts_with("100%-")) {
|
||||
const auto POSXRAW = POSXSTR.substr(5);
|
||||
posX =
|
||||
PMONITOR->vecSize.x - (!POSXRAW.contains('%') ? std::stoi(POSXRAW) : std::stof(POSXRAW.substr(0, POSXRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
|
||||
@@ -404,7 +398,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
}
|
||||
}
|
||||
|
||||
if (POSYSTR.find("100%-") == 0) {
|
||||
if (POSYSTR.starts_with("100%-")) {
|
||||
const auto POSYRAW = POSYSTR.substr(5);
|
||||
posY =
|
||||
PMONITOR->vecSize.y - (!POSYRAW.contains('%') ? std::stoi(POSYRAW) : std::stof(POSYRAW.substr(0, POSYRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
|
||||
@@ -439,7 +433,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
|
||||
PWINDOW->setHidden(false);
|
||||
} catch (...) { Debug::log(LOG, "Rule move failed, rule: {} -> {}", r.szRule, r.szValue); }
|
||||
} else if (r.szRule.find("center") == 0) {
|
||||
} else if (r.szRule.starts_with("center")) {
|
||||
auto RESERVEDOFFSET = Vector2D();
|
||||
const auto ARGS = CVarList(r.szRule, 2, ' ');
|
||||
if (ARGS[1] == "1")
|
||||
@@ -474,6 +468,16 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
const auto PLSFROMFOCUS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus);
|
||||
if (PLSFROMFOCUS && PLSFROMFOCUS->layerSurface->current.keyboard_interactive)
|
||||
PWINDOW->m_bNoInitialFocus = true;
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !requestsFullscreen && !PWINDOW->m_bIsFloating) {
|
||||
if (*PNEWTAKESOVERFS == 0)
|
||||
PWINDOW->m_bNoInitialFocus = true;
|
||||
else if (*PNEWTAKESOVERFS == 2)
|
||||
g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), false, FULLSCREEN_INVALID);
|
||||
else if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED)
|
||||
requestsMaximize = true;
|
||||
else
|
||||
requestsFullscreen = true;
|
||||
}
|
||||
|
||||
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus &&
|
||||
(PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))) && !workspaceSilent &&
|
||||
@@ -500,6 +504,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->hyprListener_requestResize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_resize, &Events::listener_requestResize, PWINDOW, "XDG Window Late");
|
||||
PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW,
|
||||
"XDG Window Late");
|
||||
PWINDOW->hyprListener_ackConfigure.initCallback(&PWINDOW->m_uSurface.xdg->events.ack_configure, &Events::listener_ackConfigure, PWINDOW, "XDG Window Late");
|
||||
} else {
|
||||
PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW,
|
||||
"XWayland Window Late");
|
||||
@@ -543,10 +548,6 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
}
|
||||
}
|
||||
|
||||
if (pFullscreenWindow && workspaceSilent) {
|
||||
g_pCompositor->setWindowFullscreen(pFullscreenWindow, true, PWORKSPACE->m_efFullscreenMode);
|
||||
}
|
||||
|
||||
// recheck idle inhibitors
|
||||
g_pInputManager->recheckIdleInhibitorStatus();
|
||||
|
||||
@@ -642,8 +643,18 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
|
||||
// recalc the values for this window
|
||||
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
|
||||
// avoid this window being visible
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFullscreen && !PWINDOW->m_bIsFloating)
|
||||
PWINDOW->m_fAlpha.setValueAndWarp(0.f);
|
||||
|
||||
g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale);
|
||||
g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale);
|
||||
g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform);
|
||||
|
||||
if (g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal()) == g_pCompositor->m_pLastWindow)
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
|
||||
// fix some xwayland apps that don't behave nicely
|
||||
PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize;
|
||||
}
|
||||
|
||||
void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
@@ -657,6 +668,13 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
if (PMONITOR) {
|
||||
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec() - PMONITOR->vecPosition;
|
||||
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec();
|
||||
PWINDOW->m_eOriginalClosedExtents = PWINDOW->getFullWindowExtents();
|
||||
}
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"closewindow", std::format("{:x}", PWINDOW)});
|
||||
EMIT_HOOK_EVENT("closeWindow", PWINDOW);
|
||||
|
||||
@@ -672,6 +690,7 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
PWINDOW->hyprListener_requestMove.removeCallback();
|
||||
PWINDOW->hyprListener_requestResize.removeCallback();
|
||||
PWINDOW->hyprListener_fullscreenWindow.removeCallback();
|
||||
PWINDOW->hyprListener_ackConfigure.removeCallback();
|
||||
} else {
|
||||
Debug::log(LOG, "Unregistered late callbacks XWL");
|
||||
PWINDOW->hyprListener_fullscreenWindow.removeCallback();
|
||||
@@ -685,13 +704,6 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
if (PWINDOW->m_bIsFullscreen)
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL);
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
if (PMONITOR) {
|
||||
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec() - PMONITOR->vecPosition;
|
||||
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec();
|
||||
PWINDOW->m_eOriginalClosedExtents = PWINDOW->getFullWindowExtents();
|
||||
}
|
||||
|
||||
// Allow the renderer to catch the last frame.
|
||||
g_pHyprOpenGL->makeWindowSnapshot(PWINDOW);
|
||||
|
||||
@@ -731,13 +743,17 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
|
||||
Debug::log(LOG, "On closed window, new focused candidate is {}", PWINDOWCANDIDATE);
|
||||
|
||||
if (PWINDOWCANDIDATE != g_pCompositor->m_pLastWindow) {
|
||||
if (!PWINDOWCANDIDATE)
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
else
|
||||
g_pCompositor->focusWindow(PWINDOWCANDIDATE);
|
||||
} else {
|
||||
if (PWINDOWCANDIDATE != g_pCompositor->m_pLastWindow && PWINDOWCANDIDATE)
|
||||
g_pCompositor->focusWindow(PWINDOWCANDIDATE);
|
||||
|
||||
if (g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal()) == PWINDOWCANDIDATE)
|
||||
g_pInputManager->simulateMouseMovement();
|
||||
|
||||
// CWindow::onUnmap will remove this window's active status, but we can't really do it above.
|
||||
if (PWINDOW == g_pCompositor->m_pLastWindow || !g_pCompositor->m_pLastWindow) {
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", ","});
|
||||
EMIT_HOOK_EVENT("activeWindow", (CWindow*)nullptr);
|
||||
}
|
||||
} else {
|
||||
Debug::log(LOG, "Unmapped was not focused, ignoring a refocus.");
|
||||
@@ -774,12 +790,33 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
PWINDOW->onUnmap();
|
||||
}
|
||||
|
||||
void Events::listener_ackConfigure(void* owner, void* data) {
|
||||
CWindow* PWINDOW = (CWindow*)owner;
|
||||
const auto E = (wlr_xdg_surface_configure*)data;
|
||||
|
||||
// find last matching serial
|
||||
const auto SERIAL = std::find_if(PWINDOW->m_vPendingSizeAcks.rbegin(), PWINDOW->m_vPendingSizeAcks.rend(), [&](const auto& e) { return e.first == E->serial; });
|
||||
|
||||
if (SERIAL == PWINDOW->m_vPendingSizeAcks.rend())
|
||||
return;
|
||||
|
||||
PWINDOW->m_pPendingSizeAck = *SERIAL;
|
||||
std::erase_if(PWINDOW->m_vPendingSizeAcks, [&](const auto& el) { return el.first == SERIAL->first; });
|
||||
}
|
||||
|
||||
void Events::listener_commitWindow(void* owner, void* data) {
|
||||
CWindow* PWINDOW = (CWindow*)owner;
|
||||
|
||||
if (!PWINDOW->m_bMappedX11 || PWINDOW->isHidden() || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11))
|
||||
return;
|
||||
|
||||
if (PWINDOW->m_bIsX11)
|
||||
PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged.
|
||||
else if (PWINDOW->m_pPendingSizeAck.has_value()) {
|
||||
PWINDOW->m_vReportedSize = PWINDOW->m_pPendingSizeAck->second;
|
||||
PWINDOW->m_pPendingSizeAck.reset();
|
||||
}
|
||||
|
||||
PWINDOW->updateSurfaceOutputs();
|
||||
|
||||
g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y,
|
||||
@@ -839,8 +876,8 @@ void Events::listener_destroyWindow(void* owner, void* data) {
|
||||
PWINDOW->m_bReadyToDelete = true;
|
||||
|
||||
if (!PWINDOW->m_bFadingOut) {
|
||||
g_pCompositor->removeWindowFromVectorSafe(PWINDOW); // most likely X11 unmanaged or sumn
|
||||
Debug::log(LOG, "Unmapped {} removed instantly", PWINDOW);
|
||||
g_pCompositor->removeWindowFromVectorSafe(PWINDOW); // most likely X11 unmanaged or sumn
|
||||
}
|
||||
}
|
||||
|
||||
@@ -997,6 +1034,7 @@ void Events::listener_configureX11(void* owner, void* data) {
|
||||
|
||||
if (!PWINDOW->m_uSurface.xwayland->surface || !PWINDOW->m_uSurface.xwayland->surface->mapped || !PWINDOW->m_bMappedX11) {
|
||||
wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height);
|
||||
PWINDOW->m_vReportedSize = {E->width, E->height};
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1021,8 +1059,11 @@ void Events::listener_configureX11(void* owner, void* data) {
|
||||
|
||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
||||
if (*PXWLFORCESCALEZERO) {
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR)
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) {
|
||||
const Vector2D DELTA = PWINDOW->m_vRealSize.goalv() - PWINDOW->m_vRealSize.goalv() / PMONITOR->scale;
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale);
|
||||
PWINDOW->m_vRealPosition.setValueAndWarp(PWINDOW->m_vRealPosition.goalv() + DELTA / 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
|
||||
@@ -1042,6 +1083,8 @@ void Events::listener_configureX11(void* owner, void* data) {
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
|
||||
PWINDOW->m_vReportedSize = {E->width, E->height};
|
||||
}
|
||||
|
||||
void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
||||
@@ -1080,8 +1123,11 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->width, PWINDOW->m_uSurface.xwayland->height));
|
||||
|
||||
if (*PXWLFORCESCALEZERO) {
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR)
|
||||
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) {
|
||||
const Vector2D DELTA = PWINDOW->m_vRealSize.goalv() - PWINDOW->m_vRealSize.goalv() / PMONITOR->scale;
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale);
|
||||
PWINDOW->m_vRealPosition.setValueAndWarp(PWINDOW->m_vRealPosition.goalv() + DELTA / 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goalv();
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include "Vector2D.hpp"
|
||||
#include "Color.hpp"
|
||||
#include "../macros.hpp"
|
||||
#include "../debug/Log.hpp"
|
||||
|
||||
enum ANIMATEDVARTYPE
|
||||
{
|
||||
|
125
src/helpers/Box.cpp
Normal file
125
src/helpers/Box.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
#include "Box.hpp"
|
||||
wlr_box CBox::wlr() {
|
||||
CBox rounded = roundInternal();
|
||||
m_bWlrBox = wlr_box{(int)rounded.x, (int)rounded.y, (int)rounded.w, (int)rounded.h};
|
||||
return m_bWlrBox;
|
||||
}
|
||||
|
||||
wlr_box* CBox::pWlr() {
|
||||
CBox rounded = roundInternal();
|
||||
m_bWlrBox = wlr_box{(int)rounded.x, (int)rounded.y, (int)rounded.w, (int)rounded.h};
|
||||
return &m_bWlrBox;
|
||||
}
|
||||
|
||||
CBox& CBox::scale(double scale) {
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
w *= scale;
|
||||
h *= scale;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::scale(const Vector2D& scale) {
|
||||
x *= scale.x;
|
||||
y *= scale.y;
|
||||
w *= scale.x;
|
||||
h *= scale.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::translate(const Vector2D& vec) {
|
||||
x += vec.x;
|
||||
y += vec.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector2D CBox::middle() const {
|
||||
return Vector2D{x + w / 2.0, y + h / 2.0};
|
||||
}
|
||||
|
||||
bool CBox::containsPoint(const Vector2D& vec) const {
|
||||
return VECINRECT(vec, x, y, x + w, y + h);
|
||||
}
|
||||
|
||||
bool CBox::empty() const {
|
||||
return w == 0 || h == 0;
|
||||
}
|
||||
|
||||
CBox& CBox::applyFromWlr() {
|
||||
x = m_bWlrBox.x;
|
||||
y = m_bWlrBox.y;
|
||||
w = m_bWlrBox.width;
|
||||
h = m_bWlrBox.height;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::round() {
|
||||
float newW = x + w - std::round(x);
|
||||
float newH = y + h - std::round(y);
|
||||
x = std::round(x);
|
||||
y = std::round(y);
|
||||
w = std::round(newW);
|
||||
h = std::round(newH);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::transform(const wl_output_transform t, double w, double h) {
|
||||
wlr_box_transform(&m_bWlrBox, pWlr(), t, w, h);
|
||||
applyFromWlr();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::addExtents(const SWindowDecorationExtents& e) {
|
||||
x -= e.topLeft.x;
|
||||
y -= e.topLeft.y;
|
||||
w += e.topLeft.x + e.bottomRight.x;
|
||||
h += e.topLeft.y + e.bottomRight.y;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::scaleFromCenter(double scale) {
|
||||
double oldW = w, oldH = h;
|
||||
|
||||
w *= scale;
|
||||
h *= scale;
|
||||
|
||||
x -= (w - oldW) / 2.0;
|
||||
y -= (h - oldH) / 2.0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox& CBox::expand(const double& value) {
|
||||
x -= value;
|
||||
y -= value;
|
||||
w += value * 2.0;
|
||||
h += value * 2.0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBox CBox::roundInternal() {
|
||||
float newW = x + w - std::floor(x);
|
||||
float newH = y + h - std::floor(y);
|
||||
|
||||
return CBox{std::floor(x), std::floor(y), std::floor(newW), std::floor(newH)};
|
||||
}
|
||||
|
||||
Vector2D CBox::pos() const {
|
||||
return {x, y};
|
||||
}
|
||||
|
||||
Vector2D CBox::size() const {
|
||||
return {w, h};
|
||||
}
|
||||
|
||||
SWindowDecorationExtents CBox::extentsFrom(const CBox& small) {
|
||||
return {{small.x - x, small.y - y}, {w - small.w - (small.x - x), h - small.h - (small.y - y)}};
|
||||
}
|
83
src/helpers/Box.hpp
Normal file
83
src/helpers/Box.hpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
#include "Vector2D.hpp"
|
||||
#include "../SharedDefs.hpp"
|
||||
#include "../includes.hpp"
|
||||
|
||||
class CBox {
|
||||
public:
|
||||
CBox(double x_, double y_, double w_, double h_) {
|
||||
x = x_;
|
||||
y = y_;
|
||||
w = w_;
|
||||
h = h_;
|
||||
}
|
||||
|
||||
CBox() {
|
||||
w = 0;
|
||||
h = 0;
|
||||
}
|
||||
|
||||
CBox(const wlr_box& box) {
|
||||
x = box.x;
|
||||
y = box.y;
|
||||
w = box.width;
|
||||
h = box.height;
|
||||
}
|
||||
|
||||
CBox(const double d) {
|
||||
x = d;
|
||||
y = d;
|
||||
w = d;
|
||||
h = d;
|
||||
}
|
||||
|
||||
CBox(const Vector2D& pos, const Vector2D& size) {
|
||||
x = pos.x;
|
||||
y = pos.y;
|
||||
w = size.x;
|
||||
h = size.y;
|
||||
}
|
||||
|
||||
wlr_box wlr();
|
||||
wlr_box* pWlr();
|
||||
|
||||
CBox& applyFromWlr();
|
||||
CBox& scale(double scale);
|
||||
CBox& scaleFromCenter(double scale);
|
||||
CBox& scale(const Vector2D& scale);
|
||||
CBox& translate(const Vector2D& vec);
|
||||
CBox& round();
|
||||
CBox& transform(const wl_output_transform t, double w, double h);
|
||||
CBox& addExtents(const SWindowDecorationExtents& e);
|
||||
CBox& expand(const double& value);
|
||||
|
||||
SWindowDecorationExtents extentsFrom(const CBox&); // this is the big box
|
||||
|
||||
Vector2D middle() const;
|
||||
Vector2D pos() const;
|
||||
Vector2D size() const;
|
||||
|
||||
bool containsPoint(const Vector2D& vec) const;
|
||||
bool empty() const;
|
||||
|
||||
double x = 0, y = 0;
|
||||
union {
|
||||
double w;
|
||||
double width;
|
||||
};
|
||||
union {
|
||||
double h;
|
||||
double height;
|
||||
};
|
||||
|
||||
//
|
||||
bool operator==(const CBox& rhs) const {
|
||||
return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h;
|
||||
}
|
||||
|
||||
private:
|
||||
CBox roundInternal();
|
||||
|
||||
wlr_box m_bWlrBox;
|
||||
};
|
@@ -5,7 +5,7 @@
|
||||
class CColor {
|
||||
public:
|
||||
CColor();
|
||||
CColor(float, float, float, float);
|
||||
CColor(float r, float g, float b, float a);
|
||||
CColor(uint64_t);
|
||||
|
||||
float r = 0, g = 0, b = 0, a = 1.f;
|
||||
@@ -27,4 +27,8 @@ class CColor {
|
||||
bool operator==(const CColor& c2) const {
|
||||
return r == c2.r && g == c2.g && b == c2.b && a == c2.a;
|
||||
}
|
||||
|
||||
CColor stripA() const {
|
||||
return {r, g, b, 1};
|
||||
}
|
||||
};
|
||||
|
@@ -2,11 +2,14 @@
|
||||
#include "../defines.hpp"
|
||||
#include <algorithm>
|
||||
#include "../Compositor.hpp"
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <sys/utsname.h>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#ifdef HAS_EXECINFO
|
||||
#include <execinfo.h>
|
||||
#endif
|
||||
|
||||
#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
#include <sys/sysctl.h>
|
||||
@@ -182,13 +185,6 @@ std::string escapeJSONStrings(const std::string& str) {
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
void scaleBox(wlr_box* box, float scale) {
|
||||
box->width = std::round(box->width * scale);
|
||||
box->height = std::round(box->height * scale);
|
||||
box->x = std::round(box->x * scale);
|
||||
box->y = std::round(box->y * scale);
|
||||
}
|
||||
|
||||
std::string removeBeginEndSpacesTabs(std::string str) {
|
||||
if (str.empty())
|
||||
return str;
|
||||
@@ -246,9 +242,13 @@ bool isDirection(const std::string& arg) {
|
||||
return arg == "l" || arg == "r" || arg == "u" || arg == "d" || arg == "t" || arg == "b";
|
||||
}
|
||||
|
||||
bool isDirection(const char& arg) {
|
||||
return arg == 'l' || arg == 'r' || arg == 'u' || arg == 'd' || arg == 't' || arg == 'b';
|
||||
}
|
||||
|
||||
int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
int result = INT_MAX;
|
||||
if (in.find("special") == 0) {
|
||||
if (in.starts_with("special")) {
|
||||
outName = "special";
|
||||
|
||||
if (in.length() > 8) {
|
||||
@@ -262,7 +262,7 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
}
|
||||
|
||||
return SPECIAL_WORKSPACE_START;
|
||||
} else if (in.find("name:") == 0) {
|
||||
} else if (in.starts_with("name:")) {
|
||||
const auto WORKSPACENAME = in.substr(in.find_first_of(':') + 1);
|
||||
const auto WORKSPACE = g_pCompositor->getWorkspaceByName(WORKSPACENAME);
|
||||
if (!WORKSPACE) {
|
||||
@@ -271,14 +271,14 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
result = WORKSPACE->m_iID;
|
||||
}
|
||||
outName = WORKSPACENAME;
|
||||
} else if (in.find("empty") == 0) {
|
||||
} else if (in.starts_with("empty")) {
|
||||
int id = 0;
|
||||
while (++id < INT_MAX) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id);
|
||||
if (!PWORKSPACE || (g_pCompositor->getWindowsOnWorkspace(id) == 0))
|
||||
return id;
|
||||
}
|
||||
} else if (in.find("prev") == 0) {
|
||||
} else if (in.starts_with("prev")) {
|
||||
if (!g_pCompositor->m_pLastMonitor)
|
||||
return INT_MAX;
|
||||
|
||||
@@ -389,12 +389,12 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
int beginID = finalWSID;
|
||||
int curID = finalWSID;
|
||||
while (--curID > 0 && remainingWSes > 0) {
|
||||
if (invalidWSes.find(curID) == invalidWSes.end()) {
|
||||
if (!invalidWSes.contains(curID)) {
|
||||
remainingWSes--;
|
||||
}
|
||||
finalWSID = curID;
|
||||
}
|
||||
if (finalWSID <= 0 || invalidWSes.find(finalWSID) != invalidWSes.end()) {
|
||||
if (finalWSID <= 0 || invalidWSes.contains(finalWSID)) {
|
||||
if (namedWSes.size()) {
|
||||
// Go to the named workspaces
|
||||
// Need remainingWSes more
|
||||
@@ -414,7 +414,7 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
if (walkDir == '+') {
|
||||
int curID = finalWSID;
|
||||
while (++curID < INT32_MAX && remainingWSes > 0) {
|
||||
if (invalidWSes.find(curID) == invalidWSes.end()) {
|
||||
if (!invalidWSes.contains(curID)) {
|
||||
remainingWSes--;
|
||||
}
|
||||
finalWSID = curID;
|
||||
@@ -501,6 +501,43 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::optional<std::string> cleanCmdForWorkspace(const std::string& inWorkspaceName, std::string dirtyCmd) {
|
||||
|
||||
std::string cmd = removeBeginEndSpacesTabs(dirtyCmd);
|
||||
|
||||
if (!cmd.empty()) {
|
||||
std::string rules;
|
||||
const std::string workspaceRule = "workspace " + inWorkspaceName;
|
||||
|
||||
if (cmd[0] == '[') {
|
||||
const int closingBracketIdx = cmd.find_last_of(']');
|
||||
auto tmpRules = cmd.substr(1, closingBracketIdx - 1);
|
||||
cmd = cmd.substr(closingBracketIdx + 1);
|
||||
|
||||
auto rulesList = CVarList(tmpRules, 0, ';');
|
||||
|
||||
bool hadWorkspaceRule = false;
|
||||
rulesList.map([&](std::string& rule) {
|
||||
if (rule.find("workspace") == 0) {
|
||||
rule = workspaceRule;
|
||||
hadWorkspaceRule = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!hadWorkspaceRule)
|
||||
rulesList.append(workspaceRule);
|
||||
|
||||
rules = "[" + rulesList.join(";") + "]";
|
||||
} else {
|
||||
rules = "[" + workspaceRule + "]";
|
||||
}
|
||||
|
||||
return std::optional<std::string>(rules + " " + cmd);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2) {
|
||||
const float DX = std::max({0.0, p1.x - vec.x, vec.x - p2.x});
|
||||
const float DY = std::max({0.0, p1.y - vec.y, vec.y - p2.y});
|
||||
@@ -626,11 +663,11 @@ int64_t getPPIDof(int64_t pid) {
|
||||
}
|
||||
|
||||
int64_t configStringToInt(const std::string& VALUE) {
|
||||
if (VALUE.find("0x") == 0) {
|
||||
if (VALUE.starts_with("0x")) {
|
||||
// Values with 0x are hex
|
||||
const auto VALUEWITHOUTHEX = VALUE.substr(2);
|
||||
return stol(VALUEWITHOUTHEX, nullptr, 16);
|
||||
} else if (VALUE.find("rgba(") == 0 && VALUE.find(')') == VALUE.length() - 1) {
|
||||
} else if (VALUE.starts_with("rgba(") && VALUE.ends_with(')')) {
|
||||
const auto VALUEWITHOUTFUNC = VALUE.substr(5, VALUE.length() - 6);
|
||||
|
||||
if (removeBeginEndSpacesTabs(VALUEWITHOUTFUNC).length() != 8) {
|
||||
@@ -642,7 +679,7 @@ int64_t configStringToInt(const std::string& VALUE) {
|
||||
|
||||
// now we need to RGBA -> ARGB. The config holds ARGB only.
|
||||
return (RGBA >> 8) + 0x1000000 * (RGBA & 0xFF);
|
||||
} else if (VALUE.find("rgb(") == 0 && VALUE.find(')') == VALUE.length() - 1) {
|
||||
} else if (VALUE.starts_with("rgb(") && VALUE.ends_with(')')) {
|
||||
const auto VALUEWITHOUTFUNC = VALUE.substr(4, VALUE.length() - 5);
|
||||
|
||||
if (removeBeginEndSpacesTabs(VALUEWITHOUTFUNC).length() != 6) {
|
||||
@@ -653,9 +690,9 @@ int64_t configStringToInt(const std::string& VALUE) {
|
||||
const auto RGB = std::stol(VALUEWITHOUTFUNC, nullptr, 16);
|
||||
|
||||
return RGB + 0xFF000000; // 0xFF for opaque
|
||||
} else if (VALUE.find("true") == 0 || VALUE.find("on") == 0 || VALUE.find("yes") == 0) {
|
||||
} else if (VALUE.starts_with("true") || VALUE.starts_with("on") || VALUE.starts_with("yes")) {
|
||||
return 1;
|
||||
} else if (VALUE.find("false") == 0 || VALUE.find("off") == 0 || VALUE.find("no") == 0) {
|
||||
} else if (VALUE.starts_with("false") || VALUE.starts_with("off") || VALUE.starts_with("no")) {
|
||||
return 0;
|
||||
}
|
||||
return std::stoll(VALUE);
|
||||
@@ -689,9 +726,10 @@ std::string replaceInString(std::string subject, const std::string& search, cons
|
||||
std::vector<SCallstackFrameInfo> getBacktrace() {
|
||||
std::vector<SCallstackFrameInfo> callstack;
|
||||
|
||||
void* bt[1024];
|
||||
size_t btSize;
|
||||
char** btSymbols;
|
||||
#ifdef HAS_EXECINFO
|
||||
void* bt[1024];
|
||||
size_t btSize;
|
||||
char** btSymbols;
|
||||
|
||||
btSize = backtrace(bt, 1024);
|
||||
btSymbols = backtrace_symbols(bt, btSize);
|
||||
@@ -699,6 +737,9 @@ std::vector<SCallstackFrameInfo> getBacktrace() {
|
||||
for (size_t i = 0; i < btSize; ++i) {
|
||||
callstack.emplace_back(SCallstackFrameInfo{bt[i], std::string{btSymbols[i]}});
|
||||
}
|
||||
#else
|
||||
callstack.emplace_back(SCallstackFrameInfo{nullptr, "configuration does not support execinfo.h"});
|
||||
#endif
|
||||
|
||||
return callstack;
|
||||
}
|
||||
@@ -706,4 +747,21 @@ std::vector<SCallstackFrameInfo> getBacktrace() {
|
||||
void throwError(const std::string& err) {
|
||||
Debug::log(CRIT, "Critical error thrown: {}", err);
|
||||
throw std::runtime_error(err);
|
||||
}
|
||||
|
||||
uint32_t drmFormatToGL(uint32_t drm) {
|
||||
switch (drm) {
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
case DRM_FORMAT_XBGR8888: return GL_RGBA; // doesn't matter, opengl is gucci in this case.
|
||||
case DRM_FORMAT_XRGB2101010:
|
||||
case DRM_FORMAT_XBGR2101010:
|
||||
#ifdef GLES2
|
||||
return GL_RGB10_A2_EXT;
|
||||
#else
|
||||
return GL_RGB10_A2;
|
||||
#endif
|
||||
default: return GL_RGBA;
|
||||
}
|
||||
UNREACHABLE();
|
||||
return GL_RGBA;
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <wayland-server.h>
|
||||
#include <wlr/util/box.h>
|
||||
@@ -15,11 +16,12 @@ struct SCallstackFrameInfo {
|
||||
std::string absolutePath(const std::string&, const std::string&);
|
||||
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString);
|
||||
std::string escapeJSONStrings(const std::string& str);
|
||||
void scaleBox(wlr_box*, float);
|
||||
std::string removeBeginEndSpacesTabs(std::string);
|
||||
bool isNumber(const std::string&, bool allowfloat = false);
|
||||
bool isDirection(const std::string&);
|
||||
bool isDirection(const char&);
|
||||
int getWorkspaceIDFromString(const std::string&, std::string&);
|
||||
std::optional<std::string> cleanCmdForWorkspace(const std::string&, std::string);
|
||||
float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2);
|
||||
void logSystemInfo();
|
||||
std::string execAndGet(const char*);
|
||||
@@ -31,6 +33,7 @@ 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);
|
||||
|
||||
template <typename... Args>
|
||||
[[deprecated("use std::format instead")]] std::string getFormat(std::format_string<Args...> fmt, Args&&... args) {
|
||||
|
@@ -40,6 +40,8 @@ void CMonitor::onConnect(bool noRule) {
|
||||
hyprListener_monitorCommit.initCallback(&output->events.commit, &Events::listener_monitorCommit, this);
|
||||
hyprListener_monitorBind.initCallback(&output->events.bind, &Events::listener_monitorBind, this);
|
||||
|
||||
tearingState.canTear = wlr_backend_is_drm(output->backend); // tearing only works on drm
|
||||
|
||||
if (m_bEnabled) {
|
||||
wlr_output_enable(output, 1);
|
||||
wlr_output_commit(output);
|
||||
@@ -107,20 +109,20 @@ void CMonitor::onConnect(bool noRule) {
|
||||
m_bRenderingInitPassed = true;
|
||||
}
|
||||
|
||||
if (!m_pThisWrap) {
|
||||
std::shared_ptr<CMonitor>* thisWrapper = nullptr;
|
||||
|
||||
// find the wrap
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
if (m->ID == ID) {
|
||||
m_pThisWrap = &m;
|
||||
break;
|
||||
}
|
||||
// find the wrap
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
if (m->ID == ID) {
|
||||
thisWrapper = &m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()) {
|
||||
g_pCompositor->m_vMonitors.push_back(*m_pThisWrap);
|
||||
}
|
||||
RASSERT(thisWrapper->get(), "CMonitor::onConnect: Had no wrapper???");
|
||||
|
||||
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end())
|
||||
g_pCompositor->m_vMonitors.push_back(*thisWrapper);
|
||||
|
||||
m_bEnabled = true;
|
||||
|
||||
@@ -130,6 +132,8 @@ void CMonitor::onConnect(bool noRule) {
|
||||
if (!noRule)
|
||||
g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true);
|
||||
|
||||
wlr_output_commit(output);
|
||||
|
||||
wlr_damage_ring_set_bounds(&damage, vecTransformedSize.x, vecTransformedSize.y);
|
||||
|
||||
wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, scale);
|
||||
@@ -150,8 +154,6 @@ void CMonitor::onConnect(bool noRule) {
|
||||
if (scale < 0.1)
|
||||
scale = getDefaultScale();
|
||||
|
||||
m_pThisWrap = nullptr;
|
||||
|
||||
forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering.
|
||||
//
|
||||
|
||||
@@ -182,6 +184,8 @@ void CMonitor::onConnect(bool noRule) {
|
||||
g_pCompositor->setActiveMonitor(this);
|
||||
|
||||
renderTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, ratHandler, this);
|
||||
|
||||
g_pCompositor->scheduleFrameForMonitor(this);
|
||||
}
|
||||
|
||||
void CMonitor::onDisconnect() {
|
||||
@@ -219,9 +223,6 @@ void CMonitor::onDisconnect() {
|
||||
g_pConfigManager->m_bWantsMonitorReload = true;
|
||||
}
|
||||
|
||||
m_bEnabled = false;
|
||||
m_bRenderingInitPassed = false;
|
||||
|
||||
hyprListener_monitorFrame.removeCallback();
|
||||
hyprListener_monitorDamage.removeCallback();
|
||||
hyprListener_monitorNeedsFrame.removeCallback();
|
||||
@@ -243,9 +244,12 @@ void CMonitor::onDisconnect() {
|
||||
|
||||
if (!BACKUPMON) {
|
||||
Debug::log(WARN, "Unplugged last monitor, entering an unsafe state. Good luck my friend.");
|
||||
g_pCompositor->m_bUnsafeState = true;
|
||||
g_pCompositor->enterUnsafeState();
|
||||
}
|
||||
|
||||
m_bEnabled = false;
|
||||
m_bRenderingInitPassed = false;
|
||||
|
||||
if (BACKUPMON) {
|
||||
// snap cursor
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, BACKUPMON->vecPosition.x + BACKUPMON->vecTransformedSize.x / 2.f,
|
||||
@@ -254,7 +258,7 @@ void CMonitor::onDisconnect() {
|
||||
// move workspaces
|
||||
std::deque<CWorkspace*> wspToMove;
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (w->m_iMonitorID == ID) {
|
||||
if (w->m_iMonitorID == ID || !g_pCompositor->getMonitorFromID(w->m_iMonitorID)) {
|
||||
wspToMove.push_back(w.get());
|
||||
}
|
||||
}
|
||||
@@ -313,14 +317,14 @@ void CMonitor::addDamage(const CRegion* rg) {
|
||||
addDamage(const_cast<CRegion*>(rg)->pixman());
|
||||
}
|
||||
|
||||
void CMonitor::addDamage(const wlr_box* box) {
|
||||
void CMonitor::addDamage(const CBox* box) {
|
||||
static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue;
|
||||
if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) {
|
||||
wlr_damage_ring_add_whole(&damage);
|
||||
g_pCompositor->scheduleFrameForMonitor(this);
|
||||
}
|
||||
|
||||
if (wlr_damage_ring_add_box(&damage, box))
|
||||
if (wlr_damage_ring_add_box(&damage, const_cast<CBox*>(box)->pWlr()))
|
||||
g_pCompositor->scheduleFrameForMonitor(this);
|
||||
}
|
||||
|
||||
@@ -412,19 +416,22 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
|
||||
vecPosition = RULE.offset;
|
||||
|
||||
// push to mvmonitors
|
||||
if (!m_pThisWrap) {
|
||||
// find the wrap
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
if (m->ID == ID) {
|
||||
m_pThisWrap = &m;
|
||||
break;
|
||||
}
|
||||
|
||||
std::shared_ptr<CMonitor>* thisWrapper = nullptr;
|
||||
|
||||
// find the wrap
|
||||
for (auto& m : g_pCompositor->m_vRealMonitors) {
|
||||
if (m->ID == ID) {
|
||||
thisWrapper = &m;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RASSERT(thisWrapper->get(), "CMonitor::setMirror: Had no wrapper???");
|
||||
|
||||
if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) ==
|
||||
g_pCompositor->m_vMonitors.end()) {
|
||||
g_pCompositor->m_vMonitors.push_back(*m_pThisWrap);
|
||||
g_pCompositor->m_vMonitors.push_back(*thisWrapper);
|
||||
}
|
||||
|
||||
setupDefaultWS(RULE);
|
||||
@@ -552,6 +559,8 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool
|
||||
g_pHyprRenderer->damageMonitor(this);
|
||||
|
||||
g_pCompositor->updateFullscreenFadeOnWorkspace(pWorkspace);
|
||||
|
||||
g_pConfigManager->ensureVRR(this);
|
||||
}
|
||||
|
||||
void CMonitor::changeWorkspace(const int& id, bool internal) {
|
||||
|
@@ -61,10 +61,12 @@ class CMonitor {
|
||||
bool gammaChanged = false;
|
||||
float xwaylandScale = 1.f;
|
||||
|
||||
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;
|
||||
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;
|
||||
@@ -81,6 +83,18 @@ class CMonitor {
|
||||
|
||||
CRegion lastFrameDamage; // stores last frame damage
|
||||
|
||||
// for tearing
|
||||
CWindow* solitaryClient = nullptr;
|
||||
|
||||
struct {
|
||||
bool canTear = false;
|
||||
bool nextRenderTorn = false;
|
||||
bool activelyTearing = false;
|
||||
|
||||
bool busy = false;
|
||||
bool frameScheduledWhileBusy = false;
|
||||
} tearingState;
|
||||
|
||||
// for the special workspace. 0 means not open.
|
||||
int specialWorkspaceID = 0;
|
||||
|
||||
@@ -95,24 +109,23 @@ class CMonitor {
|
||||
DYNLISTENER(monitorBind);
|
||||
|
||||
// methods
|
||||
void onConnect(bool noRule);
|
||||
void onDisconnect();
|
||||
void addDamage(const pixman_region32_t* rg);
|
||||
void addDamage(const CRegion* rg);
|
||||
void addDamage(const wlr_box* box);
|
||||
void setMirror(const std::string&);
|
||||
bool isMirror();
|
||||
float getDefaultScale();
|
||||
void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false);
|
||||
void changeWorkspace(const int& id, bool internal = false);
|
||||
void setSpecialWorkspace(CWorkspace* const pWorkspace);
|
||||
void setSpecialWorkspace(const int& id);
|
||||
void moveTo(const Vector2D& pos);
|
||||
Vector2D middle();
|
||||
void onConnect(bool noRule);
|
||||
void onDisconnect();
|
||||
void addDamage(const pixman_region32_t* rg);
|
||||
void addDamage(const CRegion* rg);
|
||||
void addDamage(const CBox* box);
|
||||
void setMirror(const std::string&);
|
||||
bool isMirror();
|
||||
float getDefaultScale();
|
||||
void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false);
|
||||
void changeWorkspace(const int& id, bool internal = false);
|
||||
void setSpecialWorkspace(CWorkspace* const pWorkspace);
|
||||
void setSpecialWorkspace(const int& id);
|
||||
void moveTo(const Vector2D& pos);
|
||||
Vector2D middle();
|
||||
|
||||
std::shared_ptr<CMonitor>* m_pThisWrap = nullptr;
|
||||
bool m_bEnabled = false;
|
||||
bool m_bRenderingInitPassed = false;
|
||||
bool m_bEnabled = false;
|
||||
bool m_bRenderingInitPassed = false;
|
||||
|
||||
// For the list lookup
|
||||
|
||||
|
@@ -1,6 +1,8 @@
|
||||
#include "Region.hpp"
|
||||
extern "C" {
|
||||
#include <wlr/util/box.h>
|
||||
#include <wlr/util/region.h>
|
||||
}
|
||||
|
||||
CRegion::CRegion() {
|
||||
pixman_region32_init(&m_rRegion);
|
||||
@@ -19,6 +21,10 @@ CRegion::CRegion(wlr_box* box) {
|
||||
pixman_region32_init_rect(&m_rRegion, box->x, box->y, box->width, box->height);
|
||||
}
|
||||
|
||||
CRegion::CRegion(const CBox& box) {
|
||||
pixman_region32_init_rect(&m_rRegion, box.x, box.y, box.w, box.h);
|
||||
}
|
||||
|
||||
CRegion::CRegion(pixman_box32_t* box) {
|
||||
pixman_region32_init_rect(&m_rRegion, box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1);
|
||||
}
|
||||
@@ -57,6 +63,11 @@ CRegion& CRegion::add(double x, double y, double w, double h) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::add(const CBox& other) {
|
||||
pixman_region32_union_rect(&m_rRegion, &m_rRegion, other.x, other.y, other.w, other.h);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CRegion& CRegion::subtract(const CRegion& other) {
|
||||
pixman_region32_subtract(&m_rRegion, &m_rRegion, const_cast<CRegion*>(&other)->pixman());
|
||||
return *this;
|
||||
@@ -98,7 +109,7 @@ std::vector<pixman_box32_t> CRegion::getRects() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
wlr_box CRegion::getExtents() {
|
||||
CBox CRegion::getExtents() {
|
||||
pixman_box32_t* box = pixman_region32_extents(&m_rRegion);
|
||||
return {box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1};
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
#include <pixman.h>
|
||||
#include <vector>
|
||||
#include "Vector2D.hpp"
|
||||
#include "Box.hpp"
|
||||
|
||||
struct wlr_box;
|
||||
|
||||
@@ -15,6 +16,8 @@ class CRegion {
|
||||
CRegion(double x, double y, double w, double h);
|
||||
/* Create from a wlr_box */
|
||||
CRegion(wlr_box* box);
|
||||
/* Create from a CBox */
|
||||
CRegion(const CBox& box);
|
||||
/* Create from a pixman_box32_t */
|
||||
CRegion(pixman_box32_t* box);
|
||||
|
||||
@@ -37,13 +40,14 @@ class CRegion {
|
||||
CRegion& set(const CRegion& other);
|
||||
CRegion& add(const CRegion& other);
|
||||
CRegion& add(double x, double y, double w, double h);
|
||||
CRegion& add(const CBox& other);
|
||||
CRegion& subtract(const CRegion& other);
|
||||
CRegion& intersect(const CRegion& other);
|
||||
CRegion& intersect(double x, double y, double w, double h);
|
||||
CRegion& translate(const Vector2D& vec);
|
||||
CRegion& invert(pixman_box32_t* box);
|
||||
CRegion& scale(float scale);
|
||||
wlr_box getExtents();
|
||||
CBox getExtents();
|
||||
bool containsPoint(const Vector2D& vec) const;
|
||||
bool empty() const;
|
||||
Vector2D closestPoint(const Vector2D& vec) const;
|
||||
@@ -51,7 +55,7 @@ class CRegion {
|
||||
std::vector<pixman_box32_t> getRects() const;
|
||||
|
||||
pixman_region32_t* pixman() {
|
||||
return &m_rRegion;
|
||||
return &m_rRegion;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@@ -98,8 +98,9 @@ void SubsurfaceTree::destroySurfaceTree(SSurfaceTreeNode* pNode) {
|
||||
|
||||
// damage
|
||||
if (pNode->pSurface && pNode->pSurface->exists()) {
|
||||
wlr_box extents = {};
|
||||
wlr_surface_get_extends(pNode->pSurface->wlr(), &extents);
|
||||
CBox extents = {};
|
||||
wlr_surface_get_extends(pNode->pSurface->wlr(), extents.pWlr());
|
||||
extents.applyFromWlr();
|
||||
|
||||
int lx = 0, ly = 0;
|
||||
addSurfaceGlobalOffset(pNode, &lx, &ly);
|
||||
@@ -198,7 +199,7 @@ void Events::listener_unmapSubsurface(void* owner, void* data) {
|
||||
int lx = 0, ly = 0;
|
||||
addSurfaceGlobalOffset(PNODE, &lx, &ly);
|
||||
|
||||
wlr_box extents = {lx, ly, 0, 0};
|
||||
CBox extents = {lx, ly, 0, 0};
|
||||
|
||||
extents.width = PNODE->pSurface->wlr()->current.width;
|
||||
extents.height = PNODE->pSurface->wlr()->current.height;
|
||||
@@ -245,6 +246,29 @@ void Events::listener_commitSubsurface(void* owner, void* data) {
|
||||
|
||||
if (pNode->pSurface && pNode->pSurface->exists())
|
||||
g_pHyprRenderer->damageSurface(pNode->pSurface->wlr(), lx, ly, SCALE);
|
||||
|
||||
if (pNode->pWindowOwner) {
|
||||
if (pNode->pWindowOwner->m_bIsX11)
|
||||
pNode->pWindowOwner->m_vReportedSize = pNode->pWindowOwner->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged.
|
||||
|
||||
// tearing: if solitary, redraw it. This still might be a single surface window
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->pWindowOwner->m_iMonitorID);
|
||||
if (PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->canBeTorn() && PMONITOR->tearingState.canTear &&
|
||||
pNode->pSurface->wlr()->current.committed & WLR_SURFACE_STATE_BUFFER) {
|
||||
CRegion damageBox;
|
||||
wlr_surface_get_effective_damage(pNode->pSurface->wlr(), damageBox.pixman());
|
||||
|
||||
if (!damageBox.empty()) {
|
||||
|
||||
if (PMONITOR->tearingState.busy) {
|
||||
PMONITOR->tearingState.frameScheduledWhileBusy = true;
|
||||
} else {
|
||||
PMONITOR->tearingState.nextRenderTorn = true;
|
||||
g_pHyprRenderer->renderMonitor(PMONITOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Events::listener_destroySubsurface(void* owner, void* data) {
|
||||
|
@@ -1,3 +1,4 @@
|
||||
#include "MiscFunctions.hpp"
|
||||
#include "VarList.hpp"
|
||||
#include <ranges>
|
||||
#include <algorithm>
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "../macros.hpp"
|
||||
@@ -20,6 +21,15 @@ class CVarList {
|
||||
|
||||
std::string join(const std::string& joiner, size_t from = 0, size_t to = 0) const;
|
||||
|
||||
void map(std::function<void(std::string&)> func) {
|
||||
for (auto& s : m_vArgs)
|
||||
func(s);
|
||||
}
|
||||
|
||||
void append(const std::string arg) {
|
||||
m_vArgs.emplace_back(arg);
|
||||
}
|
||||
|
||||
std::string operator[](const size_t& idx) const {
|
||||
if (idx >= m_vArgs.size())
|
||||
return "";
|
||||
|
@@ -28,6 +28,10 @@ Vector2D Vector2D::floor() const {
|
||||
return Vector2D(std::floor(x), std::floor(y));
|
||||
}
|
||||
|
||||
Vector2D Vector2D::round() const {
|
||||
return Vector2D(std::round(x), std::round(y));
|
||||
}
|
||||
|
||||
Vector2D Vector2D::clamp(const Vector2D& min, const Vector2D& max) const {
|
||||
return Vector2D(std::clamp(this->x, min.x, max.x < min.x ? INFINITY : max.x), std::clamp(this->y, min.y, max.y < min.y ? INFINITY : max.y));
|
||||
}
|
||||
@@ -45,3 +49,7 @@ bool Vector2D::inTriangle(const Vector2D& p1, const Vector2D& p2, const Vector2D
|
||||
|
||||
return 0 <= a && a <= 1 && 0 <= b && b <= 1 && 0 <= c && c <= 1;
|
||||
}
|
||||
|
||||
double Vector2D::size() const {
|
||||
return std::sqrt(x * x + y * y);
|
||||
}
|
||||
|
@@ -22,6 +22,9 @@ class Vector2D {
|
||||
Vector2D operator-(const Vector2D& a) const {
|
||||
return Vector2D(this->x - a.x, this->y - a.y);
|
||||
}
|
||||
Vector2D operator-() const {
|
||||
return Vector2D(-this->x, -this->y);
|
||||
}
|
||||
Vector2D operator*(const float& a) const {
|
||||
return Vector2D(this->x * a, this->y * a);
|
||||
}
|
||||
@@ -54,10 +57,11 @@ class Vector2D {
|
||||
}
|
||||
|
||||
double distance(const Vector2D& other) const;
|
||||
|
||||
double size() const;
|
||||
Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D()) const;
|
||||
|
||||
Vector2D floor() const;
|
||||
Vector2D round() const;
|
||||
|
||||
bool inTriangle(const Vector2D& p1, const Vector2D& p2, const Vector2D& p3) const;
|
||||
};
|
||||
|
@@ -20,7 +20,7 @@ void SLayerSurface::applyRules() {
|
||||
noAnimations = true;
|
||||
else if (rule.rule == "blur")
|
||||
forceBlur = true;
|
||||
else if (rule.rule.find("ignorealpha") == 0 || rule.rule.find("ignorezero") == 0) {
|
||||
else if (rule.rule.starts_with("ignorealpha") || rule.rule.starts_with("ignorezero")) {
|
||||
const auto FIRST_SPACE_POS = rule.rule.find_first_of(' ');
|
||||
std::string alphaValue = "";
|
||||
if (FIRST_SPACE_POS != std::string::npos)
|
||||
@@ -31,7 +31,7 @@ void SLayerSurface::applyRules() {
|
||||
if (!alphaValue.empty())
|
||||
ignoreAlphaValue = std::stof(alphaValue);
|
||||
} catch (...) { Debug::log(ERR, "Invalid value passed to ignoreAlpha"); }
|
||||
} else if (rule.rule.find("xray") == 0) {
|
||||
} else if (rule.rule.starts_with("xray")) {
|
||||
CVarList vars{rule.rule, 0, ' '};
|
||||
try {
|
||||
xray = configStringToInt(vars[1]);
|
||||
|
@@ -33,7 +33,7 @@ struct SLayerSurface {
|
||||
DYNLISTENER(commitLayerSurface);
|
||||
DYNLISTENER(newPopup);
|
||||
|
||||
wlr_box geometry = {0, 0, 0, 0};
|
||||
CBox geometry = {0, 0, 0, 0};
|
||||
Vector2D position;
|
||||
zwlr_layer_shell_v1_layer layer;
|
||||
|
||||
@@ -65,12 +65,12 @@ class CMonitor;
|
||||
struct SRenderData {
|
||||
CMonitor* pMonitor;
|
||||
timespec* when;
|
||||
int x, y;
|
||||
double x, y;
|
||||
|
||||
// for iters
|
||||
void* data = nullptr;
|
||||
wlr_surface* surface = nullptr;
|
||||
int w, h;
|
||||
double w, h;
|
||||
|
||||
// for rounding
|
||||
bool dontRound = true;
|
||||
@@ -168,18 +168,19 @@ struct SConstraint {
|
||||
|
||||
bool active = false;
|
||||
|
||||
bool hintSet = false;
|
||||
Vector2D positionHint = {-1, -1}; // the position hint, but will be set to the current cursor pos if not set.
|
||||
bool hintSet = false;
|
||||
Vector2D positionHint = {-1, -1}; // the position hint, but will use cursorPosOnActivate if unset
|
||||
Vector2D cursorPosOnActivate = {-1, -1};
|
||||
|
||||
DYNLISTENER(setConstraintRegion);
|
||||
DYNLISTENER(destroyConstraint);
|
||||
|
||||
CRegion getLogicCoordsRegion();
|
||||
CRegion getLogicCoordsRegion();
|
||||
Vector2D getLogicConstraintPos();
|
||||
Vector2D getLogicConstraintSize();
|
||||
|
||||
bool operator==(const SConstraint& b) const {
|
||||
return constraint == b.constraint;
|
||||
bool operator==(const SConstraint& b) const {
|
||||
return constraint == b.constraint;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -392,3 +393,14 @@ struct SSwitchDevice {
|
||||
return pWlrDevice == other.pWlrDevice;
|
||||
}
|
||||
};
|
||||
|
||||
struct STearingController {
|
||||
wlr_tearing_control_v1* pWlrHint = nullptr;
|
||||
|
||||
DYNLISTENER(set);
|
||||
DYNLISTENER(destroy);
|
||||
|
||||
bool operator==(const STearingController& other) {
|
||||
return pWlrHint == other.pWlrHint;
|
||||
}
|
||||
};
|
||||
|
@@ -2,11 +2,18 @@
|
||||
#include "MiscFunctions.hpp"
|
||||
#include <string>
|
||||
#include "../debug/Log.hpp"
|
||||
#include "Watchdog.hpp"
|
||||
|
||||
void handleWrapped(wl_listener* listener, void* data) {
|
||||
CHyprWLListener::SWrapper* pWrap = wl_container_of(listener, pWrap, m_sListener);
|
||||
|
||||
pWrap->m_pSelf->emit(data);
|
||||
g_pWatchdog->startWatching();
|
||||
|
||||
try {
|
||||
pWrap->m_pSelf->emit(data);
|
||||
} catch (std::exception& e) { Debug::log(ERR, "Listener {} timed out and was killed by Watchdog!!!", (uintptr_t)listener); }
|
||||
|
||||
g_pWatchdog->endWatching();
|
||||
}
|
||||
|
||||
CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function<void(void*, void*)> callback, void* pOwner) {
|
||||
@@ -50,4 +57,4 @@ void CHyprWLListener::initCallback(wl_signal* pSignal, std::function<void(void*,
|
||||
|
||||
void CHyprWLListener::emit(void* data) {
|
||||
m_pCallback(m_pOwner, data);
|
||||
}
|
||||
}
|
||||
|
@@ -27,15 +27,45 @@ wlr_surface* CWLSurface::wlr() const {
|
||||
return m_pWLRSurface;
|
||||
}
|
||||
|
||||
bool CWLSurface::small() const {
|
||||
if (!m_pOwner || !exists())
|
||||
return false;
|
||||
|
||||
return m_pOwner->m_vReportedSize.x > m_pWLRSurface->current.buffer_width + 1 || m_pOwner->m_vReportedSize.y > m_pWLRSurface->current.buffer_height + 1;
|
||||
}
|
||||
|
||||
Vector2D CWLSurface::correctSmallVec() const {
|
||||
if (!m_pOwner || !exists() || !small() || m_bFillIgnoreSmall)
|
||||
return {};
|
||||
|
||||
const auto SIZE = getViewporterCorrectedSize();
|
||||
|
||||
return Vector2D{(m_pOwner->m_vReportedSize.x - SIZE.x) / 2, (m_pOwner->m_vReportedSize.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) *
|
||||
(m_pOwner->m_vRealSize.vec() / m_pOwner->m_vReportedSize);
|
||||
}
|
||||
|
||||
Vector2D CWLSurface::getViewporterCorrectedSize() const {
|
||||
if (!exists())
|
||||
return {};
|
||||
|
||||
return m_pWLRSurface->current.viewport.has_dst ? Vector2D{m_pWLRSurface->current.viewport.dst_width, m_pWLRSurface->current.viewport.dst_height} :
|
||||
Vector2D{m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height};
|
||||
}
|
||||
|
||||
void CWLSurface::destroy() {
|
||||
if (!m_pWLRSurface)
|
||||
return;
|
||||
|
||||
hyprListener_destroy.removeCallback();
|
||||
m_pWLRSurface->data = nullptr;
|
||||
m_pOwner = nullptr;
|
||||
|
||||
if (g_pCompositor->m_pLastFocus == m_pWLRSurface)
|
||||
g_pCompositor->m_pLastFocus = nullptr;
|
||||
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");
|
||||
|
||||
m_pWLRSurface = nullptr;
|
||||
|
||||
|
@@ -1,6 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "../defines.hpp"
|
||||
|
||||
class CWindow;
|
||||
|
||||
class CWLSurface {
|
||||
public:
|
||||
CWLSurface() = default;
|
||||
@@ -10,20 +13,29 @@ class CWLSurface {
|
||||
void assign(wlr_surface* pSurface);
|
||||
void unassign();
|
||||
|
||||
CWLSurface(const CWLSurface&) = delete;
|
||||
CWLSurface(CWLSurface&&) = delete;
|
||||
CWLSurface(const CWLSurface&) = delete;
|
||||
CWLSurface(CWLSurface&&) = delete;
|
||||
CWLSurface& operator=(const CWLSurface&) = delete;
|
||||
CWLSurface& operator=(CWLSurface&&) = delete;
|
||||
CWLSurface& operator=(CWLSurface&&) = delete;
|
||||
|
||||
wlr_surface* wlr() const;
|
||||
bool exists() const;
|
||||
bool small() const; // means surface is smaller than the requested size
|
||||
Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces
|
||||
Vector2D getViewporterCorrectedSize() const;
|
||||
|
||||
CWLSurface& operator=(wlr_surface* pSurface) {
|
||||
destroy();
|
||||
m_pWLRSurface = pSurface;
|
||||
init();
|
||||
// allow stretching. Useful for plugins.
|
||||
bool m_bFillIgnoreSmall = false;
|
||||
|
||||
return *this;
|
||||
// if present, means this is a base surface of a window. Cleaned on unassign()
|
||||
CWindow* m_pOwner = nullptr;
|
||||
|
||||
CWLSurface& operator=(wlr_surface* pSurface) {
|
||||
destroy();
|
||||
m_pWLRSurface = pSurface;
|
||||
init();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const CWLSurface& other) const {
|
||||
@@ -38,6 +50,10 @@ class CWLSurface {
|
||||
return exists();
|
||||
}
|
||||
|
||||
static CWLSurface* surfaceFromWlr(wlr_surface* pSurface) {
|
||||
return (CWLSurface*)pSurface->data;
|
||||
}
|
||||
|
||||
private:
|
||||
wlr_surface* m_pWLRSurface = nullptr;
|
||||
|
||||
|
59
src/helpers/Watchdog.cpp
Normal file
59
src/helpers/Watchdog.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "Watchdog.hpp"
|
||||
#include <signal.h>
|
||||
#include "config/ConfigManager.hpp"
|
||||
|
||||
CWatchdog::~CWatchdog() {
|
||||
m_bExitThread = true;
|
||||
m_bNotified = true;
|
||||
m_cvWatchdogCondition.notify_all();
|
||||
m_pWatchdog.reset();
|
||||
}
|
||||
|
||||
CWatchdog::CWatchdog() {
|
||||
m_iMainThreadPID = pthread_self();
|
||||
|
||||
m_pWatchdog = std::make_unique<std::thread>([this] {
|
||||
static auto* const PTIMEOUT = &g_pConfigManager->getConfigValuePtr("debug:watchdog_timeout")->intValue;
|
||||
|
||||
while (1337) {
|
||||
std::unique_lock lk(m_mWatchdogMutex);
|
||||
|
||||
if (!m_bWillWatch)
|
||||
m_cvWatchdogCondition.wait(lk, [this] { return m_bNotified; });
|
||||
else {
|
||||
if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(*PTIMEOUT * 1000.0)), [this] { return m_bNotified; }) == false)
|
||||
pthread_kill(m_iMainThreadPID, SIGUSR1);
|
||||
}
|
||||
|
||||
if (m_bExitThread)
|
||||
break;
|
||||
|
||||
m_bWatching = false;
|
||||
m_bNotified = false;
|
||||
}
|
||||
});
|
||||
|
||||
m_pWatchdog->detach();
|
||||
}
|
||||
|
||||
void CWatchdog::startWatching() {
|
||||
static auto* const PTIMEOUT = &g_pConfigManager->getConfigValuePtr("debug:watchdog_timeout")->intValue;
|
||||
|
||||
if (*PTIMEOUT == 0)
|
||||
return;
|
||||
|
||||
m_tTriggered = std::chrono::high_resolution_clock::now();
|
||||
m_bWillWatch = true;
|
||||
m_bWatching = true;
|
||||
|
||||
m_bNotified = true;
|
||||
m_cvWatchdogCondition.notify_all();
|
||||
}
|
||||
|
||||
void CWatchdog::endWatching() {
|
||||
m_bWatching = false;
|
||||
m_bWillWatch = false;
|
||||
|
||||
m_bNotified = true;
|
||||
m_cvWatchdogCondition.notify_all();
|
||||
}
|
32
src/helpers/Watchdog.hpp
Normal file
32
src/helpers/Watchdog.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <condition_variable>
|
||||
|
||||
class CWatchdog {
|
||||
public:
|
||||
// must be called from the main thread
|
||||
CWatchdog();
|
||||
~CWatchdog();
|
||||
|
||||
void startWatching();
|
||||
void endWatching();
|
||||
|
||||
private:
|
||||
std::chrono::high_resolution_clock::time_point m_tTriggered;
|
||||
|
||||
pthread_t m_iMainThreadPID = 0;
|
||||
|
||||
bool m_bWatching = false;
|
||||
bool m_bWillWatch = false;
|
||||
|
||||
std::unique_ptr<std::thread> m_pWatchdog;
|
||||
std::mutex m_mWatchdogMutex;
|
||||
bool m_bNotified = false;
|
||||
bool m_bExitThread = false;
|
||||
std::condition_variable m_cvWatchdogCondition;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CWatchdog> g_pWatchdog;
|
@@ -40,7 +40,7 @@ CWorkspace::~CWorkspace() {
|
||||
void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle;
|
||||
|
||||
if (ANIMSTYLE.find("slidefade") == 0) {
|
||||
if (ANIMSTYLE.starts_with("slidefade")) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
||||
float movePerc = 100.f;
|
||||
|
||||
@@ -54,7 +54,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
m_fAlpha.setValueAndWarp(1.f);
|
||||
m_vRenderOffset.setValueAndWarp(Vector2D(0, 0));
|
||||
|
||||
if (ANIMSTYLE.find("slidefadevert") == 0) {
|
||||
if (ANIMSTYLE.starts_with("slidefadevert")) {
|
||||
if (in) {
|
||||
m_fAlpha.setValueAndWarp(0.f);
|
||||
m_vRenderOffset.setValueAndWarp(Vector2D(0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f)));
|
||||
|
@@ -4,9 +4,9 @@
|
||||
#include <string>
|
||||
#include "../defines.hpp"
|
||||
|
||||
enum eFullscreenMode : uint8_t
|
||||
{
|
||||
FULLSCREEN_FULL = 0,
|
||||
enum eFullscreenMode : int8_t {
|
||||
FULLSCREEN_INVALID = -1,
|
||||
FULLSCREEN_FULL = 0,
|
||||
FULLSCREEN_MAXIMIZED
|
||||
};
|
||||
|
||||
@@ -49,12 +49,12 @@ class CWorkspace {
|
||||
bool m_bDefaultFloating = false;
|
||||
bool m_bDefaultPseudo = false;
|
||||
|
||||
// don't destroy in sanity check
|
||||
bool m_bIndestructible = false;
|
||||
|
||||
// last monitor (used on reconnect)
|
||||
std::string m_szLastMonitor = "";
|
||||
|
||||
// Whether the user configured command for on-created-empty has been executed, if any
|
||||
bool m_bOnCreatedEmptyExecuted = false;
|
||||
|
||||
void startAnim(bool in, bool left, bool instant = false);
|
||||
void setActive(bool on);
|
||||
|
||||
|
@@ -5,7 +5,7 @@ CHyprError::CHyprError() {
|
||||
m_fFadeOpacity.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), nullptr, AVARDAMAGE_NONE);
|
||||
m_fFadeOpacity.registerVar();
|
||||
|
||||
g_pHookSystem->hookDynamic("focusedMon", [&](void* self, std::any param) {
|
||||
g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) {
|
||||
if (!m_bIsCreated)
|
||||
return;
|
||||
|
||||
@@ -13,7 +13,7 @@ CHyprError::CHyprError() {
|
||||
m_bMonitorChanged = true;
|
||||
});
|
||||
|
||||
g_pHookSystem->hookDynamic("preRender", [&](void* self, std::any param) {
|
||||
g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any param) {
|
||||
if (!m_bIsCreated)
|
||||
return;
|
||||
|
||||
@@ -154,7 +154,7 @@ void CHyprError::draw() {
|
||||
|
||||
const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor;
|
||||
|
||||
wlr_box monbox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
CBox monbox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
|
||||
m_bDamageBox.x = (int)PMONITOR->vecPosition.x;
|
||||
m_bDamageBox.y = (int)PMONITOR->vecPosition.y;
|
||||
|
@@ -23,7 +23,7 @@ class CHyprError {
|
||||
bool m_bIsCreated = false;
|
||||
CTexture m_tTexture;
|
||||
CAnimatedVariable m_fFadeOpacity;
|
||||
wlr_box m_bDamageBox = {0, 0, 0, 0};
|
||||
CBox m_bDamageBox = {0, 0, 0, 0};
|
||||
|
||||
bool m_bMonitorChanged = false;
|
||||
};
|
||||
|
@@ -47,7 +47,6 @@ extern "C" {
|
||||
#include <wlr/types/wlr_export_dmabuf_v1.h>
|
||||
#include <wlr/types/wlr_linux_dmabuf_v1.h>
|
||||
#include <wlr/types/wlr_gamma_control_v1.h>
|
||||
#include <wlr/types/wlr_idle.h>
|
||||
#include <wlr/types/wlr_input_device.h>
|
||||
#include <wlr/types/wlr_keyboard.h>
|
||||
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||
@@ -105,6 +104,8 @@ extern "C" {
|
||||
#include <wlr/types/wlr_single_pixel_buffer_v1.h>
|
||||
#include <wlr/types/wlr_idle_notify_v1.h>
|
||||
#include <wlr/types/wlr_cursor_shape_v1.h>
|
||||
#include <wlr/types/wlr_tearing_control_v1.h>
|
||||
#include <wlr/util/box.h>
|
||||
|
||||
#include <libdrm/drm_fourcc.h>
|
||||
|
||||
@@ -145,3 +146,5 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include "helpers/Vector2D.hpp"
|
||||
#include "helpers/Box.hpp"
|
||||
#include "SharedDefs.hpp"
|
||||
|
@@ -4,15 +4,12 @@
|
||||
|
||||
void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverride, bool verticalOverride) {
|
||||
if (children[0]) {
|
||||
|
||||
const auto REVERSESPLITRATIO = 2.f - splitRatio;
|
||||
|
||||
static auto* const PSMARTSPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:smart_split")->intValue;
|
||||
static auto* const PPRESERVESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:preserve_split")->intValue;
|
||||
static auto* const PFLMULT = &g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier")->floatValue;
|
||||
|
||||
if (*PPRESERVESPLIT == 0 && *PSMARTSPLIT == 0) {
|
||||
splitTop = size.y * *PFLMULT > size.x;
|
||||
splitTop = box.h * *PFLMULT > box.w;
|
||||
}
|
||||
|
||||
if (verticalOverride == true)
|
||||
@@ -24,16 +21,14 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverrid
|
||||
|
||||
if (SPLITSIDE) {
|
||||
// split left/right
|
||||
children[0]->position = position;
|
||||
children[0]->size = Vector2D(size.x / 2.f * splitRatio, size.y);
|
||||
children[1]->position = Vector2D(position.x + size.x / 2.f * splitRatio, position.y);
|
||||
children[1]->size = Vector2D(size.x / 2.f * REVERSESPLITRATIO, size.y);
|
||||
const float FIRSTSIZE = box.w / 2.0 * splitRatio;
|
||||
children[0]->box = CBox{box.x, box.y, FIRSTSIZE, box.h};
|
||||
children[1]->box = CBox{box.x + FIRSTSIZE, box.y, box.w - FIRSTSIZE, box.h};
|
||||
} else {
|
||||
// split top/bottom
|
||||
children[0]->position = position;
|
||||
children[0]->size = Vector2D(size.x, size.y / 2.f * splitRatio);
|
||||
children[1]->position = Vector2D(position.x, position.y + size.y / 2.f * splitRatio);
|
||||
children[1]->size = Vector2D(size.x, size.y / 2.f * REVERSESPLITRATIO);
|
||||
const float FIRSTSIZE = box.h / 2.0 * splitRatio;
|
||||
children[0]->box = CBox{box.x, box.y, box.w, FIRSTSIZE};
|
||||
children[1]->box = CBox{box.x, box.y + FIRSTSIZE, box.w, box.h - FIRSTSIZE};
|
||||
}
|
||||
|
||||
children[0]->recalcSizePosRecursive(force);
|
||||
@@ -110,16 +105,19 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||
}
|
||||
|
||||
// for gaps outer
|
||||
const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
|
||||
const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
|
||||
const bool DISPLAYTOP = STICKS(pNode->position.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
|
||||
const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
|
||||
const bool DISPLAYLEFT = STICKS(pNode->box.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
|
||||
const bool DISPLAYRIGHT = STICKS(pNode->box.x + pNode->box.w, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
|
||||
const bool DISPLAYTOP = STICKS(pNode->box.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
|
||||
const bool DISPLAYBOTTOM = STICKS(pNode->box.y + pNode->box.h, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
|
||||
|
||||
const auto PWINDOW = pNode->pWindow;
|
||||
// get specific gaps and rules for this workspace,
|
||||
// if user specified them in config
|
||||
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID));
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks)
|
||||
return;
|
||||
|
||||
PWINDOW->updateSpecialRenderData();
|
||||
|
||||
static auto* const PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
|
||||
@@ -135,8 +133,11 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||
return;
|
||||
}
|
||||
|
||||
PWINDOW->m_vSize = pNode->size;
|
||||
PWINDOW->m_vPosition = pNode->position;
|
||||
CBox nodeBox = pNode->box;
|
||||
nodeBox.round();
|
||||
|
||||
PWINDOW->m_vSize = nodeBox.size();
|
||||
PWINDOW->m_vPosition = nodeBox.pos();
|
||||
|
||||
const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->m_iWorkspaceID);
|
||||
|
||||
@@ -157,6 +158,8 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -204,10 +207,13 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||
// if special, we adjust the coords a bit
|
||||
static auto* const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("dwindle:special_scale_factor")->floatValue;
|
||||
|
||||
PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f;
|
||||
PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR;
|
||||
CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR};
|
||||
wb.round(); // avoid rounding mess
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * *PSCALEFACTOR);
|
||||
PWINDOW->m_vRealPosition = wb.pos();
|
||||
PWINDOW->m_vRealSize = wb.size();
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
|
||||
} else {
|
||||
PWINDOW->m_vRealSize = calcSize;
|
||||
PWINDOW->m_vRealPosition = calcPos;
|
||||
@@ -282,7 +288,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
}
|
||||
|
||||
// first, check if OPENINGON isn't too big.
|
||||
const auto PREDSIZEMAX = OPENINGON ? Vector2D(OPENINGON->size.x, OPENINGON->size.y) : PMONITOR->vecSize;
|
||||
const auto PREDSIZEMAX = OPENINGON ? Vector2D(OPENINGON->box.w, OPENINGON->box.h) : PMONITOR->vecSize;
|
||||
if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); MAXSIZE.x < PREDSIZEMAX.x || MAXSIZE.y < PREDSIZEMAX.y) {
|
||||
// we can't continue. make it floating.
|
||||
pWindow->m_bIsFloating = true;
|
||||
@@ -291,13 +297,6 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
// last fail-safe to avoid duplicate fullscreens
|
||||
if ((!OPENINGON || OPENINGON->pWindow == pWindow) && getNodesOnWorkspace(PNODE->workspaceID) > 1) {
|
||||
for (auto& node : m_lDwindleNodesData) {
|
||||
@@ -310,8 +309,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
|
||||
// if it's the first, it's easy. Make it fullscreen.
|
||||
if (!OPENINGON || OPENINGON->pWindow == pWindow) {
|
||||
PNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
PNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
PNODE->box = CBox{PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight};
|
||||
|
||||
applyNodeDataToWindow(PNODE);
|
||||
|
||||
@@ -320,39 +318,35 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
return;
|
||||
}
|
||||
|
||||
// if it's a group, add the window
|
||||
if (OPENINGON->pWindow->m_sGroupData.pNextWindow // target is group
|
||||
&& !g_pKeybindManager->m_bGroupsLocked // global group lock disengaged
|
||||
&& ((pWindow->m_eGroupRules & GROUP_INVADE && pWindow->m_bFirstMap) // window ignore local group locks, or
|
||||
|| (!OPENINGON->pWindow->getGroupHead()->m_sGroupData.locked // target unlocked
|
||||
&& !(pWindow->m_sGroupData.pNextWindow && pWindow->getGroupHead()->m_sGroupData.locked))) // source unlocked or isn't group
|
||||
&& !pWindow->m_sGroupData.deny // source is not denied entry
|
||||
&& !(pWindow->m_eGroupRules & GROUP_BARRED && pWindow->m_bFirstMap) // group rule doesn't prevent adding window
|
||||
&& !m_vOverrideFocalPoint // we are not moving window
|
||||
) {
|
||||
if (!pWindow->m_sGroupData.pNextWindow)
|
||||
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
if (!m_vOverrideFocalPoint && g_pInputManager->m_bWasDraggingWindow) {
|
||||
for (auto& wd : OPENINGON->pWindow->m_dWindowDecorations) {
|
||||
if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))
|
||||
continue;
|
||||
|
||||
if (g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(MOUSECOORDS)) {
|
||||
if (!wd->onEndWindowDragOnDeco(pWindow, MOUSECOORDS))
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if it's a group, add the window
|
||||
if (OPENINGON->pWindow->m_sGroupData.pNextWindow // target is group
|
||||
&& pWindow->canBeGroupedInto(OPENINGON->pWindow) && !m_vOverrideFocalPoint) { // we are not moving window
|
||||
m_lDwindleNodesData.remove(*PNODE);
|
||||
|
||||
const wlr_box box = OPENINGON->pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents();
|
||||
if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) { // TODO: Deny when not using mouse
|
||||
const int SIZE = OPENINGON->pWindow->getGroupSize();
|
||||
const int INDEX = (int)((MOUSECOORDS.x - box.x) * 2 * SIZE / box.width + 1) / 2 - 1;
|
||||
CWindow* pWindowInsertAfter = OPENINGON->pWindow->getGroupWindowByIndex(INDEX);
|
||||
pWindowInsertAfter->insertWindowToGroup(pWindow);
|
||||
if (INDEX == -1)
|
||||
std::swap(pWindow->m_sGroupData.pNextWindow->m_sGroupData.head, pWindow->m_sGroupData.head);
|
||||
} else {
|
||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("misc:group_insert_after_current")->intValue;
|
||||
(*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
||||
}
|
||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue;
|
||||
(*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
||||
|
||||
OPENINGON->pWindow->setGroupCurrent(pWindow);
|
||||
pWindow->applyGroupRules();
|
||||
pWindow->updateWindowDecos();
|
||||
recalculateWindow(pWindow);
|
||||
|
||||
if (!pWindow->getDecorationByType(DECORATION_GROUPBAR))
|
||||
pWindow->addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -362,8 +356,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
const auto NEWPARENT = &m_lDwindleNodesData.back();
|
||||
|
||||
// make the parent have the OPENINGON's stats
|
||||
NEWPARENT->position = OPENINGON->position;
|
||||
NEWPARENT->size = OPENINGON->size;
|
||||
NEWPARENT->box = OPENINGON->box;
|
||||
NEWPARENT->workspaceID = OPENINGON->workspaceID;
|
||||
NEWPARENT->pParent = OPENINGON->pParent;
|
||||
NEWPARENT->isNode = true; // it is a node
|
||||
@@ -372,7 +365,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
const auto PWIDTHMULTIPLIER = &g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier")->floatValue;
|
||||
|
||||
// if cursor over first child, make it first, etc
|
||||
const auto SIDEBYSIDE = NEWPARENT->size.x > NEWPARENT->size.y * *PWIDTHMULTIPLIER;
|
||||
const auto SIDEBYSIDE = NEWPARENT->box.w > NEWPARENT->box.h * *PWIDTHMULTIPLIER;
|
||||
NEWPARENT->splitTop = !SIDEBYSIDE;
|
||||
|
||||
static auto* const PFORCESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:force_split")->intValue;
|
||||
@@ -404,11 +397,11 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
if (*PERMANENTDIRECTIONOVERRIDE == 0)
|
||||
overrideDirection = DIRECTION_DEFAULT;
|
||||
} else if (*PSMARTSPLIT == 1) {
|
||||
const auto tl = NEWPARENT->position;
|
||||
const auto tr = NEWPARENT->position + Vector2D(NEWPARENT->size.x, 0);
|
||||
const auto bl = NEWPARENT->position + Vector2D(0, NEWPARENT->size.y);
|
||||
const auto br = NEWPARENT->position + NEWPARENT->size;
|
||||
const auto cc = NEWPARENT->position + NEWPARENT->size / 2;
|
||||
const auto tl = NEWPARENT->box.pos();
|
||||
const auto tr = NEWPARENT->box.pos() + Vector2D(NEWPARENT->box.w, 0);
|
||||
const auto bl = NEWPARENT->box.pos() + Vector2D(0, NEWPARENT->box.h);
|
||||
const auto br = NEWPARENT->box.pos() + NEWPARENT->box.size();
|
||||
const auto cc = NEWPARENT->box.pos() + NEWPARENT->box.size() / 2;
|
||||
|
||||
if (MOUSECOORDS.inTriangle(tl, tr, cc)) {
|
||||
NEWPARENT->splitTop = true;
|
||||
@@ -429,11 +422,9 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
}
|
||||
} else if (*PFORCESPLIT == 0 || !pWindow->m_bFirstMap) {
|
||||
if ((SIDEBYSIDE &&
|
||||
VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / *PWIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x / 2.f,
|
||||
NEWPARENT->position.y + NEWPARENT->size.y)) ||
|
||||
VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y + NEWPARENT->box.h)) ||
|
||||
(!SIDEBYSIDE &&
|
||||
VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / *PWIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x,
|
||||
NEWPARENT->position.y + NEWPARENT->size.y / 2.f))) {
|
||||
VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w, NEWPARENT->box.y + NEWPARENT->box.h / 2.f))) {
|
||||
// we are hovering over the first node, make PNODE first.
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
@@ -462,18 +453,14 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
}
|
||||
|
||||
// Update the children
|
||||
if (!verticalOverride && (NEWPARENT->size.x * *PWIDTHMULTIPLIER > NEWPARENT->size.y || horizontalOverride)) {
|
||||
if (!verticalOverride && (NEWPARENT->box.w * *PWIDTHMULTIPLIER > NEWPARENT->box.h || horizontalOverride)) {
|
||||
// split left/right -> forced
|
||||
OPENINGON->position = NEWPARENT->position;
|
||||
OPENINGON->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y);
|
||||
PNODE->position = Vector2D(NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y);
|
||||
PNODE->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y);
|
||||
OPENINGON->box = {NEWPARENT->box.pos(), Vector2D(NEWPARENT->box.w / 2.f, NEWPARENT->box.h)};
|
||||
PNODE->box = {Vector2D(NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y), Vector2D(NEWPARENT->box.w / 2.f, NEWPARENT->box.h)};
|
||||
} else {
|
||||
// split top/bottom
|
||||
OPENINGON->position = NEWPARENT->position;
|
||||
OPENINGON->size = Vector2D(NEWPARENT->size.x, NEWPARENT->size.y / 2.f);
|
||||
PNODE->position = Vector2D(NEWPARENT->position.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f);
|
||||
PNODE->size = Vector2D(NEWPARENT->size.x, NEWPARENT->size.y / 2.f);
|
||||
OPENINGON->box = {NEWPARENT->box.pos(), Vector2D(NEWPARENT->box.w, NEWPARENT->box.h / 2.f)};
|
||||
PNODE->box = {Vector2D(NEWPARENT->box.x, NEWPARENT->box.y + NEWPARENT->box.h / 2.f), Vector2D(NEWPARENT->box.w, NEWPARENT->box.h / 2.f)};
|
||||
}
|
||||
|
||||
OPENINGON->pParent = NEWPARENT;
|
||||
@@ -481,8 +468,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire
|
||||
|
||||
NEWPARENT->recalcSizePosRecursive(false, horizontalOverride, verticalOverride);
|
||||
|
||||
applyNodeDataToWindow(PNODE);
|
||||
applyNodeDataToWindow(OPENINGON);
|
||||
recalculateMonitor(pWindow->m_iMonitorID);
|
||||
|
||||
pWindow->applyGroupRules();
|
||||
}
|
||||
|
||||
@@ -510,9 +497,8 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
|
||||
const auto PSIBLING = PPARENT->children[0] == PNODE ? PPARENT->children[1] : PPARENT->children[0];
|
||||
|
||||
PSIBLING->position = PPARENT->position;
|
||||
PSIBLING->size = PPARENT->size;
|
||||
PSIBLING->pParent = PPARENT->pParent;
|
||||
PSIBLING->box = PPARENT->box;
|
||||
PSIBLING->pParent = PPARENT->pParent;
|
||||
|
||||
if (PPARENT->pParent != nullptr) {
|
||||
if (PPARENT->pParent->children[0] == PPARENT) {
|
||||
@@ -551,8 +537,7 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
|
||||
const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->specialWorkspaceID);
|
||||
|
||||
if (TOPNODE && PMONITOR) {
|
||||
TOPNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
TOPNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
TOPNODE->box = {PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight};
|
||||
TOPNODE->recalcSizePosRecursive();
|
||||
}
|
||||
}
|
||||
@@ -567,11 +552,11 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
|
||||
} else if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) {
|
||||
SDwindleNodeData fakeNode;
|
||||
fakeNode.pWindow = PFULLWINDOW;
|
||||
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
fakeNode.box = {PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight};
|
||||
fakeNode.workspaceID = PWORKSPACE->m_iID;
|
||||
PFULLWINDOW->m_vPosition = fakeNode.position;
|
||||
PFULLWINDOW->m_vSize = fakeNode.size;
|
||||
PFULLWINDOW->m_vPosition = fakeNode.box.pos();
|
||||
PFULLWINDOW->m_vSize = fakeNode.box.size();
|
||||
fakeNode.ignoreFullscreenChecks = true;
|
||||
|
||||
applyNodeDataToWindow(&fakeNode);
|
||||
}
|
||||
@@ -582,8 +567,7 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
|
||||
const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->activeWorkspace);
|
||||
|
||||
if (TOPNODE && PMONITOR) {
|
||||
TOPNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
TOPNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
TOPNODE->box = {PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight};
|
||||
TOPNODE->recalcSizePosRecursive();
|
||||
}
|
||||
}
|
||||
@@ -628,7 +612,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
m_PseudoDragFlags.started = true;
|
||||
|
||||
const auto pseudoSize = PWINDOW->m_vRealSize.goalv();
|
||||
const auto mouseOffset = g_pInputManager->getMouseCoordsInternal() - (PNODE->position + ((PNODE->size / 2) - (pseudoSize / 2)));
|
||||
const auto mouseOffset = g_pInputManager->getMouseCoordsInternal() - (PNODE->box.pos() + ((PNODE->box.size() / 2) - (pseudoSize / 2)));
|
||||
|
||||
if (mouseOffset.x > 0 && mouseOffset.x < pseudoSize.x && mouseOffset.y > 0 && mouseOffset.y < pseudoSize.y) {
|
||||
m_PseudoDragFlags.pseudo = true;
|
||||
@@ -651,8 +635,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
else
|
||||
PWINDOW->m_vPseudoSize.y -= pixResize.y * 2;
|
||||
|
||||
PWINDOW->m_vPseudoSize.x = std::clamp(PWINDOW->m_vPseudoSize.x, 30.0, PNODE->size.x);
|
||||
PWINDOW->m_vPseudoSize.y = std::clamp(PWINDOW->m_vPseudoSize.y, 30.0, PNODE->size.y);
|
||||
PWINDOW->m_vPseudoSize.x = std::clamp(PWINDOW->m_vPseudoSize.x, 30.0, PNODE->box.w);
|
||||
PWINDOW->m_vPseudoSize.y = std::clamp(PWINDOW->m_vPseudoSize.y, 30.0, PNODE->box.h);
|
||||
|
||||
PWINDOW->m_vLastFloatingSize = PWINDOW->m_vPseudoSize;
|
||||
PNODE->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
@@ -699,30 +683,30 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
}
|
||||
|
||||
if (PHOUTER) {
|
||||
PHOUTER->pParent->splitRatio = std::clamp(PHOUTER->pParent->splitRatio + allowedMovement.x * 2.f / PHOUTER->pParent->size.x, 0.1, 1.9);
|
||||
PHOUTER->pParent->splitRatio = std::clamp(PHOUTER->pParent->splitRatio + allowedMovement.x * 2.f / PHOUTER->pParent->box.w, 0.1, 1.9);
|
||||
|
||||
if (PHINNER) {
|
||||
const auto ORIGINAL = PHINNER->size.x;
|
||||
const auto ORIGINAL = PHINNER->box.w;
|
||||
PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
if (PHINNER->pParent->children[0] == PHINNER)
|
||||
PHINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.x) / PHINNER->pParent->size.x * 2.f, 0.1, 1.9);
|
||||
PHINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.x) / PHINNER->pParent->box.w * 2.f, 0.1, 1.9);
|
||||
else
|
||||
PHINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.x) / PHINNER->pParent->size.x * 2.f, 0.1, 1.9);
|
||||
PHINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.x) / PHINNER->pParent->box.w * 2.f, 0.1, 1.9);
|
||||
PHINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
} else
|
||||
PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
}
|
||||
|
||||
if (PVOUTER) {
|
||||
PVOUTER->pParent->splitRatio = std::clamp(PVOUTER->pParent->splitRatio + allowedMovement.y * 2.f / PVOUTER->pParent->size.y, 0.1, 1.9);
|
||||
PVOUTER->pParent->splitRatio = std::clamp(PVOUTER->pParent->splitRatio + allowedMovement.y * 2.f / PVOUTER->pParent->box.h, 0.1, 1.9);
|
||||
|
||||
if (PVINNER) {
|
||||
const auto ORIGINAL = PVINNER->size.y;
|
||||
const auto ORIGINAL = PVINNER->box.h;
|
||||
PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
if (PVINNER->pParent->children[0] == PVINNER)
|
||||
PVINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.y) / PVINNER->pParent->size.y * 2.f, 0.1, 1.9);
|
||||
PVINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.y) / PVINNER->pParent->box.h * 2.f, 0.1, 1.9);
|
||||
else
|
||||
PVINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.y) / PVINNER->pParent->size.y * 2.f, 0.1, 1.9);
|
||||
PVINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.y) / PVINNER->pParent->box.h * 2.f, 0.1, 1.9);
|
||||
PVINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
} else
|
||||
PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
@@ -742,11 +726,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
// No parent means we have only 2 windows, and thus one axis of freedom
|
||||
if (!PPARENT2) {
|
||||
if (PARENTSIDEBYSIDE) {
|
||||
allowedMovement.x *= 2.f / PPARENT->size.x;
|
||||
allowedMovement.x *= 2.f / PPARENT->box.w;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
} else {
|
||||
allowedMovement.y *= 2.f / PPARENT->size.y;
|
||||
allowedMovement.y *= 2.f / PPARENT->box.h;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
}
|
||||
@@ -761,11 +745,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
// no parent, one axis of freedom
|
||||
if (!PPARENT2) {
|
||||
if (PARENTSIDEBYSIDE) {
|
||||
allowedMovement.x *= 2.f / PPARENT->size.x;
|
||||
allowedMovement.x *= 2.f / PPARENT->box.w;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
} else {
|
||||
allowedMovement.y *= 2.f / PPARENT->size.y;
|
||||
allowedMovement.y *= 2.f / PPARENT->box.h;
|
||||
PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
PPARENT->recalcSizePosRecursive(*PANIMATE == 0);
|
||||
}
|
||||
@@ -777,8 +761,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||
const auto SIDECONTAINER = PARENTSIDEBYSIDE ? PPARENT : PPARENT2;
|
||||
const auto TOPCONTAINER = PARENTSIDEBYSIDE ? PPARENT2 : PPARENT;
|
||||
|
||||
allowedMovement.x *= 2.f / SIDECONTAINER->size.x;
|
||||
allowedMovement.y *= 2.f / TOPCONTAINER->size.y;
|
||||
allowedMovement.x *= 2.f / SIDECONTAINER->box.w;
|
||||
allowedMovement.y *= 2.f / TOPCONTAINER->box.h;
|
||||
|
||||
SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, 0.1, 1.9);
|
||||
TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, 0.1, 1.9);
|
||||
@@ -846,11 +830,10 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
||||
|
||||
SDwindleNodeData fakeNode;
|
||||
fakeNode.pWindow = pWindow;
|
||||
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
fakeNode.box = {PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight};
|
||||
fakeNode.workspaceID = pWindow->m_iWorkspaceID;
|
||||
pWindow->m_vPosition = fakeNode.position;
|
||||
pWindow->m_vSize = fakeNode.size;
|
||||
pWindow->m_vPosition = fakeNode.box.pos();
|
||||
pWindow->m_vSize = fakeNode.box.size();
|
||||
|
||||
applyNodeDataToWindow(&fakeNode);
|
||||
}
|
||||
@@ -962,17 +945,15 @@ void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
|
||||
}
|
||||
|
||||
if (ACTIVE1) {
|
||||
ACTIVE1->position = PNODE->position;
|
||||
ACTIVE1->size = PNODE->size;
|
||||
ACTIVE1->pWindow->m_vPosition = ACTIVE1->position;
|
||||
ACTIVE1->pWindow->m_vSize = ACTIVE1->size;
|
||||
ACTIVE1->box = PNODE->box;
|
||||
ACTIVE1->pWindow->m_vPosition = ACTIVE1->box.pos();
|
||||
ACTIVE1->pWindow->m_vSize = ACTIVE1->box.size();
|
||||
}
|
||||
|
||||
if (ACTIVE2) {
|
||||
ACTIVE2->position = PNODE2->position;
|
||||
ACTIVE2->size = PNODE2->size;
|
||||
ACTIVE2->pWindow->m_vPosition = ACTIVE2->position;
|
||||
ACTIVE2->pWindow->m_vSize = ACTIVE2->size;
|
||||
ACTIVE2->box = PNODE2->box;
|
||||
ACTIVE2->pWindow->m_vPosition = ACTIVE2->box.pos();
|
||||
ACTIVE2->pWindow->m_vSize = ACTIVE2->box.size();
|
||||
}
|
||||
|
||||
g_pHyprRenderer->damageWindow(pWindow);
|
||||
|
@@ -9,7 +9,7 @@
|
||||
#include <format>
|
||||
|
||||
class CHyprDwindleLayout;
|
||||
enum eFullscreenMode : uint8_t;
|
||||
enum eFullscreenMode : int8_t;
|
||||
|
||||
struct SDwindleNodeData {
|
||||
SDwindleNodeData* pParent = nullptr;
|
||||
@@ -21,8 +21,7 @@ struct SDwindleNodeData {
|
||||
|
||||
bool splitTop = false; // for preserve_split
|
||||
|
||||
Vector2D position;
|
||||
Vector2D size;
|
||||
CBox box = {0};
|
||||
|
||||
int workspaceID = -1;
|
||||
|
||||
@@ -30,10 +29,12 @@ struct SDwindleNodeData {
|
||||
|
||||
bool valid = true;
|
||||
|
||||
bool ignoreFullscreenChecks = false;
|
||||
|
||||
// For list lookup
|
||||
bool operator==(const SDwindleNodeData& rhs) const {
|
||||
return pWindow == rhs.pWindow && workspaceID == rhs.workspaceID && position == rhs.position && size == rhs.size && pParent == rhs.pParent &&
|
||||
children[0] == rhs.children[0] && children[1] == rhs.children[1];
|
||||
return pWindow == rhs.pWindow && workspaceID == rhs.workspaceID && box == rhs.box && pParent == rhs.pParent && children[0] == rhs.children[0] &&
|
||||
children[1] == rhs.children[1];
|
||||
}
|
||||
|
||||
void recalcSizePosRecursive(bool force = false, bool horizontalOverride = false, bool verticalOverride = false);
|
||||
@@ -94,7 +95,7 @@ struct std::formatter<SDwindleNodeData*, CharT> : std::formatter<CharT> {
|
||||
auto out = ctx.out();
|
||||
if (!node)
|
||||
return std::format_to(out, "[Node nullptr]");
|
||||
std::format_to(out, "[Node {:x}: workspace: {}, pos: {:j2}, size: {:j2}", (uintptr_t)node, node->workspaceID, node->position, node->size);
|
||||
std::format_to(out, "[Node {:x}: workspace: {}, pos: {:j2}, size: {:j2}", (uintptr_t)node, node->workspaceID, node->box.pos(), node->box.size());
|
||||
if (!node->isNode && node->pWindow)
|
||||
std::format_to(out, ", window: {:x}", node->pWindow);
|
||||
return std::format_to(out, "]");
|
||||
|
@@ -6,7 +6,7 @@ void IHyprLayout::onWindowCreated(CWindow* pWindow, eDirection direction) {
|
||||
if (pWindow->m_bIsFloating) {
|
||||
onWindowCreatedFloating(pWindow);
|
||||
} else {
|
||||
wlr_box desiredGeometry = {0};
|
||||
CBox desiredGeometry = {};
|
||||
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
|
||||
|
||||
if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
|
||||
@@ -75,7 +75,7 @@ void IHyprLayout::onWindowRemovedFloating(CWindow* pWindow) {
|
||||
|
||||
void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||
|
||||
wlr_box desiredGeometry = {0};
|
||||
CBox desiredGeometry = {0};
|
||||
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
@@ -162,6 +162,9 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
|
||||
|
||||
g_pCompositor->changeWindowZOrder(pWindow, true);
|
||||
} else {
|
||||
pWindow->m_vPendingReportedSize = pWindow->m_vRealSize.goalv();
|
||||
pWindow->m_vReportedSize = pWindow->m_vPendingReportedSize;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,6 +257,7 @@ void IHyprLayout::onEndDragWindow() {
|
||||
g_pInputManager->unsetCursorImage();
|
||||
|
||||
g_pInputManager->currentlyDraggedWindow = nullptr;
|
||||
g_pInputManager->m_bWasDraggingWindow = true;
|
||||
|
||||
if (DRAGGINGWINDOW->m_bDraggingTiled) {
|
||||
DRAGGINGWINDOW->m_bIsFloating = false;
|
||||
@@ -265,6 +269,8 @@ void IHyprLayout::onEndDragWindow() {
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
|
||||
g_pCompositor->focusWindow(DRAGGINGWINDOW);
|
||||
|
||||
g_pInputManager->m_bWasDraggingWindow = false;
|
||||
}
|
||||
|
||||
void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
@@ -301,11 +307,13 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
|
||||
if (g_pInputManager->dragMode == MBIND_MOVE) {
|
||||
|
||||
if (*PANIMATEMOUSE) {
|
||||
DRAGGINGWINDOW->m_vRealPosition = m_vBeginDragPositionXY + DELTA;
|
||||
} else {
|
||||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA);
|
||||
}
|
||||
CBox wb = {m_vBeginDragPositionXY + DELTA, DRAGGINGWINDOW->m_vRealSize.goalv()};
|
||||
wb.round();
|
||||
|
||||
if (*PANIMATEMOUSE)
|
||||
DRAGGINGWINDOW->m_vRealPosition = wb.pos();
|
||||
else
|
||||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos());
|
||||
|
||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
||||
} else if (g_pInputManager->dragMode == MBIND_RESIZE || g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) {
|
||||
@@ -357,12 +365,15 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
else if (m_eGrabbedCorner == CORNER_BOTTOMLEFT)
|
||||
newPos = newPos + Vector2D((m_vBeginDragSizeXY - newSize).x, 0);
|
||||
|
||||
CBox wb = {newPos, newSize};
|
||||
wb.round();
|
||||
|
||||
if (*PANIMATE) {
|
||||
DRAGGINGWINDOW->m_vRealSize = newSize;
|
||||
DRAGGINGWINDOW->m_vRealPosition = newPos;
|
||||
DRAGGINGWINDOW->m_vRealSize = wb.size();
|
||||
DRAGGINGWINDOW->m_vRealPosition = wb.pos();
|
||||
} else {
|
||||
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(newSize);
|
||||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(newPos);
|
||||
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(wb.size());
|
||||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos());
|
||||
}
|
||||
|
||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
||||
@@ -408,7 +419,7 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
|
||||
if (!TILED) {
|
||||
const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.vec() + pWindow->m_vRealSize.vec() / 2.f);
|
||||
pWindow->m_iMonitorID = PNEWMON->ID;
|
||||
pWindow->moveToWorkspace(PNEWMON->activeWorkspace);
|
||||
pWindow->moveToWorkspace(PNEWMON->specialWorkspaceID != 0 ? PNEWMON->specialWorkspaceID : PNEWMON->activeWorkspace);
|
||||
pWindow->updateGroupOutputs();
|
||||
|
||||
// save real pos cuz the func applies the default 5,5 mid
|
||||
|
@@ -13,9 +13,10 @@ struct SLayoutMessageHeader {
|
||||
CWindow* pWindow = nullptr;
|
||||
};
|
||||
|
||||
enum eFullscreenMode : uint8_t;
|
||||
enum eFullscreenMode : int8_t;
|
||||
|
||||
enum eRectCorner {
|
||||
enum eRectCorner
|
||||
{
|
||||
CORNER_NONE = 0,
|
||||
CORNER_TOPLEFT,
|
||||
CORNER_TOPRIGHT,
|
||||
@@ -23,9 +24,10 @@ enum eRectCorner {
|
||||
CORNER_BOTTOMLEFT
|
||||
};
|
||||
|
||||
enum eDirection {
|
||||
enum eDirection
|
||||
{
|
||||
DIRECTION_DEFAULT = -1,
|
||||
DIRECTION_UP = 0,
|
||||
DIRECTION_UP = 0,
|
||||
DIRECTION_RIGHT,
|
||||
DIRECTION_DOWN,
|
||||
DIRECTION_LEFT
|
||||
|
@@ -94,45 +94,106 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc
|
||||
|
||||
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
|
||||
|
||||
// if it's a group, add the window
|
||||
if (OPENINGON && OPENINGON != PNODE && OPENINGON->pWindow->m_sGroupData.pNextWindow // target is group
|
||||
&& !g_pKeybindManager->m_bGroupsLocked // global group lock disengaged
|
||||
&& ((pWindow->m_eGroupRules & GROUP_INVADE && pWindow->m_bFirstMap) // window ignore local group locks, or
|
||||
|| (!OPENINGON->pWindow->getGroupHead()->m_sGroupData.locked // target unlocked
|
||||
&& !(pWindow->m_sGroupData.pNextWindow && pWindow->getGroupHead()->m_sGroupData.locked))) // source unlocked or isn't group
|
||||
&& !pWindow->m_sGroupData.deny // source is not denied entry
|
||||
&& !(pWindow->m_eGroupRules & GROUP_BARRED) // group rule doesn't prevent adding window
|
||||
) {
|
||||
if (g_pInputManager->m_bWasDraggingWindow && OPENINGON) {
|
||||
for (auto& wd : OPENINGON->pWindow->m_dWindowDecorations) {
|
||||
if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))
|
||||
continue;
|
||||
|
||||
if (!pWindow->m_sGroupData.pNextWindow)
|
||||
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
if (g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(MOUSECOORDS)) {
|
||||
if (!wd->onEndWindowDragOnDeco(pWindow, MOUSECOORDS))
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if it's a group, add the window
|
||||
if (OPENINGON && OPENINGON != PNODE && OPENINGON->pWindow->m_sGroupData.pNextWindow // target is group
|
||||
&& pWindow->canBeGroupedInto(OPENINGON->pWindow)) {
|
||||
|
||||
m_lMasterNodesData.remove(*PNODE);
|
||||
|
||||
const wlr_box box = OPENINGON->pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents();
|
||||
if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) { // TODO: Deny when not using mouse
|
||||
const int SIZE = OPENINGON->pWindow->getGroupSize();
|
||||
const int INDEX = (int)((MOUSECOORDS.x - box.x) * 2 * SIZE / box.width + 1) / 2 - 1;
|
||||
CWindow* pWindowInsertAfter = OPENINGON->pWindow->getGroupWindowByIndex(INDEX);
|
||||
pWindowInsertAfter->insertWindowToGroup(pWindow);
|
||||
if (INDEX == -1)
|
||||
std::swap(pWindow->m_sGroupData.pNextWindow->m_sGroupData.head, pWindow->m_sGroupData.head);
|
||||
} else {
|
||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("misc:group_insert_after_current")->intValue;
|
||||
(*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
||||
}
|
||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue;
|
||||
(*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
||||
|
||||
OPENINGON->pWindow->setGroupCurrent(pWindow);
|
||||
pWindow->applyGroupRules();
|
||||
pWindow->updateWindowDecos();
|
||||
recalculateWindow(pWindow);
|
||||
|
||||
if (!pWindow->getDecorationByType(DECORATION_GROUPBAR))
|
||||
pWindow->addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
pWindow->applyGroupRules();
|
||||
|
||||
if (*PNEWISMASTER || WINDOWSONWORKSPACE == 1 || (!pWindow->m_bFirstMap && OPENINGON->isMaster)) {
|
||||
static auto* const PDROPATCURSOR = &g_pConfigManager->getConfigValuePtr("master:drop_at_cursor")->intValue;
|
||||
const auto PWORKSPACEDATA = getMasterWorkspaceData(pWindow->m_iWorkspaceID);
|
||||
eOrientation orientation = PWORKSPACEDATA->orientation;
|
||||
const auto NODEIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *PNODE);
|
||||
|
||||
bool forceDropAsMaster = false;
|
||||
// if dragging window to move, drop it at the cursor position instead of bottom/top of stack
|
||||
if (*PDROPATCURSOR && g_pInputManager->dragMode == MBIND_MOVE) {
|
||||
if (WINDOWSONWORKSPACE > 2) {
|
||||
for (auto it = m_lMasterNodesData.begin(); it != m_lMasterNodesData.end(); ++it) {
|
||||
if (it->workspaceID != pWindow->m_iWorkspaceID)
|
||||
continue;
|
||||
const CBox box = it->pWindow->getWindowIdealBoundingBoxIgnoreReserved();
|
||||
if (box.containsPoint(MOUSECOORDS)) {
|
||||
switch (orientation) {
|
||||
case ORIENTATION_LEFT:
|
||||
case ORIENTATION_RIGHT:
|
||||
if (MOUSECOORDS.y > it->pWindow->middle().y)
|
||||
++it;
|
||||
break;
|
||||
case ORIENTATION_TOP:
|
||||
case ORIENTATION_BOTTOM:
|
||||
if (MOUSECOORDS.x > it->pWindow->middle().x)
|
||||
++it;
|
||||
break;
|
||||
case ORIENTATION_CENTER: break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
m_lMasterNodesData.splice(it, m_lMasterNodesData, NODEIT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (WINDOWSONWORKSPACE == 2) {
|
||||
// when dropping as the second tiled window in the workspace,
|
||||
// make it the master only if the cursor is on the master side of the screen
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
|
||||
switch (orientation) {
|
||||
case ORIENTATION_LEFT:
|
||||
case ORIENTATION_CENTER:
|
||||
if (MOUSECOORDS.x < nd.pWindow->middle().x)
|
||||
forceDropAsMaster = true;
|
||||
break;
|
||||
case ORIENTATION_RIGHT:
|
||||
if (MOUSECOORDS.x > nd.pWindow->middle().x)
|
||||
forceDropAsMaster = true;
|
||||
break;
|
||||
case ORIENTATION_TOP:
|
||||
if (MOUSECOORDS.y < nd.pWindow->middle().y)
|
||||
forceDropAsMaster = true;
|
||||
break;
|
||||
case ORIENTATION_BOTTOM:
|
||||
if (MOUSECOORDS.y > nd.pWindow->middle().y)
|
||||
forceDropAsMaster = true;
|
||||
break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((*PNEWISMASTER && g_pInputManager->dragMode != MBIND_MOVE) || WINDOWSONWORKSPACE == 1 || (WINDOWSONWORKSPACE > 2 && !pWindow->m_bFirstMap && OPENINGON->isMaster) ||
|
||||
forceDropAsMaster) {
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
|
||||
nd.isMaster = false;
|
||||
@@ -167,13 +228,6 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc
|
||||
}
|
||||
}
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
// recalc
|
||||
recalculateMonitor(pWindow->m_iMonitorID);
|
||||
}
|
||||
@@ -575,6 +629,9 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
// if user specified them in config
|
||||
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID));
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks)
|
||||
return;
|
||||
|
||||
PWINDOW->updateSpecialRenderData();
|
||||
|
||||
static auto* const PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
|
||||
@@ -611,6 +668,8 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -633,15 +692,21 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID)) {
|
||||
static auto* const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("master:special_scale_factor")->floatValue;
|
||||
|
||||
PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f;
|
||||
PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR;
|
||||
CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR};
|
||||
wb.round(); // avoid rounding mess
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * *PSCALEFACTOR);
|
||||
PWINDOW->m_vRealPosition = wb.pos();
|
||||
PWINDOW->m_vRealSize = wb.size();
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
|
||||
} else {
|
||||
PWINDOW->m_vRealSize = calcSize;
|
||||
PWINDOW->m_vRealPosition = calcPos;
|
||||
CBox wb = {calcPos, calcSize};
|
||||
wb.round(); // avoid rounding mess
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
|
||||
PWINDOW->m_vRealPosition = wb.pos();
|
||||
PWINDOW->m_vRealSize = wb.size();
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
|
||||
}
|
||||
|
||||
if (m_bForceWarps && !*PANIMATE) {
|
||||
@@ -718,8 +783,9 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
|
||||
const auto workspaceIdForResizing = PMONITOR->specialWorkspaceID == 0 ? PMONITOR->activeWorkspace : PMONITOR->specialWorkspaceID;
|
||||
for (auto& n : m_lMasterNodesData) {
|
||||
if (n.isMaster && n.workspaceID == PMONITOR->activeWorkspace)
|
||||
if (n.isMaster && n.workspaceID == workspaceIdForResizing)
|
||||
n.percMaster = std::clamp(n.percMaster + delta, 0.05, 0.95);
|
||||
}
|
||||
|
||||
@@ -860,12 +926,13 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen
|
||||
// To keep consistent with the settings without C+P code
|
||||
|
||||
SMasterNodeData fakeNode;
|
||||
fakeNode.pWindow = pWindow;
|
||||
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
fakeNode.workspaceID = pWindow->m_iWorkspaceID;
|
||||
pWindow->m_vPosition = fakeNode.position;
|
||||
pWindow->m_vSize = fakeNode.size;
|
||||
fakeNode.pWindow = pWindow;
|
||||
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
fakeNode.workspaceID = pWindow->m_iWorkspaceID;
|
||||
pWindow->m_vPosition = fakeNode.position;
|
||||
pWindow->m_vSize = fakeNode.size;
|
||||
fakeNode.ignoreFullscreenChecks = true;
|
||||
|
||||
applyNodeDataToWindow(&fakeNode);
|
||||
}
|
||||
@@ -903,7 +970,16 @@ void CHyprMasterLayout::moveWindowTo(CWindow* pWindow, const std::string& dir) {
|
||||
|
||||
const auto PWINDOW2 = g_pCompositor->getWindowInDirection(pWindow, dir[0]);
|
||||
|
||||
switchWindows(pWindow, PWINDOW2);
|
||||
if (pWindow->m_iWorkspaceID != PWINDOW2->m_iWorkspaceID) {
|
||||
// if different monitors, send to monitor
|
||||
onWindowRemovedTiling(pWindow);
|
||||
pWindow->moveToWorkspace(PWINDOW2->m_iWorkspaceID);
|
||||
pWindow->m_iMonitorID = PWINDOW2->m_iMonitorID;
|
||||
onWindowCreatedTiling(pWindow);
|
||||
} else {
|
||||
// if same monitor, switch windows
|
||||
switchWindows(pWindow, PWINDOW2);
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
|
||||
|
@@ -7,7 +7,7 @@
|
||||
#include <deque>
|
||||
#include <any>
|
||||
|
||||
enum eFullscreenMode : uint8_t;
|
||||
enum eFullscreenMode : int8_t;
|
||||
|
||||
//orientation determines which side of the screen the master area resides
|
||||
enum eOrientation : uint8_t {
|
||||
@@ -31,7 +31,10 @@ struct SMasterNodeData {
|
||||
|
||||
int workspaceID = -1;
|
||||
|
||||
bool operator==(const SMasterNodeData& rhs) const {
|
||||
bool ignoreFullscreenChecks = false;
|
||||
|
||||
//
|
||||
bool operator==(const SMasterNodeData& rhs) const {
|
||||
return pWindow == rhs.pWindow;
|
||||
}
|
||||
};
|
||||
@@ -40,7 +43,8 @@ struct SMasterWorkspaceData {
|
||||
int workspaceID = -1;
|
||||
eOrientation orientation = ORIENTATION_LEFT;
|
||||
|
||||
bool operator==(const SMasterWorkspaceData& rhs) const {
|
||||
//
|
||||
bool operator==(const SMasterWorkspaceData& rhs) const {
|
||||
return workspaceID == rhs.workspaceID;
|
||||
}
|
||||
};
|
||||
|
@@ -14,22 +14,7 @@
|
||||
#define ISDEBUG false
|
||||
#endif
|
||||
|
||||
// git stuff
|
||||
#ifndef GIT_COMMIT_HASH
|
||||
#define GIT_COMMIT_HASH "?"
|
||||
#endif
|
||||
#ifndef GIT_BRANCH
|
||||
#define GIT_BRANCH "?"
|
||||
#endif
|
||||
#ifndef GIT_COMMIT_MESSAGE
|
||||
#define GIT_COMMIT_MESSAGE "?"
|
||||
#endif
|
||||
#ifndef GIT_DIRTY
|
||||
#define GIT_DIRTY "?"
|
||||
#endif
|
||||
#ifndef GIT_TAG
|
||||
#define GIT_TAG "?"
|
||||
#endif
|
||||
#include "version.h"
|
||||
|
||||
#define SPECIAL_WORKSPACE_START (-99)
|
||||
|
||||
@@ -57,7 +42,7 @@
|
||||
if (!(expr)) { \
|
||||
Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n{}\n\nat: line {} in {}", \
|
||||
std::format(reason, ##__VA_ARGS__), __LINE__, \
|
||||
([]() constexpr -> std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })()); \
|
||||
([]() constexpr->std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })()); \
|
||||
printf("Assertion failed! See the log in /tmp/hypr/hyprland.log for more info."); \
|
||||
raise(SIGABRT); \
|
||||
}
|
||||
@@ -76,7 +61,9 @@
|
||||
}
|
||||
|
||||
#define FORMAT_FLAG(spec__, flag__) \
|
||||
case spec__: (flag__) = true; break;
|
||||
case spec__: \
|
||||
(flag__) = true; \
|
||||
break;
|
||||
|
||||
#define FORMAT_NUMBER(buf__) \
|
||||
case '0': \
|
||||
@@ -88,7 +75,9 @@
|
||||
case '6': \
|
||||
case '7': \
|
||||
case '8': \
|
||||
case '9': (buf__).push_back(*it); break;
|
||||
case '9': \
|
||||
(buf__).push_back(*it); \
|
||||
break;
|
||||
|
||||
#if ISDEBUG
|
||||
#define UNREACHABLE() \
|
||||
|
@@ -104,6 +104,8 @@ int main(int argc, char** argv) {
|
||||
// If all's good to go, start.
|
||||
g_pCompositor->startCompositor();
|
||||
|
||||
g_pCompositor->m_bIsShuttingDown = true;
|
||||
|
||||
// If we are here it means we got yote.
|
||||
Debug::log(LOG, "Hyprland reached the end.");
|
||||
g_pCompositor.reset();
|
||||
|
@@ -68,6 +68,7 @@ void CAnimationManager::tick() {
|
||||
|
||||
if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW && !*PSHADOWSENABLED) {
|
||||
av->warp(false);
|
||||
animationEndedVars.push_back(av);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -81,7 +82,7 @@ void CAnimationManager::tick() {
|
||||
CMonitor* PMONITOR = nullptr;
|
||||
bool animationsDisabled = animGlobalDisabled;
|
||||
|
||||
wlr_box WLRBOXPREV = {0, 0, 0, 0};
|
||||
CBox WLRBOXPREV = {0, 0, 0, 0};
|
||||
if (PWINDOW) {
|
||||
WLRBOXPREV = PWINDOW->getFullWindowBoundingBox();
|
||||
PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
@@ -93,6 +94,12 @@ void CAnimationManager::tick() {
|
||||
if (!PMONITOR)
|
||||
continue;
|
||||
WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y};
|
||||
|
||||
// TODO: just make this into a damn callback already vax...
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (!w->isHidden() && w->m_bIsMapped && w->m_bIsFloating)
|
||||
g_pHyprRenderer->damageWindow(w.get());
|
||||
}
|
||||
} else if (PLAYER) {
|
||||
WLRBOXPREV = PLAYER->geometry;
|
||||
PMONITOR = g_pCompositor->getMonitorFromVector(Vector2D(PLAYER->geometry.x, PLAYER->geometry.y) + Vector2D(PLAYER->geometry.width, PLAYER->geometry.height) / 2.f);
|
||||
@@ -230,7 +237,7 @@ void CAnimationManager::tick() {
|
||||
BORDERSIZE + ROUNDINGSIZE); // bottom
|
||||
|
||||
// damage for new box
|
||||
const wlr_box WLRBOXNEW = {PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealSize.vec().y};
|
||||
const CBox WLRBOXNEW = {PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealSize.vec().y};
|
||||
g_pHyprRenderer->damageBox(WLRBOXNEW.x - BORDERSIZE, WLRBOXNEW.y - BORDERSIZE, WLRBOXNEW.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top
|
||||
g_pHyprRenderer->damageBox(WLRBOXNEW.x - BORDERSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXNEW.height + 2 * BORDERSIZE); // left
|
||||
g_pHyprRenderer->damageBox(WLRBOXNEW.x + WLRBOXNEW.width - ROUNDINGSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE,
|
||||
@@ -242,29 +249,9 @@ void CAnimationManager::tick() {
|
||||
case AVARDAMAGE_SHADOW: {
|
||||
RASSERT(PWINDOW, "Tried to AVARDAMAGE_SHADOW a non-window AVAR!");
|
||||
|
||||
static auto* const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue;
|
||||
const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW);
|
||||
|
||||
const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW);
|
||||
|
||||
if (PDECO) {
|
||||
const auto EXTENTS = PDECO->getWindowDecorationExtents();
|
||||
|
||||
wlr_box dmg = {PWINDOW->m_vRealPosition.vec().x - EXTENTS.topLeft.x, PWINDOW->m_vRealPosition.vec().y - EXTENTS.topLeft.y,
|
||||
PWINDOW->m_vRealSize.vec().x + EXTENTS.topLeft.x + EXTENTS.bottomRight.x,
|
||||
PWINDOW->m_vRealSize.vec().y + EXTENTS.topLeft.y + EXTENTS.bottomRight.y};
|
||||
|
||||
if (!*PSHADOWIGNOREWINDOW) {
|
||||
// easy, damage the entire box
|
||||
g_pHyprRenderer->damageBox(&dmg);
|
||||
} else {
|
||||
CRegion rg{dmg.x, dmg.y, dmg.width, dmg.height};
|
||||
CRegion wb{PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealSize.vec().y};
|
||||
|
||||
rg.subtract(wb);
|
||||
|
||||
g_pHyprRenderer->damageRegion(rg);
|
||||
}
|
||||
}
|
||||
PDECO->damageEntire();
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -423,7 +410,7 @@ void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) {
|
||||
|
||||
if (pWindow->m_sAdditionalConfigData.animationStyle != "") {
|
||||
// the window has config'd special anim
|
||||
if (pWindow->m_sAdditionalConfigData.animationStyle.find("slide") == 0) {
|
||||
if (pWindow->m_sAdditionalConfigData.animationStyle.starts_with("slide")) {
|
||||
if (pWindow->m_sAdditionalConfigData.animationStyle.contains(' ')) {
|
||||
// has a direction
|
||||
animationSlide(pWindow, pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find(' ') + 1), close);
|
||||
@@ -452,7 +439,7 @@ void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) {
|
||||
// anim popin, fallback
|
||||
|
||||
float minPerc = 0.f;
|
||||
if (ANIMSTYLE.find("%") != 0) {
|
||||
if (!ANIMSTYLE.starts_with("%")) {
|
||||
try {
|
||||
auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' '));
|
||||
minPerc = std::stoi(percstr.substr(0, percstr.length() - 1));
|
||||
@@ -467,10 +454,10 @@ void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) {
|
||||
}
|
||||
|
||||
std::string CAnimationManager::styleValidInConfigVar(const std::string& config, const std::string& style) {
|
||||
if (config.find("window") == 0) {
|
||||
if (config.starts_with("window")) {
|
||||
if (style == "slide") {
|
||||
return "";
|
||||
} else if (style.find("popin") == 0) {
|
||||
} else if (style.starts_with("popin")) {
|
||||
// try parsing
|
||||
float minPerc = 0.f;
|
||||
if (style.find("%") != std::string::npos) {
|
||||
@@ -491,7 +478,7 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config,
|
||||
} else if (config == "workspaces" || config == "specialWorkspace") {
|
||||
if (style == "slide" || style == "slidevert" || style == "fade")
|
||||
return "";
|
||||
else if (style.find("slidefade") == 0) {
|
||||
else if (style.starts_with("slidefade")) {
|
||||
// try parsing
|
||||
float movePerc = 0.f;
|
||||
if (style.find("%") != std::string::npos) {
|
||||
|
@@ -26,7 +26,7 @@ void CHookSystemManager::unhook(HOOK_CALLBACK_FN* fn) {
|
||||
}
|
||||
}
|
||||
|
||||
void CHookSystemManager::emit(const std::vector<SCallbackFNPtr>* callbacks, std::any data) {
|
||||
void CHookSystemManager::emit(const std::vector<SCallbackFNPtr>* callbacks, SCallbackInfo& info, std::any data) {
|
||||
if (callbacks->empty())
|
||||
return;
|
||||
|
||||
@@ -38,7 +38,7 @@ void CHookSystemManager::emit(const std::vector<SCallbackFNPtr>* callbacks, std:
|
||||
|
||||
if (!cb.handle) {
|
||||
// we don't guard hl hooks
|
||||
(*cb.fn)(cb.fn, data);
|
||||
(*cb.fn)(cb.fn, info, data);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ void CHookSystemManager::emit(const std::vector<SCallbackFNPtr>* callbacks, std:
|
||||
|
||||
try {
|
||||
if (!setjmp(m_jbHookFaultJumpBuf))
|
||||
(*cb.fn)(cb.fn, data);
|
||||
(*cb.fn)(cb.fn, info, data);
|
||||
else {
|
||||
// this module crashed.
|
||||
throw std::exception();
|
||||
|
@@ -12,7 +12,8 @@
|
||||
#include "../plugins/PluginAPI.hpp"
|
||||
|
||||
// global typedef for hooked functions. Passes itself as a ptr when called, and `data` additionally.
|
||||
typedef std::function<void(void*, std::any)> HOOK_CALLBACK_FN;
|
||||
|
||||
typedef std::function<void(void*, SCallbackInfo& info, std::any data)> HOOK_CALLBACK_FN;
|
||||
|
||||
struct SCallbackFNPtr {
|
||||
HOOK_CALLBACK_FN* fn = nullptr;
|
||||
@@ -22,7 +23,17 @@ struct SCallbackFNPtr {
|
||||
#define EMIT_HOOK_EVENT(name, param) \
|
||||
{ \
|
||||
static auto* const PEVENTVEC = g_pHookSystem->getVecForEvent(name); \
|
||||
g_pHookSystem->emit(PEVENTVEC, param); \
|
||||
SCallbackInfo info; \
|
||||
g_pHookSystem->emit(PEVENTVEC, info, param); \
|
||||
}
|
||||
|
||||
#define EMIT_HOOK_EVENT_CANCELLABLE(name, param) \
|
||||
{ \
|
||||
static auto* const PEVENTVEC = g_pHookSystem->getVecForEvent(name); \
|
||||
SCallbackInfo info; \
|
||||
g_pHookSystem->emit(PEVENTVEC, info, param); \
|
||||
if (info.cancelled) \
|
||||
return; \
|
||||
}
|
||||
|
||||
class CHookSystemManager {
|
||||
@@ -34,7 +45,7 @@ class CHookSystemManager {
|
||||
void hookStatic(const std::string& event, HOOK_CALLBACK_FN* fn, HANDLE handle = nullptr);
|
||||
void unhook(HOOK_CALLBACK_FN* fn);
|
||||
|
||||
void emit(const std::vector<SCallbackFNPtr>* callbacks, std::any data = 0);
|
||||
void emit(const std::vector<SCallbackFNPtr>* callbacks, SCallbackInfo& info, std::any data = 0);
|
||||
std::vector<SCallbackFNPtr>* getVecForEvent(const std::string& event);
|
||||
|
||||
bool m_bCurrentEventPlugin = false;
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#include "KeybindManager.hpp"
|
||||
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
||||
#include "debug/Log.hpp"
|
||||
#include "helpers/VarList.hpp"
|
||||
|
||||
#include <regex>
|
||||
|
||||
@@ -77,7 +79,7 @@ CKeybindManager::CKeybindManager() {
|
||||
|
||||
m_tScrollTimer.reset();
|
||||
|
||||
g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, std::any param) {
|
||||
g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) {
|
||||
// clear cuz realloc'd
|
||||
m_pActiveKeybind = nullptr;
|
||||
m_vPressedSpecialBinds.clear();
|
||||
@@ -435,7 +437,8 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string&
|
||||
const bool IGNORECONDITIONS =
|
||||
SPECIALDISPATCHER && !pressed && SPECIALTRIGGERED; // ignore mods. Pass, global dispatchers should be released immediately once the key is released.
|
||||
|
||||
if (!IGNORECONDITIONS && (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || k.shadowed))
|
||||
if (!IGNORECONDITIONS &&
|
||||
((modmask != k.modmask && !k.ignoreMods) || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || k.shadowed))
|
||||
continue;
|
||||
|
||||
if (!key.empty()) {
|
||||
@@ -804,12 +807,13 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
// the current workspace will instead switch to the previous.
|
||||
static auto* const PBACKANDFORTH = &g_pConfigManager->getConfigValuePtr("binds:workspace_back_and_forth")->intValue;
|
||||
static auto* const PALLOWWORKSPACECYCLES = &g_pConfigManager->getConfigValuePtr("binds:allow_workspace_cycles")->intValue;
|
||||
static auto* const PWORKSPACECENTERON = &g_pConfigManager->getConfigValuePtr("binds:workspace_center_on")->intValue;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->m_pLastMonitor;
|
||||
const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
const bool EXPLICITPREVIOUS = args.find("previous") == 0;
|
||||
const bool EXPLICITPREVIOUS = args.starts_with("previous");
|
||||
|
||||
if (args.find("previous") == 0) {
|
||||
if (args.starts_with("previous")) {
|
||||
// Do nothing if there's no previous workspace, otherwise switch to it.
|
||||
if (PCURRENTWORKSPACE->m_sPrevWorkspace.iID == -1) {
|
||||
Debug::log(LOG, "No previous workspace to change to");
|
||||
@@ -863,9 +867,13 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
PMONITORWORKSPACEOWNER->changeWorkspace(pWorkspaceToChangeTo, false, true);
|
||||
|
||||
if (PMONITOR != PMONITORWORKSPACEOWNER) {
|
||||
g_pCompositor->warpCursorTo(PMONITORWORKSPACEOWNER->middle());
|
||||
if (const auto PLAST = pWorkspaceToChangeTo->getLastFocusedWindow(); PLAST)
|
||||
Vector2D middle = PMONITORWORKSPACEOWNER->middle();
|
||||
if (const auto PLAST = pWorkspaceToChangeTo->getLastFocusedWindow(); PLAST) {
|
||||
g_pCompositor->focusWindow(PLAST);
|
||||
if (*PWORKSPACECENTERON == 1)
|
||||
middle = PLAST->middle();
|
||||
}
|
||||
g_pCompositor->warpCursorTo(middle);
|
||||
}
|
||||
|
||||
if (BISWORKSPACECURRENT) {
|
||||
@@ -996,7 +1004,8 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||
}
|
||||
|
||||
void CKeybindManager::moveFocusTo(std::string args) {
|
||||
char arg = args[0];
|
||||
static auto* const PFULLCYCLE = &g_pConfigManager->getConfigValuePtr("binds:movefocus_cycles_fullscreen")->intValue;
|
||||
char arg = args[0];
|
||||
|
||||
if (!isDirection(args)) {
|
||||
Debug::log(ERR, "Cannot move focus in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg);
|
||||
@@ -1012,7 +1021,7 @@ void CKeybindManager::moveFocusTo(std::string args) {
|
||||
// remove constraints
|
||||
g_pInputManager->unconstrainMouse();
|
||||
|
||||
const auto PWINDOWTOCHANGETO = PLASTWINDOW->m_bIsFullscreen ?
|
||||
const auto PWINDOWTOCHANGETO = *PFULLCYCLE && PLASTWINDOW->m_bIsFullscreen ?
|
||||
(arg == 'd' || arg == 'b' || arg == 'r' ? g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true) : g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW, true)) :
|
||||
g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);
|
||||
|
||||
@@ -1083,13 +1092,13 @@ void CKeybindManager::swapActive(std::string args) {
|
||||
return;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, PWINDOWTOCHANGETO);
|
||||
g_pCompositor->warpCursorTo(PLASTWINDOW->m_vRealPosition.vec() + PLASTWINDOW->m_vRealSize.vec() / 2.0);
|
||||
g_pCompositor->warpCursorTo(PLASTWINDOW->middle());
|
||||
}
|
||||
|
||||
void CKeybindManager::moveActiveTo(std::string args) {
|
||||
char arg = args[0];
|
||||
|
||||
if (args.find("mon:") == 0) {
|
||||
if (args.starts_with("mon:")) {
|
||||
const auto PNEWMONITOR = g_pCompositor->getMonitorFromString(args.substr(4));
|
||||
if (!PNEWMONITOR)
|
||||
return;
|
||||
@@ -1109,20 +1118,20 @@ void CKeybindManager::moveActiveTo(std::string args) {
|
||||
return;
|
||||
|
||||
if (PLASTWINDOW->m_bIsFloating) {
|
||||
auto vPos = PLASTWINDOW->m_vRealPosition.goalv();
|
||||
Vector2D vPos;
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PLASTWINDOW->m_iMonitorID);
|
||||
const auto BORDERSIZE = PLASTWINDOW->getRealBorderSize();
|
||||
|
||||
switch (arg) {
|
||||
case 'l': vPos.x = PMONITOR->vecReservedTopLeft.x + BORDERSIZE; break;
|
||||
case 'r': vPos.x = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PLASTWINDOW->m_vRealSize.goalv().x - BORDERSIZE; break;
|
||||
case 'l': vPos.x = PMONITOR->vecReservedTopLeft.x + BORDERSIZE + PMONITOR->vecPosition.x; break;
|
||||
case 'r': vPos.x = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PLASTWINDOW->m_vRealSize.goalv().x - BORDERSIZE + PMONITOR->vecPosition.x; break;
|
||||
case 't':
|
||||
case 'u': vPos.y = PMONITOR->vecReservedTopLeft.y + BORDERSIZE; break;
|
||||
case 'u': vPos.y = PMONITOR->vecReservedTopLeft.y + BORDERSIZE + PMONITOR->vecPosition.y; break;
|
||||
case 'b':
|
||||
case 'd': vPos.y = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PLASTWINDOW->m_vRealSize.goalv().y - BORDERSIZE; break;
|
||||
case 'd': vPos.y = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PLASTWINDOW->m_vRealSize.goalv().y - BORDERSIZE + PMONITOR->vecPosition.y; break;
|
||||
}
|
||||
|
||||
PLASTWINDOW->m_vRealPosition = vPos + PMONITOR->vecPosition;
|
||||
PLASTWINDOW->m_vRealPosition = Vector2D(vPos.x != 0 ? vPos.x : PLASTWINDOW->m_vRealPosition.goalv().x, vPos.y != 0 ? vPos.y : PLASTWINDOW->m_vRealPosition.goalv().y);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1172,6 +1181,18 @@ void CKeybindManager::changeGroupActive(std::string args) {
|
||||
if (PWINDOW->m_sGroupData.pNextWindow == PWINDOW)
|
||||
return;
|
||||
|
||||
if (isNumber(args, false)) {
|
||||
// index starts from '1'; '0' means last window
|
||||
const int INDEX = std::stoi(args);
|
||||
if (INDEX > PWINDOW->getGroupSize())
|
||||
return;
|
||||
if (INDEX == 0)
|
||||
PWINDOW->setGroupCurrent(PWINDOW->getGroupTail());
|
||||
else
|
||||
PWINDOW->setGroupCurrent(PWINDOW->getGroupWindowByIndex(INDEX - 1));
|
||||
return;
|
||||
}
|
||||
|
||||
if (args != "b" && args != "prev") {
|
||||
PWINDOW->setGroupCurrent(PWINDOW->m_sGroupData.pNextWindow);
|
||||
} else {
|
||||
@@ -1204,7 +1225,7 @@ void CKeybindManager::alterSplitRatio(std::string args) {
|
||||
}
|
||||
|
||||
if (splitratio == 0) {
|
||||
if (args.find("exact") == 0) {
|
||||
if (args.starts_with("exact")) {
|
||||
exact = true;
|
||||
splitratio = getPlusMinusKeywordResult(args.substr(5), 0);
|
||||
} else {
|
||||
@@ -1704,10 +1725,10 @@ void CKeybindManager::toggleOpaque(std::string unused) {
|
||||
}
|
||||
|
||||
void CKeybindManager::dpms(std::string arg) {
|
||||
bool enable = arg.find("on") == 0;
|
||||
bool enable = arg.starts_with("on");
|
||||
std::string port = "";
|
||||
|
||||
if (arg.find("toggle") == 0)
|
||||
if (arg.starts_with("toggle"))
|
||||
enable = !std::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](const auto& other) { return !other->dpmsStatus; }); // enable if any is off
|
||||
|
||||
if (arg.find_first_of(' ') != std::string::npos)
|
||||
@@ -1819,25 +1840,22 @@ void CKeybindManager::mouse(std::string args) {
|
||||
const auto mouseCoords = g_pInputManager->getMouseCoordsInternal();
|
||||
CWindow* pWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
|
||||
|
||||
if (pWindow && !pWindow->m_bIsFullscreen && !pWindow->hasPopupAt(mouseCoords) && pWindow->m_sGroupData.pNextWindow) {
|
||||
const wlr_box box = pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents();
|
||||
if (wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y)) {
|
||||
const int SIZE = pWindow->getGroupSize();
|
||||
pWindow = pWindow->getGroupWindowByIndex((mouseCoords.x - box.x) * SIZE / box.width);
|
||||
if (pWindow && !pWindow->m_bIsFullscreen && !pWindow->hasPopupAt(mouseCoords)) {
|
||||
for (auto& wd : pWindow->m_dWindowDecorations) {
|
||||
if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))
|
||||
continue;
|
||||
|
||||
// hack
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow);
|
||||
if (!pWindow->m_bIsFloating) {
|
||||
const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_bGroupsLocked;
|
||||
g_pKeybindManager->m_bGroupsLocked = true;
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(pWindow);
|
||||
g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV;
|
||||
if (g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(mouseCoords)) {
|
||||
wd->onBeginWindowDragOnDeco(mouseCoords);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_pInputManager->currentlyDraggedWindow = pWindow;
|
||||
g_pInputManager->dragMode = MBIND_MOVE;
|
||||
if (!g_pInputManager->currentlyDraggedWindow)
|
||||
g_pInputManager->currentlyDraggedWindow = pWindow;
|
||||
|
||||
g_pInputManager->dragMode = MBIND_MOVE;
|
||||
g_pLayoutManager->getCurrentLayout()->onBeginDragWindow();
|
||||
} else {
|
||||
g_pKeybindManager->m_bIsMouseBindActive = false;
|
||||
@@ -1946,12 +1964,9 @@ void CKeybindManager::moveWindowIntoGroup(CWindow* pWindow, CWindow* pWindowInDi
|
||||
if (pWindow->m_sGroupData.deny)
|
||||
return;
|
||||
|
||||
if (!pWindow->m_sGroupData.pNextWindow)
|
||||
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); // This removes groupped property!
|
||||
|
||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("misc:group_insert_after_current")->intValue;
|
||||
static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue;
|
||||
pWindowInDirection = *USECURRPOS ? pWindowInDirection : pWindowInDirection->getGroupTail();
|
||||
|
||||
pWindowInDirection->insertWindowToGroup(pWindow);
|
||||
@@ -1960,11 +1975,13 @@ void CKeybindManager::moveWindowIntoGroup(CWindow* pWindow, CWindow* pWindowInDi
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow);
|
||||
g_pCompositor->focusWindow(pWindow);
|
||||
g_pCompositor->warpCursorTo(pWindow->middle());
|
||||
|
||||
if (!pWindow->getDecorationByType(DECORATION_GROUPBAR))
|
||||
pWindow->addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||
}
|
||||
|
||||
void CKeybindManager::moveWindowOutOfGroup(CWindow* pWindow, const std::string& dir) {
|
||||
|
||||
static auto* const BFOCUSREMOVEDWINDOW = &g_pConfigManager->getConfigValuePtr("misc:group_focus_removed_window")->intValue;
|
||||
static auto* const BFOCUSREMOVEDWINDOW = &g_pConfigManager->getConfigValuePtr("group:focus_removed_window")->intValue;
|
||||
const auto PWINDOWPREV = pWindow->getGroupPrevious();
|
||||
eDirection direction;
|
||||
|
||||
@@ -2003,7 +2020,10 @@ void CKeybindManager::moveWindowOutOfGroup(CWindow* pWindow, const std::string&
|
||||
void CKeybindManager::moveIntoGroup(std::string args) {
|
||||
char arg = args[0];
|
||||
|
||||
static auto* const BIGNOREGROUPLOCK = &g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock")->intValue;
|
||||
static auto* const PIGNOREGROUPLOCK = &g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock")->intValue;
|
||||
|
||||
if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked)
|
||||
return;
|
||||
|
||||
if (!isDirection(args)) {
|
||||
Debug::log(ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg);
|
||||
@@ -2021,13 +2041,18 @@ void CKeybindManager::moveIntoGroup(std::string args) {
|
||||
return;
|
||||
|
||||
// Do not move window into locked group if binds:ignore_group_lock is false
|
||||
if (!*BIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || (PWINDOW->m_sGroupData.pNextWindow && PWINDOW->getGroupHead()->m_sGroupData.locked)))
|
||||
if (!*PIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || (PWINDOW->m_sGroupData.pNextWindow && PWINDOW->getGroupHead()->m_sGroupData.locked)))
|
||||
return;
|
||||
|
||||
moveWindowIntoGroup(PWINDOW, PWINDOWINDIR);
|
||||
}
|
||||
|
||||
void CKeybindManager::moveOutOfGroup(std::string args) {
|
||||
static auto* const PIGNOREGROUPLOCK = &g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock")->intValue;
|
||||
|
||||
if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked)
|
||||
return;
|
||||
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (!PWINDOW || !PWINDOW->m_sGroupData.pNextWindow)
|
||||
@@ -2049,6 +2074,12 @@ void CKeybindManager::moveWindowOrGroup(std::string args) {
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
if (!PWINDOW || PWINDOW->m_bIsFullscreen)
|
||||
return;
|
||||
|
||||
if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) {
|
||||
g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, arg);
|
||||
|
||||
const bool ISWINDOWGROUP = PWINDOW->m_sGroupData.pNextWindow;
|
||||
|
@@ -23,12 +23,14 @@ struct SKeybind {
|
||||
bool mouse = false;
|
||||
bool nonConsuming = false;
|
||||
bool transparent = false;
|
||||
bool ignoreMods = false;
|
||||
|
||||
// DO NOT INITIALIZE
|
||||
bool shadowed = false;
|
||||
};
|
||||
|
||||
enum eFocusWindowMode {
|
||||
enum eFocusWindowMode
|
||||
{
|
||||
MODE_CLASS_REGEX = 0,
|
||||
MODE_TITLE_REGEX,
|
||||
MODE_ADDRESS,
|
||||
|
@@ -74,7 +74,7 @@ void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) {
|
||||
g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID)->m_pLastFocusedWindow = pWindow;
|
||||
}
|
||||
|
||||
void CHyprXWaylandManager::getGeometryForWindow(CWindow* pWindow, wlr_box* pbox) {
|
||||
void CHyprXWaylandManager::getGeometryForWindow(CWindow* pWindow, CBox* pbox) {
|
||||
if (pWindow->m_bIsX11) {
|
||||
const auto SIZEHINTS = pWindow->m_uSurface.xwayland->size_hints;
|
||||
|
||||
@@ -89,8 +89,10 @@ void CHyprXWaylandManager::getGeometryForWindow(CWindow* pWindow, wlr_box* pbox)
|
||||
pbox->width = pWindow->m_uSurface.xwayland->width;
|
||||
pbox->height = pWindow->m_uSurface.xwayland->height;
|
||||
}
|
||||
} else
|
||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, pbox);
|
||||
} else {
|
||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, pbox->pWlr());
|
||||
pbox->applyFromWlr();
|
||||
}
|
||||
}
|
||||
|
||||
std::string CHyprXWaylandManager::getTitle(CWindow* pWindow) {
|
||||
@@ -160,11 +162,11 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f
|
||||
windowPos = windowPos + PMONITOR->vecXWaylandPosition; // move to correct position for xwayland
|
||||
}
|
||||
|
||||
if (!force && ((pWindow->m_vReportedSize == size && windowPos == pWindow->m_vReportedPosition) || (pWindow->m_vReportedSize == size && !pWindow->m_bIsX11)))
|
||||
if (!force && ((pWindow->m_vPendingReportedSize == size && windowPos == pWindow->m_vReportedPosition) || (pWindow->m_vPendingReportedSize == size && !pWindow->m_bIsX11)))
|
||||
return;
|
||||
|
||||
pWindow->m_vReportedPosition = windowPos;
|
||||
pWindow->m_vReportedSize = size;
|
||||
pWindow->m_vReportedPosition = windowPos;
|
||||
pWindow->m_vPendingReportedSize = size;
|
||||
|
||||
pWindow->m_fX11SurfaceScaledBy = 1.f;
|
||||
|
||||
@@ -178,12 +180,15 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f
|
||||
if (pWindow->m_bIsX11)
|
||||
wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, windowPos.x, windowPos.y, size.x, size.y);
|
||||
else
|
||||
wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y);
|
||||
pWindow->m_vPendingSizeAcks.push_back(std::make_pair<>(wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y), size.floor()));
|
||||
}
|
||||
|
||||
void CHyprXWaylandManager::setWindowStyleTiled(CWindow* pWindow, uint32_t edgez) {
|
||||
if (!pWindow->m_bIsX11)
|
||||
wlr_xdg_toplevel_set_tiled(pWindow->m_uSurface.xdg->toplevel, edgez);
|
||||
if (pWindow->m_bIsX11)
|
||||
return;
|
||||
|
||||
wlr_xdg_toplevel_set_tiled(pWindow->m_uSurface.xdg->toplevel, edgez);
|
||||
wlr_xdg_toplevel_set_maximized(pWindow->m_uSurface.xdg->toplevel, true);
|
||||
}
|
||||
|
||||
wlr_surface* CHyprXWaylandManager::surfaceAt(CWindow* pWindow, const Vector2D& client, Vector2D& surface) {
|
||||
|
@@ -15,7 +15,7 @@ class CHyprXWaylandManager {
|
||||
wlr_surface* getWindowSurface(CWindow*);
|
||||
void activateSurface(wlr_surface*, bool);
|
||||
void activateWindow(CWindow*, bool);
|
||||
void getGeometryForWindow(CWindow*, wlr_box*);
|
||||
void getGeometryForWindow(CWindow*, CBox*);
|
||||
std::string getTitle(CWindow*);
|
||||
std::string getAppIDClass(CWindow*);
|
||||
void sendCloseWindow(CWindow*);
|
||||
|
@@ -41,8 +41,6 @@ void CInputManager::simulateMouseMovement() {
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
m_vLastCursorPosFloored = m_vLastCursorPosFloored - Vector2D(1, 1); // hack: force the mouseMoveUnified to report without making this a refocus.
|
||||
mouseMoveUnified(now.tv_sec * 1000 + now.tv_nsec / 10000000);
|
||||
|
||||
m_tmrLastCursorMovement.reset();
|
||||
}
|
||||
|
||||
void CInputManager::sendMotionEventsToFocused() {
|
||||
@@ -67,15 +65,11 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
static auto* const PMOUSEREFOCUS = &g_pConfigManager->getConfigValuePtr("input:mouse_refocus")->intValue;
|
||||
static auto* const PMOUSEDPMS = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_enables_dpms")->intValue;
|
||||
static auto* const PFOLLOWONDND = &g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd")->intValue;
|
||||
static auto* const PHOGFOCUS = &g_pConfigManager->getConfigValuePtr("misc:layers_hog_keyboard_focus")->intValue;
|
||||
static auto* const PFLOATBEHAVIOR = &g_pConfigManager->getConfigValuePtr("input:float_switch_override_focus")->intValue;
|
||||
static auto* const PMOUSEFOCUSMON = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_focuses_monitor")->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;
|
||||
static auto* const PRESIZECURSORICON = &g_pConfigManager->getConfigValuePtr("general:hover_icon_on_border")->intValue;
|
||||
static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue;
|
||||
const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0;
|
||||
|
||||
const auto FOLLOWMOUSE = *PFOLLOWONDND && m_sDrag.drag ? 1 : *PFOLLOWMOUSE;
|
||||
|
||||
@@ -102,11 +96,11 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored && !refocus)
|
||||
return;
|
||||
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("mouseMove", MOUSECOORDSFLOORED);
|
||||
|
||||
if (time)
|
||||
g_pCompositor->notifyIdleActivity();
|
||||
|
||||
EMIT_HOOK_EVENT("mouseMove", MOUSECOORDSFLOORED);
|
||||
|
||||
m_vLastCursorPosFloored = MOUSECOORDSFLOORED;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
|
||||
@@ -118,7 +112,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
if (*PZOOMFACTOR != 1.f)
|
||||
g_pHyprRenderer->damageMonitor(PMONITOR);
|
||||
|
||||
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
||||
if (!PMONITOR->solitaryClient && g_pHyprRenderer->shouldRenderCursor() && PMONITOR->output->software_cursor_locks > 0)
|
||||
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
||||
|
||||
CWindow* forcedFocus = m_pForcedFocus;
|
||||
|
||||
@@ -187,9 +182,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
// update stuff
|
||||
updateDragIcon();
|
||||
|
||||
if (!m_sDrag.drag && !m_lCurrentlyHeldButtons.empty() && g_pCompositor->m_pLastFocus) {
|
||||
if (!m_sDrag.drag && !m_lCurrentlyHeldButtons.empty() && g_pCompositor->m_pLastFocus && m_pLastMouseSurface) {
|
||||
if (m_bLastFocusOnLS) {
|
||||
foundSurface = g_pCompositor->m_pLastFocus;
|
||||
foundSurface = m_pLastMouseSurface;
|
||||
pFoundLayerSurface = g_pCompositor->getLayerSurfaceFromSurface(foundSurface);
|
||||
if (pFoundLayerSurface) {
|
||||
surfacePos = g_pCompositor->getLayerSurfaceFromSurface(foundSurface)->position;
|
||||
@@ -201,10 +196,10 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
pFoundLayerSurface = nullptr;
|
||||
}
|
||||
} else if (g_pCompositor->m_pLastWindow) {
|
||||
foundSurface = g_pCompositor->m_pLastFocus;
|
||||
foundSurface = m_pLastMouseSurface;
|
||||
pFoundWindow = g_pCompositor->m_pLastWindow;
|
||||
|
||||
surfacePos = g_pCompositor->m_pLastWindow->m_vRealPosition.vec();
|
||||
surfaceCoords = g_pCompositor->vectorToSurfaceLocal(mouseCoords, pFoundWindow, foundSurface);
|
||||
|
||||
m_bFocusHeldByButtons = true;
|
||||
m_bRefocusHeldByButtons = refocus;
|
||||
@@ -306,19 +301,19 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
if (g_pHyprRenderer->m_bHasARenderedCursor) {
|
||||
// TODO: maybe wrap?
|
||||
if (m_ecbClickBehavior == CLICKMODE_KILL)
|
||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "crosshair");
|
||||
setCursorImageOverride("crosshair");
|
||||
else
|
||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "left_ptr");
|
||||
setCursorImageOverride("left_ptr");
|
||||
}
|
||||
|
||||
m_bEmptyFocusCursorSet = true;
|
||||
}
|
||||
|
||||
wlr_seat_pointer_clear_focus(g_pCompositor->m_sSeat.seat);
|
||||
m_pLastMouseSurface = nullptr;
|
||||
|
||||
if (refocus) { // if we are forcing a refocus, and we don't find a surface, clear the kb focus too!
|
||||
if (refocus || !g_pCompositor->m_pLastWindow) // if we are forcing a refocus, and we don't find a surface, clear the kb focus too!
|
||||
g_pCompositor->focusWindow(nullptr);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -340,12 +335,11 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
|
||||
bool allowKeyboardRefocus = true;
|
||||
|
||||
if (*PHOGFOCUS && !refocus && g_pCompositor->m_pLastFocus) {
|
||||
if (!refocus && g_pCompositor->m_pLastFocus) {
|
||||
const auto PLS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus);
|
||||
|
||||
if (PLS && PLS->layerSurface->current.keyboard_interactive) {
|
||||
if (PLS && PLS->layerSurface->current.keyboard_interactive == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE)
|
||||
allowKeyboardRefocus = false;
|
||||
}
|
||||
}
|
||||
|
||||
// set the values for use
|
||||
@@ -361,6 +355,14 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pFoundWindow && foundSurface == pFoundWindow->m_pWLSurface.wlr() && !m_bCursorImageOverridden) {
|
||||
const auto BOX = pFoundWindow->getWindowMainSurfaceBox();
|
||||
if (!VECINRECT(mouseCoords, BOX.x, BOX.y, BOX.x + BOX.width, BOX.y + BOX.height))
|
||||
setCursorImageOverride("left_ptr");
|
||||
else
|
||||
restoreCursorIconToApp();
|
||||
}
|
||||
|
||||
if (pFoundWindow) {
|
||||
// change cursor icon if hovering over border
|
||||
if (*PRESIZEONBORDER && *PRESIZECURSORICON) {
|
||||
@@ -371,34 +373,22 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
}
|
||||
}
|
||||
|
||||
// if we're on an input deco, reset cursor. Don't on overridden
|
||||
// if (!m_bCursorImageOverridden) {
|
||||
// if (!VECINRECT(m_vLastCursorPosFloored, pFoundWindow->m_vRealPosition.vec().x, pFoundWindow->m_vRealPosition.vec().y,
|
||||
// pFoundWindow->m_vRealPosition.vec().x + pFoundWindow->m_vRealSize.vec().x, pFoundWindow->m_vRealPosition.vec().y + pFoundWindow->m_vRealSize.vec().y)) {
|
||||
// wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "left_ptr");
|
||||
// cursorSurfaceInfo.bUsed = false;
|
||||
// } else if (!cursorSurfaceInfo.bUsed) {
|
||||
// cursorSurfaceInfo.bUsed = true;
|
||||
// wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, cursorSurfaceInfo.pSurface, cursorSurfaceInfo.vHotspot.x, cursorSurfaceInfo.vHotspot.y);
|
||||
// }
|
||||
// }
|
||||
|
||||
if (FOLLOWMOUSE != 1 && !refocus) {
|
||||
if (pFoundWindow != g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow &&
|
||||
((pFoundWindow->m_bIsFloating && *PFLOATBEHAVIOR == 2) || (g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating && *PFLOATBEHAVIOR != 0))) {
|
||||
// enter if change floating style
|
||||
if (FOLLOWMOUSE != 3 && allowKeyboardRefocus)
|
||||
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
|
||||
m_pLastMouseSurface = foundSurface;
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||
} else if (FOLLOWMOUSE == 2 || FOLLOWMOUSE == 3) {
|
||||
m_pLastMouseSurface = foundSurface;
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||
}
|
||||
|
||||
if (pFoundWindow == g_pCompositor->m_pLastWindow) {
|
||||
if (foundSurface != g_pCompositor->m_pLastFocus || m_bLastFocusOnLS) {
|
||||
// ^^^ changed the subsurface ^^^ came back from a LS
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||
}
|
||||
m_pLastMouseSurface = foundSurface;
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||
}
|
||||
|
||||
if (FOLLOWMOUSE != 0 || pFoundWindow == g_pCompositor->m_pLastWindow)
|
||||
@@ -421,7 +411,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
}
|
||||
|
||||
if (pFoundLayerSurface &&
|
||||
(pFoundLayerSurface->layerSurface->current.keyboard_interactive || (pFoundLayerSurface->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP && !g_pCompositor->m_pLastWindow)) &&
|
||||
(pFoundLayerSurface->layerSurface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE ||
|
||||
(pFoundLayerSurface->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP && !g_pCompositor->m_pLastWindow)) &&
|
||||
FOLLOWMOUSE != 3 && allowKeyboardRefocus) {
|
||||
g_pCompositor->focusSurface(foundSurface);
|
||||
}
|
||||
@@ -430,14 +421,15 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
m_bLastFocusOnLS = true;
|
||||
}
|
||||
|
||||
m_pLastMouseSurface = foundSurface;
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, time, surfaceLocal.x, surfaceLocal.y);
|
||||
}
|
||||
|
||||
void CInputManager::onMouseButton(wlr_pointer_button_event* e) {
|
||||
g_pCompositor->notifyIdleActivity();
|
||||
EMIT_HOOK_EVENT_CANCELLABLE("mouseButton", e);
|
||||
|
||||
EMIT_HOOK_EVENT("mouseButton", e);
|
||||
g_pCompositor->notifyIdleActivity();
|
||||
|
||||
m_tmrLastCursorMovement.reset();
|
||||
|
||||
@@ -473,32 +465,72 @@ void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_even
|
||||
else
|
||||
g_pHyprRenderer->m_bWindowRequestedCursorHide = false;
|
||||
|
||||
if (!cursorImageUnlocked() || !g_pHyprRenderer->shouldRenderCursor())
|
||||
if (!cursorImageUnlocked() || !g_pHyprRenderer->m_bHasARenderedCursor)
|
||||
return;
|
||||
|
||||
// cursorSurfaceInfo.pSurface = e->surface;
|
||||
if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) {
|
||||
m_sCursorSurfaceInfo.wlSurface.unassign();
|
||||
|
||||
// if (e->surface) {
|
||||
// hyprListener_CursorSurfaceDestroy.removeCallback();
|
||||
// hyprListener_CursorSurfaceDestroy.initCallback(
|
||||
// &e->surface->events.destroy, [&](void* owner, void* data) { cursorSurfaceInfo.pSurface = nullptr; }, this, "InputManager");
|
||||
// cursorSurfaceInfo.vHotspot = {e->hotspot_x, e->hotspot_y};
|
||||
// }
|
||||
if (e->surface) {
|
||||
m_sCursorSurfaceInfo.wlSurface.assign(e->surface);
|
||||
m_sCursorSurfaceInfo.vHotspot = {e->hotspot_x, e->hotspot_y};
|
||||
m_sCursorSurfaceInfo.hidden = false;
|
||||
} else {
|
||||
m_sCursorSurfaceInfo.vHotspot = {};
|
||||
m_sCursorSurfaceInfo.hidden = true;
|
||||
}
|
||||
|
||||
if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client)
|
||||
wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, e->surface, e->hotspot_x, e->hotspot_y);
|
||||
m_sCursorSurfaceInfo.name = "";
|
||||
|
||||
m_sCursorSurfaceInfo.inUse = true;
|
||||
g_pHyprRenderer->setCursorSurface(e->surface, e->hotspot_x, e->hotspot_y);
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::processMouseRequest(wlr_cursor_shape_manager_v1_request_set_shape_event* e) {
|
||||
if (!g_pHyprRenderer->shouldRenderCursor() || !cursorImageUnlocked())
|
||||
if (!g_pHyprRenderer->m_bHasARenderedCursor || !cursorImageUnlocked())
|
||||
return;
|
||||
|
||||
if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client)
|
||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, wlr_cursor_shape_v1_name(e->shape));
|
||||
if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) {
|
||||
m_sCursorSurfaceInfo.wlSurface.unassign();
|
||||
m_sCursorSurfaceInfo.vHotspot = {};
|
||||
m_sCursorSurfaceInfo.name = wlr_cursor_shape_v1_name(e->shape);
|
||||
m_sCursorSurfaceInfo.hidden = false;
|
||||
|
||||
m_sCursorSurfaceInfo.inUse = true;
|
||||
g_pHyprRenderer->setCursorFromName(m_sCursorSurfaceInfo.name);
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::restoreCursorIconToApp() {
|
||||
if (m_sCursorSurfaceInfo.inUse)
|
||||
return;
|
||||
|
||||
if (m_sCursorSurfaceInfo.hidden) {
|
||||
g_pHyprRenderer->setCursorSurface(nullptr, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_sCursorSurfaceInfo.name.empty()) {
|
||||
if (m_sCursorSurfaceInfo.wlSurface.exists())
|
||||
g_pHyprRenderer->setCursorSurface(m_sCursorSurfaceInfo.wlSurface.wlr(), m_sCursorSurfaceInfo.vHotspot.x, m_sCursorSurfaceInfo.vHotspot.y);
|
||||
} else {
|
||||
g_pHyprRenderer->setCursorFromName(m_sCursorSurfaceInfo.name);
|
||||
}
|
||||
|
||||
m_sCursorSurfaceInfo.inUse = true;
|
||||
}
|
||||
|
||||
void CInputManager::setCursorImageOverride(const std::string& name) {
|
||||
if (m_bCursorImageOverridden)
|
||||
return;
|
||||
|
||||
m_sCursorSurfaceInfo.inUse = false;
|
||||
g_pHyprRenderer->setCursorFromName(name);
|
||||
}
|
||||
|
||||
bool CInputManager::cursorImageUnlocked() {
|
||||
if (!g_pHyprRenderer->shouldRenderCursor())
|
||||
if (!g_pHyprRenderer->m_bHasARenderedCursor)
|
||||
return false;
|
||||
|
||||
if (m_ecbClickBehavior == CLICKMODE_KILL)
|
||||
@@ -519,7 +551,7 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) {
|
||||
case CLICKMODE_DEFAULT:
|
||||
Debug::log(LOG, "SetClickMode: DEFAULT");
|
||||
m_ecbClickBehavior = CLICKMODE_DEFAULT;
|
||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "left_ptr");
|
||||
g_pHyprRenderer->setCursorFromName("left_ptr");
|
||||
break;
|
||||
|
||||
case CLICKMODE_KILL:
|
||||
@@ -531,7 +563,7 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) {
|
||||
refocus();
|
||||
|
||||
// set cursor
|
||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "crosshair");
|
||||
g_pHyprRenderer->setCursorFromName("crosshair");
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
@@ -551,16 +583,15 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
||||
const auto mouseCoords = g_pInputManager->getMouseCoordsInternal();
|
||||
const auto w = g_pCompositor->vectorToWindowIdeal(mouseCoords);
|
||||
|
||||
if (w && !w->m_bIsFullscreen && !w->hasPopupAt(mouseCoords) && w->m_sGroupData.pNextWindow) {
|
||||
const wlr_box box = w->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents();
|
||||
if (wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y)) {
|
||||
if (e->state == WLR_BUTTON_PRESSED) {
|
||||
const int SIZE = w->getGroupSize();
|
||||
CWindow* pWindow = w->getGroupWindowByIndex((mouseCoords.x - box.x) * SIZE / box.width);
|
||||
if (w != pWindow)
|
||||
w->setGroupCurrent(pWindow);
|
||||
if (w && !w->m_bIsFullscreen && !w->hasPopupAt(mouseCoords)) {
|
||||
for (auto& wd : w->m_dWindowDecorations) {
|
||||
if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))
|
||||
continue;
|
||||
|
||||
if (g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(mouseCoords)) {
|
||||
wd->onMouseButtonOnDeco(mouseCoords, e);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -568,8 +599,8 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
||||
// TODO detect click on LS properly
|
||||
if (*PRESIZEONBORDER && !m_bLastFocusOnLS) {
|
||||
if (w && !w->m_bIsFullscreen) {
|
||||
const wlr_box real = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
if ((!wlr_box_contains_point(&real, mouseCoords.x, mouseCoords.y) || w->isInCurvedCorner(mouseCoords.x, mouseCoords.y)) && !w->hasPopupAt(mouseCoords)) {
|
||||
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)) {
|
||||
g_pKeybindManager->resizeWithBorder(e);
|
||||
return;
|
||||
}
|
||||
@@ -581,7 +612,8 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
||||
if (*PFOLLOWMOUSE == 3) // don't refocus on full loose
|
||||
break;
|
||||
|
||||
if (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) {
|
||||
if ((!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint) /* No constraints */
|
||||
&& (w && g_pCompositor->m_pLastWindow != w) /* window should change */) {
|
||||
// a bit hacky
|
||||
// if we only pressed one button, allow us to refocus. m_lCurrentlyHeldButtons.size() > 0 will stick the focus
|
||||
if (m_lCurrentlyHeldButtons.size() == 1) {
|
||||
@@ -631,7 +663,7 @@ void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) {
|
||||
|
||||
void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
|
||||
static auto* const PSCROLLFACTOR = &g_pConfigManager->getConfigValuePtr("input:touchpad:scroll_factor")->floatValue;
|
||||
static auto* const PGROUPBARSCROLLING = &g_pConfigManager->getConfigValuePtr("misc:groupbar_scrolling")->intValue;
|
||||
static auto* const PGROUPBARSCROLLING = &g_pConfigManager->getConfigValuePtr("group:groupbar:scrolling")->intValue;
|
||||
|
||||
auto factor = (*PSCROLLFACTOR <= 0.f || e->source != WLR_AXIS_SOURCE_FINGER ? 1.f : *PSCROLLFACTOR);
|
||||
|
||||
@@ -643,8 +675,8 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
|
||||
const auto pWindow = g_pCompositor->vectorToWindowIdeal(MOUSECOORDS);
|
||||
|
||||
if (*PGROUPBARSCROLLING && pWindow && !pWindow->m_bIsFullscreen && !pWindow->hasPopupAt(MOUSECOORDS) && pWindow->m_sGroupData.pNextWindow) {
|
||||
const wlr_box box = pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents();
|
||||
if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) {
|
||||
const CBox box = g_pDecorationPositioner->getWindowDecorationBox(pWindow->getDecorationByType(DECORATION_GROUPBAR));
|
||||
if (box.containsPoint(MOUSECOORDS)) {
|
||||
if (e->delta > 0)
|
||||
pWindow->setGroupCurrent(pWindow->m_sGroupData.pNextWindow);
|
||||
else
|
||||
@@ -1011,7 +1043,7 @@ void CInputManager::setPointerConfigs() {
|
||||
libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
|
||||
} else if (ACCELPROFILE == "flat") {
|
||||
libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT);
|
||||
} else if (ACCELPROFILE.find("custom") == 0) {
|
||||
} else if (ACCELPROFILE.starts_with("custom")) {
|
||||
CVarList args = {ACCELPROFILE, 0, ' '};
|
||||
try {
|
||||
double step = std::stod(args[1]);
|
||||
@@ -1175,7 +1207,7 @@ void CInputManager::updateDragIcon() {
|
||||
switch (m_sDrag.dragIcon->drag->grab_type) {
|
||||
case WLR_DRAG_GRAB_KEYBOARD: break;
|
||||
case WLR_DRAG_GRAB_KEYBOARD_POINTER: {
|
||||
wlr_box box = {m_sDrag.pos.x - 2, m_sDrag.pos.y - 2, m_sDrag.dragIcon->surface->current.width + 4, m_sDrag.dragIcon->surface->current.height + 4};
|
||||
CBox box = {m_sDrag.pos.x - 2, m_sDrag.pos.y - 2, m_sDrag.dragIcon->surface->current.width + 4, m_sDrag.dragIcon->surface->current.height + 4};
|
||||
g_pHyprRenderer->damageBox(&box);
|
||||
m_sDrag.pos = getMouseCoordsInternal();
|
||||
break;
|
||||
@@ -1202,24 +1234,30 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co
|
||||
return;
|
||||
|
||||
const auto MOUSECOORDS = getMouseCoordsInternal();
|
||||
const auto PCONSTRAINT = constraintFromWlr(constraint);
|
||||
|
||||
pMouse->hyprListener_commitConstraint.removeCallback();
|
||||
|
||||
if (pMouse->currentConstraint) {
|
||||
if (constraint) {
|
||||
const auto PCONSTRAINT = constraintFromWlr(constraint);
|
||||
if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) {
|
||||
PCONSTRAINT->hintSet = true;
|
||||
PCONSTRAINT->positionHint = {constraint->current.cursor_hint.x, constraint->current.cursor_hint.y};
|
||||
}
|
||||
|
||||
if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT && constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED)
|
||||
warpMouseToConstraintMiddle(PCONSTRAINT);
|
||||
}
|
||||
|
||||
if (pMouse->currentConstraint)
|
||||
wlr_pointer_constraint_v1_send_deactivated(pMouse->currentConstraint);
|
||||
|
||||
if (const auto PWINDOW = g_pCompositor->getWindowFromSurface(constraint->surface); PWINDOW) {
|
||||
const auto RELATIVETO = PWINDOW->m_bIsX11 ?
|
||||
(PWINDOW->m_bIsMapped ? PWINDOW->m_vRealPosition.goalv() :
|
||||
g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y})) :
|
||||
PWINDOW->m_vRealPosition.goalv();
|
||||
|
||||
PCONSTRAINT->cursorPosOnActivate = (MOUSECOORDS - RELATIVETO) * PWINDOW->m_fX11SurfaceScaledBy;
|
||||
}
|
||||
|
||||
if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) {
|
||||
PCONSTRAINT->hintSet = true;
|
||||
PCONSTRAINT->positionHint = {constraint->current.cursor_hint.x, constraint->current.cursor_hint.y};
|
||||
}
|
||||
|
||||
if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT && constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED)
|
||||
warpMouseToConstraintMiddle(PCONSTRAINT);
|
||||
|
||||
pMouse->currentConstraint = constraint;
|
||||
pMouse->constraintActive = true;
|
||||
|
||||
@@ -1231,7 +1269,7 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co
|
||||
// warp to the constraint
|
||||
recheckConstraint(pMouse);
|
||||
|
||||
constraintFromWlr(constraint)->active = true;
|
||||
PCONSTRAINT->active = true;
|
||||
|
||||
wlr_pointer_constraint_v1_send_activated(pMouse->currentConstraint);
|
||||
|
||||
@@ -1248,23 +1286,17 @@ void CInputManager::warpMouseToConstraintMiddle(SConstraint* pConstraint) {
|
||||
const auto PWINDOW = g_pCompositor->getWindowFromSurface(pConstraint->constraint->surface);
|
||||
|
||||
if (PWINDOW) {
|
||||
const auto RELATIVETO = PWINDOW->m_bIsX11 ?
|
||||
(PWINDOW->m_bIsMapped ? PWINDOW->m_vRealPosition.goalv() :
|
||||
g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y})) :
|
||||
PWINDOW->m_vRealPosition.goalv();
|
||||
const auto RELATIVETO = pConstraint->getLogicConstraintPos();
|
||||
const auto HINTSCALE = PWINDOW->m_fX11SurfaceScaledBy;
|
||||
|
||||
if (pConstraint->hintSet) {
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, RELATIVETO.x + pConstraint->positionHint.x / HINTSCALE, RELATIVETO.y + pConstraint->positionHint.y / HINTSCALE);
|
||||
wlr_seat_pointer_warp(pConstraint->constraint->seat, pConstraint->constraint->current.cursor_hint.x, pConstraint->constraint->current.cursor_hint.y);
|
||||
} else {
|
||||
const auto RELATIVESIZE = PWINDOW->m_bIsX11 ?
|
||||
(PWINDOW->m_bIsMapped ? PWINDOW->m_vRealSize.goalv() :
|
||||
g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->width, PWINDOW->m_uSurface.xwayland->height})) :
|
||||
PWINDOW->m_vRealSize.goalv();
|
||||
auto HINT = pConstraint->hintSet ? pConstraint->positionHint : pConstraint->cursorPosOnActivate;
|
||||
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, RELATIVETO.x + RELATIVESIZE.x / 2.f, RELATIVETO.y + RELATIVESIZE.y / 2.f);
|
||||
wlr_seat_pointer_warp(pConstraint->constraint->seat, RELATIVESIZE.x / 2.f, RELATIVESIZE.y / 2.f);
|
||||
if (HINT == Vector2D{-1, -1})
|
||||
HINT = pConstraint->getLogicConstraintSize() / 2.f;
|
||||
|
||||
if (HINT != Vector2D{-1, -1}) {
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, RELATIVETO.x + HINT.x / HINTSCALE, RELATIVETO.y + HINT.y / HINTSCALE);
|
||||
wlr_seat_pointer_warp(pConstraint->constraint->seat, pConstraint->constraint->current.cursor_hint.x, pConstraint->constraint->current.cursor_hint.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1439,6 +1471,12 @@ void CInputManager::setTabletConfigs() {
|
||||
wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, t.wlrDevice, PMONITOR->output);
|
||||
wlr_cursor_map_input_to_region(g_pCompositor->m_sWLRCursor, t.wlrDevice, nullptr);
|
||||
}
|
||||
|
||||
const auto REGION_POS = g_pConfigManager->getDeviceVec(t.name, "region_position", "input:tablet:region_position");
|
||||
const auto REGION_SIZE = g_pConfigManager->getDeviceVec(t.name, "region_size", "input:tablet:region_size");
|
||||
auto regionBox = CBox{REGION_POS.x, REGION_POS.y, REGION_SIZE.x, REGION_SIZE.y};
|
||||
if (!regionBox.empty())
|
||||
wlr_cursor_map_input_to_region(g_pCompositor->m_sWLRCursor, t.wlrDevice, regionBox.pWlr());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1495,8 +1533,9 @@ void CInputManager::destroySwitch(SSwitchDevice* pDevice) {
|
||||
}
|
||||
|
||||
void CInputManager::setCursorImageUntilUnset(std::string name) {
|
||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, name.c_str());
|
||||
m_bCursorImageOverridden = true;
|
||||
g_pHyprRenderer->setCursorFromName(name.c_str());
|
||||
m_bCursorImageOverridden = true;
|
||||
m_sCursorSurfaceInfo.inUse = false;
|
||||
}
|
||||
|
||||
void CInputManager::unsetCursorImage() {
|
||||
@@ -1504,8 +1543,7 @@ void CInputManager::unsetCursorImage() {
|
||||
return;
|
||||
|
||||
m_bCursorImageOverridden = false;
|
||||
if (!g_pHyprRenderer->m_bWindowRequestedCursorHide)
|
||||
wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "left_ptr");
|
||||
restoreCursorIconToApp();
|
||||
}
|
||||
|
||||
std::string CInputManager::deviceNameToInternalString(std::string in) {
|
||||
@@ -1583,49 +1621,70 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) {
|
||||
// give a small leeway (10 px) for corner icon
|
||||
const auto CORNER = *PROUNDING + BORDERSIZE + 10;
|
||||
const auto mouseCoords = getMouseCoordsInternal();
|
||||
wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y};
|
||||
CBox box = w->getWindowMainSurfaceBox();
|
||||
eBorderIconDirection direction = BORDERICON_NONE;
|
||||
wlr_box boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE),
|
||||
box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)};
|
||||
CBox boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE),
|
||||
box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)};
|
||||
|
||||
if (!wlr_box_contains_point(&boxFullGrabInput, mouseCoords.x, mouseCoords.y) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow)) {
|
||||
if (w->hasPopupAt(mouseCoords))
|
||||
direction = BORDERICON_NONE;
|
||||
} else if (wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y)) {
|
||||
if (!w->isInCurvedCorner(mouseCoords.x, mouseCoords.y)) {
|
||||
direction = BORDERICON_NONE;
|
||||
} else {
|
||||
if (mouseCoords.y < box.y + CORNER) {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_UP_LEFT;
|
||||
else
|
||||
direction = BORDERICON_UP_RIGHT;
|
||||
} else {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_DOWN_LEFT;
|
||||
else
|
||||
direction = BORDERICON_DOWN_RIGHT;
|
||||
else if (!boxFullGrabInput.containsPoint(mouseCoords) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow))
|
||||
direction = BORDERICON_NONE;
|
||||
else {
|
||||
|
||||
bool onDeco = false;
|
||||
|
||||
for (auto& wd : w->m_dWindowDecorations) {
|
||||
if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))
|
||||
continue;
|
||||
|
||||
if (g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(mouseCoords)) {
|
||||
onDeco = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mouseCoords.y < box.y + CORNER) {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_UP_LEFT;
|
||||
else if (mouseCoords.x > box.x + box.width - CORNER)
|
||||
direction = BORDERICON_UP_RIGHT;
|
||||
else
|
||||
direction = BORDERICON_UP;
|
||||
} else if (mouseCoords.y > box.y + box.height - CORNER) {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_DOWN_LEFT;
|
||||
else if (mouseCoords.x > box.x + box.width - CORNER)
|
||||
direction = BORDERICON_DOWN_RIGHT;
|
||||
else
|
||||
direction = BORDERICON_DOWN;
|
||||
} else {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_LEFT;
|
||||
else if (mouseCoords.x > box.x + box.width - CORNER)
|
||||
direction = BORDERICON_RIGHT;
|
||||
|
||||
if (onDeco)
|
||||
direction = BORDERICON_NONE;
|
||||
else {
|
||||
if (box.containsPoint(mouseCoords)) {
|
||||
if (!w->isInCurvedCorner(mouseCoords.x, mouseCoords.y)) {
|
||||
direction = BORDERICON_NONE;
|
||||
} else {
|
||||
if (mouseCoords.y < box.y + CORNER) {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_UP_LEFT;
|
||||
else
|
||||
direction = BORDERICON_UP_RIGHT;
|
||||
} else {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_DOWN_LEFT;
|
||||
else
|
||||
direction = BORDERICON_DOWN_RIGHT;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mouseCoords.y < box.y + CORNER) {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_UP_LEFT;
|
||||
else if (mouseCoords.x > box.x + box.width - CORNER)
|
||||
direction = BORDERICON_UP_RIGHT;
|
||||
else
|
||||
direction = BORDERICON_UP;
|
||||
} else if (mouseCoords.y > box.y + box.height - CORNER) {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_DOWN_LEFT;
|
||||
else if (mouseCoords.x > box.x + box.width - CORNER)
|
||||
direction = BORDERICON_DOWN_RIGHT;
|
||||
else
|
||||
direction = BORDERICON_DOWN;
|
||||
} else {
|
||||
if (mouseCoords.x < box.x + CORNER)
|
||||
direction = BORDERICON_LEFT;
|
||||
else if (mouseCoords.x > box.x + box.width - CORNER)
|
||||
direction = BORDERICON_RIGHT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -115,6 +115,7 @@ class CInputManager {
|
||||
// for dragging floating windows
|
||||
CWindow* currentlyDraggedWindow = nullptr;
|
||||
eMouseBindMode dragMode = MBIND_INVALID;
|
||||
bool m_bWasDraggingWindow = false;
|
||||
|
||||
// for refocus to be forced
|
||||
CWindow* m_pForcedFocus = nullptr;
|
||||
@@ -181,7 +182,8 @@ class CInputManager {
|
||||
bool m_bLastInputTouch = false;
|
||||
|
||||
// for tracking mouse refocus
|
||||
CWindow* m_pLastMouseFocus = nullptr;
|
||||
CWindow* m_pLastMouseFocus = nullptr;
|
||||
wlr_surface* m_pLastMouseSurface = nullptr;
|
||||
|
||||
private:
|
||||
bool m_bCursorImageOverridden = false;
|
||||
@@ -225,15 +227,22 @@ class CInputManager {
|
||||
void setBorderCursorIcon(eBorderIconDirection);
|
||||
void setCursorIconOnBorder(CWindow* w);
|
||||
|
||||
// temporary. Obeys setUntilUnset.
|
||||
void setCursorImageOverride(const std::string& name);
|
||||
|
||||
// cursor surface
|
||||
// struct cursorSI {
|
||||
// wlr_surface* pSurface = nullptr;
|
||||
// Vector2D vHotspot;
|
||||
// bool bUsed = false;
|
||||
// } cursorSurfaceInfo;
|
||||
// DYNLISTENER(CursorSurfaceDestroy);
|
||||
struct cursorSI {
|
||||
bool hidden = false; // null surface = hidden
|
||||
CWLSurface wlSurface;
|
||||
Vector2D vHotspot;
|
||||
std::string name; // if not empty, means set by name.
|
||||
bool inUse = false;
|
||||
} m_sCursorSurfaceInfo;
|
||||
|
||||
void restoreCursorIconToApp(); // no-op if restored
|
||||
|
||||
friend class CKeybindManager;
|
||||
friend class CWLSurface;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CInputManager> g_pInputManager;
|
||||
|
@@ -3,7 +3,7 @@
|
||||
#include "../../Compositor.hpp"
|
||||
|
||||
CInputMethodRelay::CInputMethodRelay() {
|
||||
g_pHookSystem->hookDynamic("keyboardFocus", [&](void* self, std::any param) { onKeyboardFocus(std::any_cast<wlr_surface*>(param)); });
|
||||
g_pHookSystem->hookDynamic("keyboardFocus", [&](void* self, SCallbackInfo& info, std::any param) { onKeyboardFocus(std::any_cast<wlr_surface*>(param)); });
|
||||
}
|
||||
|
||||
void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) {
|
||||
@@ -178,7 +178,7 @@ void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) {
|
||||
|
||||
bool cursorRect = PFOCUSEDTI->pWlrInput ? PFOCUSEDTI->pWlrInput->current.features & WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE : true;
|
||||
const auto PFOCUSEDSURFACE = focusedSurface(PFOCUSEDTI);
|
||||
auto cursorBox = PFOCUSEDTI->pWlrInput ? PFOCUSEDTI->pWlrInput->current.cursor_rectangle : PFOCUSEDTI->pV1Input->cursorRectangle;
|
||||
CBox cursorBox = PFOCUSEDTI->pWlrInput ? PFOCUSEDTI->pWlrInput->current.cursor_rectangle : PFOCUSEDTI->pV1Input->cursorRectangle;
|
||||
CMonitor* pMonitor = nullptr;
|
||||
|
||||
Vector2D parentPos;
|
||||
@@ -209,7 +209,7 @@ void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) {
|
||||
if (!pMonitor)
|
||||
return;
|
||||
|
||||
wlr_box finalBox = cursorBox;
|
||||
CBox finalBox = cursorBox;
|
||||
|
||||
if (cursorBox.y + parentPos.y + pPopup->pSurface->surface->current.height + finalBox.height > pMonitor->vecPosition.y + pMonitor->vecSize.y)
|
||||
finalBox.y -= pPopup->pSurface->surface->current.height + finalBox.height;
|
||||
@@ -225,7 +225,7 @@ void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) {
|
||||
|
||||
pPopup->lastSize = Vector2D(pPopup->pSurface->surface->current.width, pPopup->pSurface->surface->current.height);
|
||||
|
||||
wlr_input_popup_surface_v2_send_text_input_rectangle(pPopup->pSurface, &finalBox);
|
||||
wlr_input_popup_surface_v2_send_text_input_rectangle(pPopup->pSurface, finalBox.pWlr());
|
||||
|
||||
damagePopup(pPopup);
|
||||
}
|
||||
|
@@ -51,7 +51,7 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
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" ||
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.find("slidefadevert") == 0;
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert");
|
||||
|
||||
// commit
|
||||
std::string wsname = "";
|
||||
@@ -200,7 +200,7 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||
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" ||
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.find("slidefadevert") == 0;
|
||||
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);
|
||||
|
||||
|
@@ -244,8 +244,6 @@ void CInputManager::focusTablet(STablet* pTab, wlr_tablet_tool* pTool, bool moti
|
||||
if (const auto PWINDOW = g_pCompositor->m_pLastWindow; PWINDOW) {
|
||||
const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal();
|
||||
|
||||
const auto LOCAL = CURSORPOS - PWINDOW->m_vRealPosition.goalv();
|
||||
|
||||
if (PTOOL->pSurface != g_pCompositor->m_pLastFocus)
|
||||
wlr_tablet_v2_tablet_tool_notify_proximity_out(PTOOL->wlrTabletToolV2);
|
||||
|
||||
@@ -254,8 +252,14 @@ void CInputManager::focusTablet(STablet* pTab, wlr_tablet_tool* pTool, bool moti
|
||||
wlr_tablet_v2_tablet_tool_notify_proximity_in(PTOOL->wlrTabletToolV2, pTab->wlrTabletV2, g_pCompositor->m_pLastFocus);
|
||||
}
|
||||
|
||||
if (motion)
|
||||
wlr_tablet_v2_tablet_tool_notify_motion(PTOOL->wlrTabletToolV2, LOCAL.x, LOCAL.y);
|
||||
if (motion) {
|
||||
auto local = CURSORPOS - PWINDOW->m_vRealPosition.goalv();
|
||||
|
||||
if (PWINDOW->m_bIsX11)
|
||||
local = local * PWINDOW->m_fX11SurfaceScaledBy;
|
||||
|
||||
wlr_tablet_v2_tablet_tool_notify_motion(PTOOL->wlrTabletToolV2, local.x, local.y);
|
||||
}
|
||||
} else {
|
||||
if (PTOOL->pSurface)
|
||||
wlr_tablet_v2_tablet_tool_notify_proximity_out(PTOOL->wlrTabletToolV2);
|
||||
|
@@ -32,12 +32,12 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) {
|
||||
|
||||
if (m_sTouchData.touchFocusWindow) {
|
||||
if (m_sTouchData.touchFocusWindow->m_bIsX11) {
|
||||
local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchFocusWindow->m_vRealPosition.goalv();
|
||||
local = (g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchFocusWindow->m_vRealPosition.goalv()) * m_sTouchData.touchFocusWindow->m_fX11SurfaceScaledBy;
|
||||
m_sTouchData.touchSurfaceOrigin = m_sTouchData.touchFocusWindow->m_vRealPosition.goalv();
|
||||
} else {
|
||||
g_pCompositor->vectorWindowToSurface(g_pInputManager->getMouseCoordsInternal(), m_sTouchData.touchFocusWindow, local);
|
||||
m_sTouchData.touchSurfaceOrigin = g_pInputManager->getMouseCoordsInternal() - local;
|
||||
}
|
||||
|
||||
m_sTouchData.touchSurfaceOrigin = g_pInputManager->getMouseCoordsInternal() - local;
|
||||
} else if (m_sTouchData.touchFocusLS) {
|
||||
local = g_pInputManager->getMouseCoordsInternal() - Vector2D(m_sTouchData.touchFocusLS->geometry.x, m_sTouchData.touchFocusLS->geometry.y);
|
||||
|
||||
@@ -63,7 +63,9 @@ void CInputManager::onTouchMove(wlr_touch_motion_event* e) {
|
||||
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PMONITOR->vecPosition.x + e->x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e->y * PMONITOR->vecSize.y);
|
||||
|
||||
const auto local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchSurfaceOrigin;
|
||||
auto local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchSurfaceOrigin;
|
||||
if (m_sTouchData.touchFocusWindow->m_bIsX11)
|
||||
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);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
globber = run_command('find', '.', '-name', '*.cpp', check: true)
|
||||
globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true)
|
||||
src = globber.stdout().strip().split('\n')
|
||||
|
||||
executable('Hyprland', src,
|
||||
|
@@ -9,6 +9,10 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
APICALL const char* __hyprland_api_get_hash() {
|
||||
return GIT_COMMIT_HASH;
|
||||
}
|
||||
|
||||
APICALL bool HyprlandAPI::registerCallbackStatic(HANDLE handle, const std::string& event, HOOK_CALLBACK_FN* fn) {
|
||||
auto* const PLUGIN = g_pPluginSystem->getPluginByHandle(handle);
|
||||
|
||||
@@ -107,7 +111,7 @@ APICALL bool HyprlandAPI::removeFunctionHook(HANDLE handle, CFunctionHook* hook)
|
||||
return g_pFunctionHookSystem->removeHook(hook);
|
||||
}
|
||||
|
||||
APICALL bool HyprlandAPI::addWindowDecoration(HANDLE handle, CWindow* pWindow, IHyprWindowDecoration* pDecoration) {
|
||||
APICALL bool HyprlandAPI::addWindowDecoration(HANDLE handle, CWindow* pWindow, std::unique_ptr<IHyprWindowDecoration> pDecoration) {
|
||||
auto* const PLUGIN = g_pPluginSystem->getPluginByHandle(handle);
|
||||
|
||||
if (!PLUGIN)
|
||||
@@ -116,11 +120,10 @@ APICALL bool HyprlandAPI::addWindowDecoration(HANDLE handle, CWindow* pWindow, I
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return false;
|
||||
|
||||
PLUGIN->registeredDecorations.push_back(pDecoration);
|
||||
PLUGIN->registeredDecorations.push_back(pDecoration.get());
|
||||
|
||||
pWindow->m_dWindowDecorations.emplace_back(pDecoration);
|
||||
pWindow->addWindowDeco(std::move(pDecoration));
|
||||
|
||||
pWindow->updateWindowDecos();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow);
|
||||
|
||||
return true;
|
||||
@@ -135,7 +138,7 @@ APICALL bool HyprlandAPI::removeWindowDecoration(HANDLE handle, IHyprWindowDecor
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
for (auto& d : w->m_dWindowDecorations) {
|
||||
if (d.get() == pDecoration) {
|
||||
std::erase(w->m_dWindowDecorations, d);
|
||||
w->removeWindowDeco(pDecoration);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -153,13 +156,26 @@ APICALL bool HyprlandAPI::addConfigValue(HANDLE handle, const std::string& name,
|
||||
if (!PLUGIN)
|
||||
return false;
|
||||
|
||||
if (name.find("plugin:") != 0)
|
||||
if (!name.starts_with("plugin:"))
|
||||
return false;
|
||||
|
||||
g_pConfigManager->addPluginConfigVar(handle, name, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
APICALL bool HyprlandAPI::addConfigKeyword(HANDLE handle, const std::string& name, std::function<void(const std::string& key, const std::string& val)> fn) {
|
||||
auto* const PLUGIN = g_pPluginSystem->getPluginByHandle(handle);
|
||||
|
||||
if (!g_pPluginSystem->m_bAllowConfigVars)
|
||||
return false;
|
||||
|
||||
if (!PLUGIN)
|
||||
return false;
|
||||
|
||||
g_pConfigManager->addPluginKeyword(handle, name, fn);
|
||||
return true;
|
||||
}
|
||||
|
||||
APICALL SConfigValue* HyprlandAPI::getConfigValue(HANDLE handle, const std::string& name) {
|
||||
auto* const PLUGIN = g_pPluginSystem->getPluginByHandle(handle);
|
||||
|
||||
@@ -277,7 +293,7 @@ APICALL std::vector<SFunctionMatch> HyprlandAPI::findFunctionsByName(HANDLE hand
|
||||
const auto FPATH = std::filesystem::canonical(exe);
|
||||
#elif defined(__OpenBSD__)
|
||||
// Neither KERN_PROC_PATHNAME nor /proc are supported
|
||||
const auto FPATH = std::filesystem::canonical("/usr/local/bin/Hyprland");
|
||||
const auto FPATH = std::filesystem::canonical("/usr/local/bin/Hyprland");
|
||||
#else
|
||||
const auto FPATH = std::filesystem::canonical("/proc/self/exe");
|
||||
#endif
|
||||
@@ -301,7 +317,11 @@ APICALL std::vector<SFunctionMatch> HyprlandAPI::findFunctionsByName(HANDLE hand
|
||||
count++;
|
||||
}
|
||||
|
||||
return SYMBOLSDEMANGLED.substr(pos, SYMBOLSDEMANGLED.find('\n', pos + 1) - pos);
|
||||
// Skip the newline char itself
|
||||
if (pos != 0)
|
||||
pos++;
|
||||
|
||||
return SYMBOLSDEMANGLED.substr(pos, SYMBOLSDEMANGLED.find('\n', pos) - pos);
|
||||
};
|
||||
|
||||
if (SYMBOLS.empty()) {
|
||||
@@ -334,3 +354,12 @@ APICALL std::vector<SFunctionMatch> HyprlandAPI::findFunctionsByName(HANDLE hand
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
APICALL SVersionInfo HyprlandAPI::getHyprlandVersion(HANDLE handle) {
|
||||
auto* const PLUGIN = g_pPluginSystem->getPluginByHandle(handle);
|
||||
|
||||
if (!PLUGIN)
|
||||
return {};
|
||||
|
||||
return {GIT_COMMIT_HASH, GIT_TAG, GIT_DIRTY != std::string(""), GIT_BRANCH, GIT_COMMIT_MESSAGE};
|
||||
}
|
@@ -23,12 +23,13 @@ Feel like the API is missing something you'd like to use in your plugin? Open an
|
||||
#include "../helpers/Color.hpp"
|
||||
#include "HookSystem.hpp"
|
||||
#include "../SharedDefs.hpp"
|
||||
#include "../version.h"
|
||||
|
||||
#include <any>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
typedef std::function<void(void*, std::any)> HOOK_CALLBACK_FN;
|
||||
typedef std::function<void(void*, SCallbackInfo&, std::any)> HOOK_CALLBACK_FN;
|
||||
typedef struct {
|
||||
std::string name;
|
||||
std::string description;
|
||||
@@ -42,6 +43,14 @@ struct SFunctionMatch {
|
||||
std::string demangled;
|
||||
};
|
||||
|
||||
struct SVersionInfo {
|
||||
std::string hash;
|
||||
std::string tag;
|
||||
bool dirty = false;
|
||||
std::string branch;
|
||||
std::string message;
|
||||
};
|
||||
|
||||
#define APICALL extern "C"
|
||||
#define EXPORT __attribute__((visibility("default")))
|
||||
#define REQUIRED
|
||||
@@ -105,6 +114,14 @@ namespace HyprlandAPI {
|
||||
*/
|
||||
APICALL bool addConfigValue(HANDLE handle, const std::string& name, const SConfigValue& value);
|
||||
|
||||
/*
|
||||
Add a config keyword.
|
||||
This method may only be called in "pluginInit"
|
||||
|
||||
returns: true on success, false on fail
|
||||
*/
|
||||
APICALL bool addConfigKeyword(HANDLE handle, const std::string& name, std::function<void(const std::string& key, const std::string& val)> fn);
|
||||
|
||||
/*
|
||||
Get a config value.
|
||||
|
||||
@@ -204,7 +221,7 @@ namespace HyprlandAPI {
|
||||
|
||||
returns: true on success. False otherwise.
|
||||
*/
|
||||
APICALL bool addWindowDecoration(HANDLE handle, CWindow* pWindow, IHyprWindowDecoration* pDecoration);
|
||||
APICALL bool addWindowDecoration(HANDLE handle, CWindow* pWindow, std::unique_ptr<IHyprWindowDecoration> pDecoration);
|
||||
|
||||
/*
|
||||
Removes a window decoration
|
||||
@@ -250,4 +267,24 @@ namespace HyprlandAPI {
|
||||
Empty means either none found or handle was invalid
|
||||
*/
|
||||
APICALL std::vector<SFunctionMatch> findFunctionsByName(HANDLE handle, const std::string& name);
|
||||
};
|
||||
|
||||
/*
|
||||
Returns the hyprland version data. It's highly advised to not run plugins compiled
|
||||
for a different hash.
|
||||
*/
|
||||
APICALL SVersionInfo getHyprlandVersion(HANDLE handle);
|
||||
};
|
||||
|
||||
/*
|
||||
Get the hash this plugin/server was compiled with.
|
||||
|
||||
This function will end up in both hyprland and any/all plugins,
|
||||
and can be found by a simple dlsym()
|
||||
|
||||
_get_hash() is server,
|
||||
_get_client_hash() is client.
|
||||
*/
|
||||
APICALL EXPORT const char* __hyprland_api_get_hash();
|
||||
APICALL inline EXPORT const char* __hyprland_api_get_client_hash() {
|
||||
return GIT_COMMIT_HASH;
|
||||
}
|
||||
|
@@ -78,6 +78,11 @@ void CFractionalScaleProtocolManager::getFractionalScale(wl_client* client, wl_r
|
||||
const auto PSURFACE = wlr_surface_from_resource(surface);
|
||||
const auto PADDON = getAddonForSurface(PSURFACE);
|
||||
|
||||
if (PADDON->pResource) {
|
||||
wl_resource_post_error(resource, WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_FRACTIONAL_SCALE_EXISTS, "Fractional scale exists.");
|
||||
return;
|
||||
}
|
||||
|
||||
PADDON->pResource = wl_resource_create(client, &wp_fractional_scale_v1_interface, wl_resource_get_version(resource), id);
|
||||
wl_resource_set_implementation(PADDON->pResource, &fractionalScaleAddonImpl, PADDON, handleAddonDestroy);
|
||||
|
||||
|
@@ -119,7 +119,7 @@ CScreencopyClient::~CScreencopyClient() {
|
||||
CScreencopyClient::CScreencopyClient() {
|
||||
lastMeasure.reset();
|
||||
lastFrame.reset();
|
||||
tickCallback = g_pHookSystem->hookDynamic("tick", [&](void* self, std::any data) { onTick(); });
|
||||
tickCallback = g_pHookSystem->hookDynamic("tick", [&](void* self, SCallbackInfo& info, std::any data) { onTick(); });
|
||||
}
|
||||
|
||||
void CScreencopyClient::onTick() {
|
||||
@@ -183,7 +183,7 @@ void CScreencopyProtocolManager::removeFrame(SScreencopyFrame* frame, bool force
|
||||
m_lFrames.remove(*frame);
|
||||
}
|
||||
|
||||
void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output, wlr_box box) {
|
||||
void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output, CBox box) {
|
||||
const auto PCLIENT = clientFromResource(resource);
|
||||
|
||||
const auto PFRAME = &m_lFrames.emplace_back();
|
||||
@@ -239,8 +239,7 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r
|
||||
}
|
||||
int ow, oh;
|
||||
wlr_output_effective_resolution(PFRAME->pMonitor->output, &ow, &oh);
|
||||
wlr_box_transform(&PFRAME->box, &PFRAME->box, PFRAME->pMonitor->transform, ow, oh);
|
||||
scaleBox(&PFRAME->box, PFRAME->pMonitor->scale);
|
||||
PFRAME->box.transform(PFRAME->pMonitor->transform, ow, oh).scale(PFRAME->pMonitor->scale).round();
|
||||
|
||||
PFRAME->shmStride = (PSHMINFO->bpp / 8) * PFRAME->box.width;
|
||||
|
||||
@@ -263,20 +262,23 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PBUFFER = wlr_buffer_from_resource(buffer);
|
||||
const auto PBUFFER = wlr_buffer_try_from_resource(buffer);
|
||||
if (!PBUFFER) {
|
||||
Debug::log(ERR, "[sc] invalid buffer in {:x}", (uintptr_t)PFRAME);
|
||||
wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer");
|
||||
removeFrame(PFRAME);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PBUFFER->width != PFRAME->box.width || PBUFFER->height != PFRAME->box.height) {
|
||||
Debug::log(ERR, "[sc] invalid dimensions in {:x}", (uintptr_t)PFRAME);
|
||||
wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer dimensions");
|
||||
removeFrame(PFRAME);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PFRAME->buffer) {
|
||||
Debug::log(ERR, "[sc] buffer used in {:x}", (uintptr_t)PFRAME);
|
||||
wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_ALREADY_USED, "frame already used");
|
||||
removeFrame(PFRAME);
|
||||
return;
|
||||
@@ -290,6 +292,7 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou
|
||||
PFRAME->bufferCap = WLR_BUFFER_CAP_DMABUF;
|
||||
|
||||
if (dmabufAttrs.format != PFRAME->dmabufFormat) {
|
||||
Debug::log(ERR, "[sc] invalid buffer dma format in {:x}", (uintptr_t)PFRAME);
|
||||
wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format");
|
||||
removeFrame(PFRAME);
|
||||
return;
|
||||
@@ -298,15 +301,18 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou
|
||||
wlr_buffer_end_data_ptr_access(PBUFFER);
|
||||
|
||||
if (wlrBufferAccessFormat != PFRAME->shmFormat) {
|
||||
Debug::log(ERR, "[sc] invalid buffer shm format in {:x}", (uintptr_t)PFRAME);
|
||||
wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format");
|
||||
removeFrame(PFRAME);
|
||||
return;
|
||||
} else if ((int)wlrBufferAccessStride != PFRAME->shmStride) {
|
||||
Debug::log(ERR, "[sc] invalid buffer shm stride in {:x}", (uintptr_t)PFRAME);
|
||||
wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer stride");
|
||||
removeFrame(PFRAME);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
Debug::log(ERR, "[sc] invalid buffer type in {:x}", (uintptr_t)PFRAME);
|
||||
wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer type");
|
||||
removeFrame(PFRAME);
|
||||
return;
|
||||
@@ -325,7 +331,7 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou
|
||||
}
|
||||
|
||||
void CScreencopyProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e) {
|
||||
m_pLastMonitorBackBuffer = e->buffer;
|
||||
m_pLastMonitorBackBuffer = e->state->buffer;
|
||||
shareAllFrames(pMonitor);
|
||||
m_pLastMonitorBackBuffer = nullptr;
|
||||
}
|
||||
@@ -382,11 +388,13 @@ void CScreencopyProtocolManager::shareFrame(SScreencopyFrame* frame) {
|
||||
uint32_t flags = 0;
|
||||
if (frame->bufferCap == WLR_BUFFER_CAP_DMABUF) {
|
||||
if (!copyFrameDmabuf(frame)) {
|
||||
Debug::log(ERR, "[sc] dmabuf copy failed in {:x}", (uintptr_t)frame);
|
||||
zwlr_screencopy_frame_v1_send_failed(frame->resource);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!copyFrameShm(frame, &now)) {
|
||||
Debug::log(ERR, "[sc] shm copy failed in {:x}", (uintptr_t)frame);
|
||||
zwlr_screencopy_frame_v1_send_failed(frame->resource);
|
||||
return;
|
||||
}
|
||||
|
@@ -46,7 +46,7 @@ struct SScreencopyFrame {
|
||||
|
||||
uint32_t shmFormat = 0;
|
||||
uint32_t dmabufFormat = 0;
|
||||
wlr_box box = {0};
|
||||
CBox box = {};
|
||||
int shmStride = 0;
|
||||
|
||||
bool overlayCursor = false;
|
||||
@@ -73,7 +73,7 @@ class CScreencopyProtocolManager {
|
||||
void removeFrame(SScreencopyFrame* frame, bool force = false);
|
||||
void displayDestroy();
|
||||
|
||||
void captureOutput(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output, wlr_box box = {0, 0, 0, 0});
|
||||
void captureOutput(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output, CBox box = {0, 0, 0, 0});
|
||||
|
||||
void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer);
|
||||
|
||||
|
@@ -200,7 +200,7 @@ void CTextInputV1ProtocolManager::handleSetContentType(wl_client* client, wl_res
|
||||
|
||||
void CTextInputV1ProtocolManager::handleSetCursorRectangle(wl_client* client, wl_resource* resource, int32_t x, int32_t y, int32_t width, int32_t height) {
|
||||
const auto PTI = tiFromResource(resource);
|
||||
PTI->cursorRectangle = wlr_box{x, y, width, height};
|
||||
PTI->cursorRectangle = CBox{x, y, width, height};
|
||||
}
|
||||
|
||||
void CTextInputV1ProtocolManager::handleSetPreferredLanguage(wl_client* client, wl_resource* resource, const char* language) {
|
||||
|
@@ -39,9 +39,9 @@ struct STextInputV1 {
|
||||
uint32_t purpose = 0;
|
||||
} pendingContentType;
|
||||
|
||||
wlr_box cursorRectangle = {0, 0, 0, 0};
|
||||
CBox cursorRectangle = {0, 0, 0, 0};
|
||||
|
||||
bool operator==(const STextInputV1& other) {
|
||||
bool operator==(const STextInputV1& other) {
|
||||
return other.client == client && other.resourceCaller == resourceCaller && other.resourceImpl == resourceImpl;
|
||||
}
|
||||
};
|
||||
|
@@ -201,7 +201,7 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou
|
||||
PFRAME->box = {0, 0, (int)(PFRAME->pWindow->m_vRealSize.vec().x * PMONITOR->scale), (int)(PFRAME->pWindow->m_vRealSize.vec().y * PMONITOR->scale)};
|
||||
int ow, oh;
|
||||
wlr_output_effective_resolution(PMONITOR->output, &ow, &oh);
|
||||
wlr_box_transform(&PFRAME->box, &PFRAME->box, PMONITOR->transform, ow, oh);
|
||||
PFRAME->box.transform(PMONITOR->transform, ow, oh).round();
|
||||
|
||||
PFRAME->shmStride = (PSHMINFO->bpp / 8) * PFRAME->box.width;
|
||||
|
||||
@@ -229,7 +229,7 @@ void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* r
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PBUFFER = wlr_buffer_from_resource(buffer);
|
||||
const auto PBUFFER = wlr_buffer_try_from_resource(buffer);
|
||||
if (!PBUFFER) {
|
||||
wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer");
|
||||
removeFrame(PFRAME);
|
||||
@@ -301,9 +301,9 @@ void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_outp
|
||||
if (PMONITOR != g_pCompositor->getMonitorFromID(f->pWindow->m_iMonitorID))
|
||||
continue;
|
||||
|
||||
wlr_box geometry = {f->pWindow->m_vRealPosition.vec().x, f->pWindow->m_vRealPosition.vec().y, f->pWindow->m_vRealSize.vec().x, f->pWindow->m_vRealSize.vec().y};
|
||||
CBox geometry = {f->pWindow->m_vRealPosition.vec().x, f->pWindow->m_vRealPosition.vec().y, f->pWindow->m_vRealSize.vec().x, f->pWindow->m_vRealSize.vec().y};
|
||||
|
||||
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, &geometry))
|
||||
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, geometry.pWlr()))
|
||||
continue;
|
||||
|
||||
shareFrame(f);
|
||||
@@ -448,7 +448,7 @@ bool CToplevelExportProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame, ti
|
||||
|
||||
g_pHyprOpenGL->bindWlrOutputFb();
|
||||
|
||||
wlr_box monbox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
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();
|
||||
|
@@ -58,9 +58,9 @@ void CXDGOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver
|
||||
}
|
||||
|
||||
CXDGOutputProtocol::CXDGOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||
g_pHookSystem->hookDynamic("monitorLayoutChanged", [this](void* self, std::any param) { this->updateAllOutputs(); });
|
||||
g_pHookSystem->hookDynamic("configReloaded", [this](void* self, std::any param) { this->updateAllOutputs(); });
|
||||
g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, std::any param) {
|
||||
g_pHookSystem->hookDynamic("monitorLayoutChanged", [this](void* self, SCallbackInfo& info, std::any param) { this->updateAllOutputs(); });
|
||||
g_pHookSystem->hookDynamic("configReloaded", [this](void* self, SCallbackInfo& info, std::any param) { this->updateAllOutputs(); });
|
||||
g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) {
|
||||
const auto PMONITOR = std::any_cast<CMonitor*>(param);
|
||||
std::erase_if(m_vXDGOutputs, [&](const auto& other) {
|
||||
const auto REMOVE = other->monitor == PMONITOR;
|
||||
@@ -72,15 +72,9 @@ CXDGOutputProtocol::CXDGOutputProtocol(const wl_interface* iface, const int& ver
|
||||
}
|
||||
|
||||
void CXDGOutputProtocol::onManagerGetXDGOutput(wl_client* client, wl_resource* resource, uint32_t id, wl_resource* outputResource) {
|
||||
const auto OUTPUT = wlr_output_from_resource(outputResource);
|
||||
const auto OUTPUT = wlr_output_from_resource(outputResource);
|
||||
|
||||
if (!OUTPUT)
|
||||
return;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(OUTPUT);
|
||||
|
||||
if (!PMONITOR)
|
||||
return;
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(OUTPUT);
|
||||
|
||||
SXDGOutput* pXDGOutput = m_vXDGOutputs.emplace_back(std::make_unique<SXDGOutput>(PMONITOR)).get();
|
||||
#ifndef NO_XWAYLAND
|
||||
@@ -99,6 +93,10 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(wl_client* client, wl_resource* r
|
||||
|
||||
pXDGOutput->resource->setImplementation(&OUTPUT_IMPL, nullptr);
|
||||
pXDGOutput->resource->setData(this);
|
||||
|
||||
if (!PMONITOR)
|
||||
return;
|
||||
|
||||
const auto XDGVER = pXDGOutput->resource->version();
|
||||
|
||||
if (XDGVER >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION)
|
||||
@@ -116,7 +114,7 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(wl_client* client, wl_resource* r
|
||||
void CXDGOutputProtocol::updateOutputDetails(SXDGOutput* pOutput) {
|
||||
static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue;
|
||||
|
||||
if (!pOutput->resource->good())
|
||||
if (!pOutput->resource->good() || !pOutput->monitor)
|
||||
return;
|
||||
|
||||
const auto POS = pOutput->isXWayland ? pOutput->monitor->vecXWaylandPosition : pOutput->monitor->vecPosition;
|
||||
@@ -133,6 +131,10 @@ void CXDGOutputProtocol::updateOutputDetails(SXDGOutput* pOutput) {
|
||||
|
||||
void CXDGOutputProtocol::updateAllOutputs() {
|
||||
for (auto& o : m_vXDGOutputs) {
|
||||
|
||||
if (!o->monitor)
|
||||
continue;
|
||||
|
||||
updateOutputDetails(o.get());
|
||||
|
||||
wlr_output_schedule_done(o->monitor->output);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user