Compare commits
295 Commits
v0.6.2beta
...
v0.8.1beta
Author | SHA1 | Date | |
---|---|---|---|
|
d3c1d3435c | ||
|
57f5de68ae | ||
|
eb30d9bdc8 | ||
|
98ef43496b | ||
|
1455442b9a | ||
|
71c1ff8ee3 | ||
|
b18a2738e3 | ||
|
99ebbb36b2 | ||
|
6f2368f809 | ||
|
7dc014e967 | ||
|
66eac124e2 | ||
|
d04f36c57d | ||
|
7babcf7e6a | ||
|
b0d91cbf3a | ||
|
db899e00e7 | ||
|
6e16dfa5e5 | ||
|
c998e946aa | ||
|
cde39e0b6e | ||
|
b1d3a1deea | ||
|
e2594c79cc | ||
|
a0be6e19d8 | ||
|
14176f01ca | ||
|
574d950145 | ||
|
bb539f0a8d | ||
|
067e2d39f6 | ||
|
e388a86c9d | ||
|
3e6abaf680 | ||
|
6dc8c4b310 | ||
|
1ddd7ee713 | ||
|
92d1d21a3d | ||
|
8dcc3032a8 | ||
|
1626707b7f | ||
|
72700bf9dc | ||
|
616ec22735 | ||
|
d9b0edb786 | ||
|
3f169a937a | ||
|
fa1273f258 | ||
|
8f66ddcad0 | ||
|
4db1062af6 | ||
|
0013ef9ef0 | ||
|
19cd04c85f | ||
|
a011c28227 | ||
|
d5ccca4fdb | ||
|
f512bf6b5a | ||
|
ce508f1cdc | ||
|
eb8a1939e6 | ||
|
7f660fed0d | ||
|
75ce01b1a7 | ||
|
b9f8d900b3 | ||
|
189cbe9f09 | ||
|
fa2bd3b1a8 | ||
|
fc33cae70c | ||
|
641aaff998 | ||
|
9463e3eb0a | ||
|
e6b151b6c3 | ||
|
d52446135b | ||
|
1ba600ca23 | ||
|
0026414f9b | ||
|
ce8d655fad | ||
|
d4690a5c5e | ||
|
755245e752 | ||
|
ec2afb563e | ||
|
59e34e311e | ||
|
c6c3d66373 | ||
|
21217bcb2b | ||
|
f905ae33c8 | ||
|
0281caa8e0 | ||
|
f35d513bf5 | ||
|
10a83853ac | ||
|
53b8263eb1 | ||
|
8bcfda2230 | ||
|
f2c0e6ef02 | ||
|
b669948737 | ||
|
a4b1d51c63 | ||
|
e7b8cda360 | ||
|
c466bd1219 | ||
|
ad19a15cef | ||
|
954a387cf9 | ||
|
a51f44d566 | ||
|
423c9f9d56 | ||
|
900e6947e9 | ||
|
90d07d7b52 | ||
|
60cc33a53c | ||
|
dc1f34c5fa | ||
|
afeb040684 | ||
|
f5bd30569f | ||
|
6f1b9d6af9 | ||
|
1848086abd | ||
|
cb2989cec5 | ||
|
16afa2c422 | ||
|
edcecae7a0 | ||
|
aac546b771 | ||
|
ef24329495 | ||
|
5c836e6460 | ||
|
68cfc1a496 | ||
|
08319dd1f5 | ||
|
4f9be67298 | ||
|
ce9efb7ae3 | ||
|
48e5bd96bc | ||
|
2ae088d631 | ||
|
fdbc54d97b | ||
|
e56ff0fcb0 | ||
|
43b7da0bb1 | ||
|
b2650928ea | ||
|
069e3b2114 | ||
|
db693ec7e5 | ||
|
16fecac2d1 | ||
|
1eceae811f | ||
|
fbcc6936f4 | ||
|
90ebeaa881 | ||
|
1441856811 | ||
|
19c646ab47 | ||
|
5388b54442 | ||
|
6306d4dae3 | ||
|
5af26a451a | ||
|
ba48e7ceea | ||
|
c0377457df | ||
|
202fb4d8d4 | ||
|
d8fee02063 | ||
|
01fc3d6068 | ||
|
634970a284 | ||
|
642af5395e | ||
|
316589406f | ||
|
0085319c18 | ||
|
0488f17976 | ||
|
8b52858bb5 | ||
|
b0dd370421 | ||
|
65e75c0b44 | ||
|
7c999fb9f5 | ||
|
21da348826 | ||
|
c2215e4efb | ||
|
49dbb586e3 | ||
|
6708f3b133 | ||
|
ef7ee2fd0f | ||
|
e93b45615c | ||
|
0a16513946 | ||
|
99e9503732 | ||
|
be69098cb8 | ||
|
d7d5b1a4eb | ||
|
868fc6e0f3 | ||
|
9580ef4bc2 | ||
|
532ffe1681 | ||
|
0cfc97972f | ||
|
ab859ec9fc | ||
|
ac9ff795cd | ||
|
4bea3467e0 | ||
|
bca93f4d3c | ||
|
bf762f566f | ||
|
2402f2e364 | ||
|
036f431206 | ||
|
f9985a36b3 | ||
|
ad03360665 | ||
|
3914672dd5 | ||
|
78c6371743 | ||
|
f789a14527 | ||
|
b1e3430405 | ||
|
a4f82491b7 | ||
|
da83ef7b96 | ||
|
2d856ac4b0 | ||
|
29e2bb27f6 | ||
|
2f3b2db83d | ||
|
bf8bd87d11 | ||
|
c0c75db621 | ||
|
f461ea3105 | ||
|
668dc9bd9c | ||
|
b55b6c95f2 | ||
|
676e4c36c5 | ||
|
ad66c158ba | ||
|
ab44aabbd7 | ||
|
4c4c36096b | ||
|
c923b0e538 | ||
|
2936368e80 | ||
|
5eaf93697a | ||
|
11c88e2503 | ||
|
4b334594dc | ||
|
06c0be5ea6 | ||
|
6f7377f381 | ||
|
c44cafda97 | ||
|
ddc4cbbd7e | ||
|
e6872bddf4 | ||
|
a7a3c0fc1d | ||
|
c8c5e0b90a | ||
|
8482063157 | ||
|
92e17f2925 | ||
|
491b99c61e | ||
|
75a580feda | ||
|
91249675de | ||
|
46306e59eb | ||
|
cd0a01f4de | ||
|
75c2a378e3 | ||
|
96f19d706a | ||
|
3278db67a2 | ||
|
aa3bc65342 | ||
|
a7b595d968 | ||
|
05736bc1e3 | ||
|
3bf172a37e | ||
|
22c4ecf496 | ||
|
3f43f94dc4 | ||
|
4b796d30c1 | ||
|
5762e3b9e2 | ||
|
1cf2f378d4 | ||
|
6a16f11d63 | ||
|
a545992891 | ||
|
f5936f97d6 | ||
|
141f9810bb | ||
|
1599dc47d1 | ||
|
42d18143e5 | ||
|
f9756d10d4 | ||
|
0d7a8cca79 | ||
|
9655d0c138 | ||
|
5a22335b8d | ||
|
0277f4c6bd | ||
|
8d05dddb98 | ||
|
0d54451c67 | ||
|
cda0c4577e | ||
|
239aa2cec4 | ||
|
ae096219e8 | ||
|
7ff427c229 | ||
|
55aeb91e6a | ||
|
6f5b8425cb | ||
|
dd422abb33 | ||
|
cc8b8f595f | ||
|
9742ac7596 | ||
|
beef23cee5 | ||
|
7e38de37a7 | ||
|
e0bfec6ef2 | ||
|
c40ef59a35 | ||
|
c71b76a9e0 | ||
|
853a33888b | ||
|
fc3957d538 | ||
|
3df126c675 | ||
|
69e179816b | ||
|
a229701f28 | ||
|
01228fbc9c | ||
|
f7c4865bac | ||
|
0a01ec9926 | ||
|
e0f0ed9af4 | ||
|
e81de82706 | ||
|
9d6999345e | ||
|
cb8a6f881b | ||
|
185c4d6ea1 | ||
|
b7b3344188 | ||
|
80962de2a2 | ||
|
9ee14eb445 | ||
|
e77f451e27 | ||
|
6f4f164071 | ||
|
3d294b1aaa | ||
|
7d7e82d446 | ||
|
2225dca576 | ||
|
868e0f48d0 | ||
|
1750a7cdbb | ||
|
6f2a36c123 | ||
|
29ca7f9018 | ||
|
91d68513de | ||
|
3970b43ea2 | ||
|
92890d492a | ||
|
d010ca2049 | ||
|
4510764f34 | ||
|
96a23eca81 | ||
|
ac8a23c3ae | ||
|
990d3f232b | ||
|
97b515edb7 | ||
|
328b3fa4bc | ||
|
d1564299d2 | ||
|
cfc1f6c211 | ||
|
a7ebf0ddc3 | ||
|
4101006b5e | ||
|
b0cd90a43c | ||
|
ae3ff6736e | ||
|
7d20d5c8c3 | ||
|
6ce2678970 | ||
|
d28151d255 | ||
|
be390dacfd | ||
|
dc83110c05 | ||
|
cbf3595e96 | ||
|
2659afee3c | ||
|
9391357063 | ||
|
6ec16fdcda | ||
|
208864cba9 | ||
|
bbc3b5e19b | ||
|
697ce96d62 | ||
|
31a1b3b192 | ||
|
8820f7f210 | ||
|
73663a8ba5 | ||
|
13acfb1c30 | ||
|
37abe0aedc | ||
|
5636d2031e | ||
|
9388bb5d55 | ||
|
fc4b10d13c | ||
|
504f76112a | ||
|
be460ea954 | ||
|
776ca3baf2 | ||
|
8f62f6d4b0 | ||
|
7d80327e7d | ||
|
3d46c73981 |
6
.github/pull_request_template.md
vendored
@@ -1,9 +1,9 @@
|
||||
Describe your PR, what does it fix/add?
|
||||
#### Describe your PR, what does it fix/add?
|
||||
|
||||
|
||||
Is there anything you want to mention? (unchecked code, possible bugs, found problems, breaking compatibility, etc.)
|
||||
#### Is there anything you want to mention? (unchecked code, possible bugs, found problems, breaking compatibility, etc.)
|
||||
|
||||
|
||||
Is it ready for merging, or does it need work?
|
||||
#### Is it ready for merging, or does it need work?
|
||||
|
||||
|
||||
|
38
.github/workflows/release.yaml
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
name: Release artifacts
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
source-tarball:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Hyprland
|
||||
id: checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Create tarball with submodules
|
||||
id: tar
|
||||
run: tar -czv --owner=0 --group=0 --no-same-owner --no-same-permissions -f source.tar.gz *
|
||||
|
||||
- id: whatrelease
|
||||
name: Get latest release
|
||||
uses: pozetroninc/github-action-get-latest-release@master
|
||||
with:
|
||||
owner: hyprwm
|
||||
repo: Hyprland
|
||||
excludes: prerelease, draft
|
||||
|
||||
- name: Upload to release
|
||||
id: upload
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: source.tar.gz
|
||||
asset_name: source-${{ steps.whatrelease.outputs.release }}.tar.gz
|
||||
tag: ${{ steps.whatrelease.outputs.release }}
|
||||
overwrite: true
|
2
.gitignore
vendored
@@ -12,6 +12,8 @@ _deps
|
||||
build/
|
||||
result
|
||||
/.vscode/
|
||||
.envrc
|
||||
.cache
|
||||
|
||||
*.o
|
||||
*-protocol.c
|
||||
|
@@ -36,12 +36,13 @@ execute_process(
|
||||
#
|
||||
|
||||
include_directories(. PRIVATE "subprojects/wlroots/include/")
|
||||
add_compile_options(-std=c++20 -DWLR_USE_UNSTABLE )
|
||||
include_directories(. PRIVATE "subprojects/wlroots/build/include/")
|
||||
add_compile_options(-std=c++23 -DWLR_USE_UNSTABLE )
|
||||
add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-narrowing)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo libdrm egl xkbcommon wlroots libinput xcb)
|
||||
pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo pango pangocairo libdrm egl xkbcommon libinput xcb) # we do not check for wlroots, as we provide it ourselves
|
||||
|
||||
file(GLOB_RECURSE SRCFILES "src/*.cpp")
|
||||
|
||||
@@ -61,7 +62,7 @@ IF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
message(STATUS "Configuring Hyprland in Debug with CMake!")
|
||||
add_definitions( -DHYPRLAND_DEBUG )
|
||||
ELSE()
|
||||
# add_compile_options(-O3) # may crash for some
|
||||
add_compile_options( -O3 )
|
||||
message(STATUS "Configuring Hyprland in Release with CMake!")
|
||||
ENDIF(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG)
|
||||
|
||||
@@ -79,7 +80,7 @@ include(CPack)
|
||||
target_link_libraries(Hyprland PkgConfig::deps)
|
||||
|
||||
target_link_libraries(Hyprland
|
||||
wlroots
|
||||
${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.11032 # wlroots is provided by us
|
||||
pixman-1
|
||||
OpenGL
|
||||
GLESv2
|
||||
|
28
Makefile
@@ -99,7 +99,7 @@ clear:
|
||||
rm -rf build
|
||||
rm -f *.o *-protocol.h *-protocol.c
|
||||
rm -f ./hyprctl/hyprctl
|
||||
rm -rf ./wlroots/build
|
||||
rm -rf ./subprojects/wlroots/build
|
||||
|
||||
all:
|
||||
make config
|
||||
@@ -107,11 +107,13 @@ all:
|
||||
cd ./hyprctl && make all && cd ..
|
||||
|
||||
install:
|
||||
[ ! -d /usr/include/wlr ] || mv /usr/include/wlr /usr/include/wlrBackup
|
||||
[ ! -f /usr/lib/libwlroots.so ] || mv /usr/lib/libwlroots.so /usr/lib/libwlroots.so.backup
|
||||
[ ! -f /usr/lib/pkgconfig/wlroots.pc ] || mv /usr/lib/pkgconfig/wlroots.pc /usr/lib/pkgconfig/wlroots.pc.backup
|
||||
make clear
|
||||
make fixwlr
|
||||
cd ./subprojects/wlroots && meson build/ --buildtype=release && ninja -C build/ && cp ./build/libwlroots.so.11032 /usr/lib/ && cd ../..
|
||||
make protocols
|
||||
make release
|
||||
cd hyprctl && make all && cd ..
|
||||
|
||||
make all
|
||||
mkdir -p ${PREFIX}/share/wayland-sessions
|
||||
cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions/
|
||||
mkdir -p ${PREFIX}/bin
|
||||
@@ -122,28 +124,26 @@ install:
|
||||
cp ./assets/wall_4K.png ${PREFIX}/share/hyprland
|
||||
cp ./assets/wall_8K.png ${PREFIX}/share/hyprland
|
||||
|
||||
rm -rf /usr/include/wlr
|
||||
rm -f /usr/lib/libwlroots.so
|
||||
rm -f /usr/lib/pkgconfig/wlroots.pc
|
||||
[ ! -d /usr/include/wlrBackup ] || mv /usr/include/wlrBackup /usr/include/wlr
|
||||
[ ! -f /usr/lib/libwlroots.so.backup ] || mv -f /usr/lib/libwlroots.so.backup /usr/lib/libwlroots.so
|
||||
[ ! -f /usr/lib/pkgconfig/wlroots.pc.backup ] || mv -f /usr/lib/pkgconfig/wlroots.pc.backup /usr/lib/pkgconfig/wlroots.pc
|
||||
|
||||
uninstall:
|
||||
rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop
|
||||
rm -f ${PREFIX}/bin/Hyprland
|
||||
rm -f ${PREFIX}/bin/hyprctl
|
||||
rm -f /usr/lib/libwlroots.so.11032
|
||||
rm -rf ${PREFIX}/share/hyprland
|
||||
|
||||
protocols: xdg-shell-protocol.o wlr-layer-shell-unstable-v1-protocol.o wlr-screencopy-unstable-v1-protocol.o idle-protocol.o ext-workspace-unstable-v1-protocol.o pointer-constraints-unstable-v1-protocol.o tablet-unstable-v2-protocol.o
|
||||
|
||||
config:
|
||||
make protocols
|
||||
|
||||
fixwlr:
|
||||
sed -i -E 's/(soversion = 11)([^032]|$$)/soversion = 11032/g' subprojects/wlroots/meson.build
|
||||
|
||||
rm -rf ./subprojects/wlroots/build
|
||||
|
||||
config:
|
||||
make protocols
|
||||
|
||||
make fixwlr
|
||||
|
||||
cd subprojects/wlroots && meson ./build --prefix=/usr --buildtype=release
|
||||
cd subprojects/wlroots && ninja -C build/
|
||||
|
||||
|
40
README.md
@@ -1,6 +1,6 @@
|
||||
<div align = center>
|
||||
|
||||
<img src="https://raw.githubusercontent.com/vaxerski/Hyprland/main/assets/header.svg" width="1000" height="500" alt="banner">
|
||||
<img src="https://raw.githubusercontent.com/vaxerski/Hyprland/main/assets/header.svg" width="750" height="300" alt="banner">
|
||||
|
||||
<br>
|
||||
|
||||
@@ -57,6 +57,7 @@ Try it out and report bugs / suggestions!
|
||||
- Drop shadows
|
||||
- Fully dynamic workspaces
|
||||
- Closely follows `wlroots-git`
|
||||
- Global keybinds passed to your apps of choice
|
||||
- Bundled wlroots
|
||||
- Window/layer fade in/out
|
||||
- Tiling/pseudotiling/floating/fullscreen windows
|
||||
@@ -69,6 +70,7 @@ Try it out and report bugs / suggestions!
|
||||
- Full damage tracking
|
||||
- Docks support
|
||||
- Drawing tablet support
|
||||
- and much more...
|
||||
|
||||
<br>
|
||||
<br>
|
||||
@@ -122,18 +124,18 @@ Try it out and report bugs / suggestions!
|
||||
|
||||
<!----------------------------------------------------------------------------->
|
||||
|
||||
[Configure]: https://github.com/vaxerski/Hyprland/wiki/Configuring-Hyprland
|
||||
[Configure]: https://github.com/hyprwm/Hyprland/wiki/Configuring-Hyprland
|
||||
[Discord]: https://discord.gg/hQ9XvMUjjr
|
||||
[Stars]: https://starchart.cc/vaxerski/Hyprland
|
||||
[Hypr]: https://github.com/vaxerski/Hypr
|
||||
[Stars]: https://starchart.cc/hyprwm/Hyprland
|
||||
[Hypr]: https://github.com/hyprwm/Hypr
|
||||
|
||||
[Pull Requests]: https://github.com/vaxerski/Hyprland/pulls
|
||||
[Issues]: https://github.com/vaxerski/Hyprland/issues
|
||||
[Todo]: https://github.com/vaxerski/Hyprland/projects?type=beta
|
||||
[Pull Requests]: https://github.com/hyprwm/Hyprland/pulls
|
||||
[Issues]: https://github.com/hyprwm/Hyprland/issues
|
||||
[Todo]: https://github.com/hyprwm/Hyprland/projects?type=beta
|
||||
|
||||
[Contribute]: https://github.com/vaxerski/Hyprland/wiki/Contributing-&-Debugging
|
||||
[Install]: https://github.com/vaxerski/Hyprland/wiki/Installation
|
||||
[Quick Start]: https://github.com/vaxerski/Hyprland/wiki/Quick-start
|
||||
[Contribute]: https://github.com/hyprwm/Hyprland/wiki/Contributing-&-Debugging
|
||||
[Install]: https://github.com/hyprwm/Hyprland/wiki/Installation
|
||||
[Quick Start]: https://github.com/hyprwm/Hyprland/wiki/Quick-start
|
||||
[License]: LICENSE
|
||||
|
||||
|
||||
@@ -149,19 +151,19 @@ Try it out and report bugs / suggestions!
|
||||
<!----------------------------------{ Images }--------------------------------->
|
||||
|
||||
[Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg
|
||||
[Preview A]: https://i.imgur.com/NbrTnZH.png
|
||||
[Preview B]: https://i.imgur.com/ZA4Fa8R.png
|
||||
[Preview C]: https://i.imgur.com/BpXxM8H.png
|
||||
[Preview A]: https://i.imgur.com/sCafdKQ.png
|
||||
[Preview B]: https://i.imgur.com/NbrTnZH.png
|
||||
[Preview C]: https://i.imgur.com/ZA4Fa8R.png
|
||||
|
||||
|
||||
<!----------------------------------{ Badges }--------------------------------->
|
||||
|
||||
[Badge Workflow]: https://github.com/vaxerski/Hyprland/actions/workflows/ci.yaml/badge.svg
|
||||
[Badge Workflow]: https://github.com/hyprwm/Hyprland/actions/workflows/ci.yaml/badge.svg
|
||||
|
||||
[Badge Discord]: https://img.shields.io/badge/Join%20the-Discord%20server-6666ff
|
||||
[Badge Issues]: https://img.shields.io/github/issues/vaxerski/Hyprland
|
||||
[Badge Pull Requests]: https://img.shields.io/github/issues-pr/vaxerski/Hyprland
|
||||
[Badge Language]: https://img.shields.io/github/languages/top/vaxerski/Hyprland
|
||||
[Badge License]: https://img.shields.io/github/license/vaxerski/Hyprland
|
||||
[Badge Lines]: https://img.shields.io/tokei/lines/github/vaxerski/Hyprland
|
||||
[Badge Issues]: https://img.shields.io/github/issues/hyprwm/Hyprland
|
||||
[Badge Pull Requests]: https://img.shields.io/github/issues-pr/hyprwm/Hyprland
|
||||
[Badge Language]: https://img.shields.io/github/languages/top/hyprwm/Hyprland
|
||||
[Badge License]: https://img.shields.io/github/license/hyprwm/Hyprland
|
||||
[Badge Lines]: https://img.shields.io/tokei/lines/github/hyprwm/Hyprland
|
||||
[Badge Hi Mom]: https://img.shields.io/badge/Hi-mom!-ff69b4
|
||||
|
Before Width: | Height: | Size: 798 KiB After Width: | Height: | Size: 506 KiB |
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 227 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 231 KiB After Width: | Height: | Size: 146 KiB |
@@ -26,6 +26,7 @@ If your bug is one that doesn't crash Hyprland, but feels like invalid behavior,
|
||||
If your bug crashes Hyprland, append additionally:
|
||||
- The Hyprland log
|
||||
- Coredump / Coredump analysis (with a stacktrace)
|
||||
- Your config
|
||||
|
||||
**Important**: Please do NOT use any package for reporting bugs! Clone and compile from source.
|
||||
|
||||
|
@@ -3,6 +3,11 @@
|
||||
#
|
||||
# Refer to the wiki for more information.
|
||||
|
||||
#
|
||||
# Please note not all available settings / options are set here.
|
||||
# For a full list, see the wiki (basic and advanced configuring)
|
||||
#
|
||||
|
||||
monitor=,1280x720@60,0x0,1
|
||||
workspace=DP-1,1
|
||||
|
||||
@@ -14,6 +19,10 @@ input {
|
||||
kb_rules=
|
||||
|
||||
follow_mouse=1
|
||||
|
||||
touchpad {
|
||||
natural_scroll=no
|
||||
}
|
||||
}
|
||||
|
||||
general {
|
||||
@@ -97,3 +106,6 @@ bind=ALT,7,movetoworkspace,7
|
||||
bind=ALT,8,movetoworkspace,8
|
||||
bind=ALT,9,movetoworkspace,9
|
||||
bind=ALT,0,movetoworkspace,10
|
||||
|
||||
bind=SUPER,mouse_down,workspace,e+1
|
||||
bind=SUPER,mouse_up,workspace,e-1
|
12
flake.lock
generated
@@ -2,11 +2,11 @@
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1656239181,
|
||||
"narHash": "sha256-wW1xRFBn376yGloXZ4QzBE4hjipMawpV18Lshd9QSPw=",
|
||||
"lastModified": 1657447684,
|
||||
"narHash": "sha256-FCP9AuU1q6PE3vOeM5SFf58f/UKPBAsoSGDUGamNBbo=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "f2537a505d45c31fe5d9c27ea9829b6f4c4e6ac5",
|
||||
"rev": "5f43d8b088d3771274bcfb69d3c7435b1121ac88",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -26,11 +26,11 @@
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"host": "gitlab.freedesktop.org",
|
||||
"lastModified": 1655824477,
|
||||
"narHash": "sha256-1kskHOLsnisR3kqIL5IHrQbQG/4xoXxeEf1ExMV6/RU=",
|
||||
"lastModified": 1656865312,
|
||||
"narHash": "sha256-xtQ0zwJZwN8sciruveM10CzKz6TWxBY8SyXa8E4jly4=",
|
||||
"owner": "wlroots",
|
||||
"repo": "wlroots",
|
||||
"rev": "5c4384a1330faedf975c8b8644881d50390f3613",
|
||||
"rev": "5dc1d4671dd2ca3c1f0f09587c463fdbb542f0a4",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
|
17
flake.nix
@@ -32,9 +32,14 @@
|
||||
src = inputs.wlroots;
|
||||
});
|
||||
hyprland = prev.callPackage ./nix/default.nix {
|
||||
version = "0.6.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101"));
|
||||
stdenv = prev.gcc12Stdenv;
|
||||
version = "0.7.0beta" + "+date=" + (mkDate (self.lastModifiedDate or "19700101"));
|
||||
wlroots = wlroots-hyprland;
|
||||
};
|
||||
hyprland-debug = hyprland.override {debug = true;};
|
||||
waybar-hyprland = prev.waybar.overrideAttrs (oldAttrs: {
|
||||
mesonFlags = oldAttrs.mesonFlags ++ ["-Dexperimental=true"];
|
||||
});
|
||||
};
|
||||
|
||||
packages = genSystems (system:
|
||||
@@ -43,6 +48,16 @@
|
||||
default = self.packages.${system}.hyprland;
|
||||
});
|
||||
|
||||
devShells = genSystems (system: {
|
||||
default = pkgsFor.${system}.mkShell.override {stdenv = pkgsFor.${system}.gcc12Stdenv;} {
|
||||
name = "hyprland-shell";
|
||||
inputsFrom = [
|
||||
self.packages.${system}.wlroots-hyprland
|
||||
self.packages.${system}.hyprland
|
||||
];
|
||||
};
|
||||
});
|
||||
|
||||
formatter = genSystems (system: pkgsFor.${system}.alejandra);
|
||||
|
||||
nixosModules.default = import ./nix/module.nix self;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
all:
|
||||
g++ -std=c++20 ./main.cpp -o ./hyprctl
|
||||
g++ -std=c++23 ./main.cpp -o ./hyprctl
|
||||
clean:
|
||||
rm ./hyprctl
|
||||
rm ./hyprctl
|
||||
|
156
hyprctl/main.cpp
@@ -9,14 +9,18 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#include <ranges>
|
||||
#include <algorithm>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <deque>
|
||||
|
||||
const std::string USAGE = R"#(usage: hyprctl [command] [(opt)args]
|
||||
const std::string USAGE = R"#(usage: hyprctl [(opt)flags] [command] [(opt)args]
|
||||
|
||||
commands:
|
||||
monitors
|
||||
workspaces
|
||||
clients
|
||||
@@ -27,7 +31,13 @@ const std::string USAGE = R"#(usage: hyprctl [command] [(opt)args]
|
||||
keyword
|
||||
version
|
||||
kill
|
||||
reload)#";
|
||||
splash
|
||||
hyprpaper
|
||||
reload
|
||||
|
||||
flags:
|
||||
j -> output in JSON
|
||||
)#";
|
||||
|
||||
void request(std::string arg) {
|
||||
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
@@ -75,7 +85,58 @@ void request(std::string arg) {
|
||||
|
||||
char buffer[8192] = {0};
|
||||
|
||||
sizeWritten = read(SERVERSOCKET,buffer, 8192);
|
||||
sizeWritten = read(SERVERSOCKET, buffer, 8192);
|
||||
|
||||
if (sizeWritten < 0) {
|
||||
std::cout << "Couldn't read (5)";
|
||||
return;
|
||||
}
|
||||
|
||||
close(SERVERSOCKET);
|
||||
|
||||
std::cout << std::string(buffer);
|
||||
}
|
||||
|
||||
void requestHyprpaper(std::string arg) {
|
||||
const auto SERVERSOCKET = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
if (SERVERSOCKET < 0) {
|
||||
std::cout << "Couldn't open a socket (1)";
|
||||
return;
|
||||
}
|
||||
|
||||
// get the instance signature
|
||||
auto instanceSig = getenv("HYPRLAND_INSTANCE_SIGNATURE");
|
||||
|
||||
if (!instanceSig) {
|
||||
std::cout << "HYPRLAND_INSTANCE_SIGNATURE was not set! (Is Hyprland running?)";
|
||||
return;
|
||||
}
|
||||
|
||||
std::string instanceSigStr = std::string(instanceSig);
|
||||
|
||||
sockaddr_un serverAddress = {0};
|
||||
serverAddress.sun_family = AF_UNIX;
|
||||
|
||||
std::string socketPath = "/tmp/hypr/" + instanceSigStr + "/.hyprpaper.sock";
|
||||
|
||||
strcpy(serverAddress.sun_path, socketPath.c_str());
|
||||
|
||||
if (connect(SERVERSOCKET, (sockaddr*)&serverAddress, SUN_LEN(&serverAddress)) < 0) {
|
||||
std::cout << "Couldn't connect to " << socketPath << ". (3)";
|
||||
return;
|
||||
}
|
||||
|
||||
auto sizeWritten = write(SERVERSOCKET, arg.c_str(), arg.length());
|
||||
|
||||
if (sizeWritten < 0) {
|
||||
std::cout << "Couldn't write (4)";
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[8192] = {0};
|
||||
|
||||
sizeWritten = read(SERVERSOCKET, buffer, 8192);
|
||||
|
||||
if (sizeWritten < 0) {
|
||||
std::cout << "Couldn't read (5)";
|
||||
@@ -94,7 +155,7 @@ void dispatchRequest(int argc, char** argv) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string rq = "dispatch " + std::string(argv[2]) + " " + std::string(argv[3]);
|
||||
std::string rq = "/dispatch " + std::string(argv[2]) + " " + std::string(argv[3]);
|
||||
|
||||
request(rq);
|
||||
}
|
||||
@@ -110,12 +171,36 @@ void keywordRequest(int argc, char** argv) {
|
||||
request(rq);
|
||||
}
|
||||
|
||||
void batchRequest(int argc, char** argv) {
|
||||
std::string rq = "[[BATCH]]" + std::string(argv[2]);
|
||||
void hyprpaperRequest(int argc, char** argv) {
|
||||
if (argc < 4) {
|
||||
std::cout << "hyprpaper requires 2 params";
|
||||
return;
|
||||
}
|
||||
|
||||
std::string rq = std::string(argv[2]) + " " + std::string(argv[3]);
|
||||
|
||||
requestHyprpaper(rq);
|
||||
}
|
||||
|
||||
void batchRequest(std::string arg) {
|
||||
std::string rq = "[[BATCH]]" + arg.substr(arg.find_first_of(" ") + 1);
|
||||
|
||||
request(rq);
|
||||
}
|
||||
|
||||
std::deque<std::string> splitArgs(int argc, char** argv) {
|
||||
std::deque<std::string> result;
|
||||
|
||||
for (auto i = 1 /* skip the executable */; i < argc; ++i)
|
||||
result.push_back(std::string(argv[i]));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool isNumber(const std::string& str, bool allowfloat) {
|
||||
return std::ranges::all_of(str.begin(), str.end(), [&](char c) { return isdigit(c) != 0 || c == '-' || (allowfloat && c == '.'); });
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int bflag = 0, sflag = 0, index, c;
|
||||
|
||||
@@ -124,19 +209,52 @@ int main(int argc, char** argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "monitors")) request("monitors");
|
||||
else if (!strcmp(argv[1], "clients")) request("clients");
|
||||
else if (!strcmp(argv[1], "workspaces")) request("workspaces");
|
||||
else if (!strcmp(argv[1], "activewindow")) request("activewindow");
|
||||
else if (!strcmp(argv[1], "layers")) request("layers");
|
||||
else if (!strcmp(argv[1], "version")) request("version");
|
||||
else if (!strcmp(argv[1], "kill")) request("kill");
|
||||
else if (!strcmp(argv[1], "devices")) request("devices");
|
||||
else if (!strcmp(argv[1], "reload")) request("reload");
|
||||
else if (!strcmp(argv[1], "dispatch")) dispatchRequest(argc, argv);
|
||||
else if (!strcmp(argv[1], "keyword")) keywordRequest(argc, argv);
|
||||
else if (!strcmp(argv[1], "--batch")) batchRequest(argc, argv);
|
||||
else if (!strcmp(argv[1], "--help")) printf("%s", USAGE.c_str());
|
||||
std::string fullRequest = "";
|
||||
std::string fullArgs = "";
|
||||
const auto ARGS = splitArgs(argc, argv);
|
||||
|
||||
for (auto i = 0; i < ARGS.size(); ++i) {
|
||||
if (ARGS[i][0] == '-' && !isNumber(ARGS[i], true) /* For stuff like -2 */) {
|
||||
// parse
|
||||
if (ARGS[i] == "-j" && !fullArgs.contains("j")) {
|
||||
fullArgs += "j";
|
||||
} else if (ARGS[i] == "--batch") {
|
||||
fullRequest = "--batch ";
|
||||
} else {
|
||||
printf("%s\n", USAGE.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
fullRequest += ARGS[i] + " ";
|
||||
}
|
||||
|
||||
if (fullRequest.empty()) {
|
||||
printf("%s\n", USAGE.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
fullRequest.pop_back(); // remove trailing space
|
||||
|
||||
fullRequest = fullArgs + "/" + fullRequest;
|
||||
|
||||
if (fullRequest.contains("/--batch")) batchRequest(fullRequest);
|
||||
else if (fullRequest.contains("/monitors")) request(fullRequest);
|
||||
else if (fullRequest.contains("/clients")) request(fullRequest);
|
||||
else if (fullRequest.contains("/workspaces")) request(fullRequest);
|
||||
else if (fullRequest.contains("/activewindow")) request(fullRequest);
|
||||
else if (fullRequest.contains("/layers")) request(fullRequest);
|
||||
else if (fullRequest.contains("/version")) request(fullRequest);
|
||||
else if (fullRequest.contains("/kill")) request(fullRequest);
|
||||
else if (fullRequest.contains("/splash")) request(fullRequest);
|
||||
else if (fullRequest.contains("/devices")) request(fullRequest);
|
||||
else if (fullRequest.contains("/reload")) request(fullRequest);
|
||||
else if (fullRequest.contains("/dispatch")) dispatchRequest(argc, argv);
|
||||
else if (fullRequest.contains("/keyword")) keywordRequest(argc, argv);
|
||||
else if (fullRequest.contains("/hyprpaper")) hyprpaperRequest(argc, argv);
|
||||
else if (fullRequest.contains("/--help")) printf("%s", USAGE.c_str());
|
||||
else {
|
||||
printf("%s\n", USAGE.c_str());
|
||||
return 1;
|
||||
|
15
meson.build
@@ -1,6 +1,17 @@
|
||||
project('Hyprland', 'cpp', 'c',
|
||||
version : '0.6.0beta',
|
||||
default_options : ['warning_level=3', 'cpp_std=c++20', 'default_library=static'])
|
||||
version : '0.7.0beta',
|
||||
default_options : ['warning_level=2', 'default_library=static', 'optimization=3'])
|
||||
|
||||
add_global_arguments('-std=c++23', language: 'cpp')
|
||||
|
||||
add_project_arguments(
|
||||
[
|
||||
'-Wno-unused-parameter',
|
||||
'-Wno-unused-value',
|
||||
'-Wno-missing-field-initializers',
|
||||
'-Wno-narrowing',
|
||||
],
|
||||
language: 'cpp')
|
||||
|
||||
wlroots = subproject('wlroots', default_options: ['examples=false'])
|
||||
have_xwlr = wlroots.get_variable('features').get('xwayland')
|
||||
|
@@ -20,9 +20,10 @@
|
||||
xwayland,
|
||||
enableXWayland ? true,
|
||||
version ? "git",
|
||||
debug ? false,
|
||||
}:
|
||||
stdenv.mkDerivation {
|
||||
pname = "hyprland";
|
||||
pname = "hyprland" + lib.optionalString debug "-debug";
|
||||
inherit version;
|
||||
src = ../.;
|
||||
|
||||
@@ -48,7 +49,10 @@ stdenv.mkDerivation {
|
||||
]
|
||||
++ lib.optional enableXWayland xwayland;
|
||||
|
||||
mesonBuildType = "release";
|
||||
mesonBuildType =
|
||||
if debug
|
||||
then "debug"
|
||||
else "release";
|
||||
|
||||
mesonFlags = lib.optional (!enableXWayland) "-DNO_XWAYLAND=true";
|
||||
|
||||
@@ -57,6 +61,11 @@ stdenv.mkDerivation {
|
||||
./meson-build.patch
|
||||
];
|
||||
|
||||
# Fix hardcoded paths to /usr installation
|
||||
postPatch = ''
|
||||
sed -i "s#/usr#$out#" src/render/OpenGL.cpp
|
||||
'';
|
||||
|
||||
passthru.providedSessions = ["hyprland"];
|
||||
|
||||
meta = with lib; {
|
||||
|
@@ -19,7 +19,7 @@ in {
|
||||
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
default = pkgs.hyprland or self.packages.${pkgs.system}.default;
|
||||
default = self.packages.${pkgs.system}.default;
|
||||
defaultText = literalExpression "<Hyprland flake>.packages.<system>.default";
|
||||
example = literalExpression "<Hyprland flake>.packages.<system>.default.override { }";
|
||||
description = ''
|
||||
|
@@ -30,7 +30,9 @@ public:
|
||||
|
||||
// ------------------ WLR BASICS ------------------ //
|
||||
wl_display* m_sWLDisplay;
|
||||
wl_event_loop* m_sWLEventLoop;
|
||||
wlr_backend* m_sWLRBackend;
|
||||
wlr_session* m_sWLRSession;
|
||||
wlr_renderer* m_sWLRRenderer;
|
||||
wlr_allocator* m_sWLRAllocator;
|
||||
wlr_compositor* m_sWLRCompositor;
|
||||
@@ -60,22 +62,27 @@ public:
|
||||
wlr_virtual_pointer_manager_v1* m_sWLRVirtPtrMgr;
|
||||
wlr_foreign_toplevel_manager_v1* m_sWLRToplevelMgr;
|
||||
wlr_tablet_manager_v2* m_sWLRTabletManager;
|
||||
wlr_xdg_foreign_registry* m_sWLRForeignRegistry;
|
||||
wlr_idle_inhibit_manager_v1* m_sWLRIdleInhibitMgr;
|
||||
wlr_pointer_gestures_v1* m_sWLRPointerGestures;
|
||||
// ------------------------------------------------- //
|
||||
|
||||
|
||||
const char* m_szWLDisplaySocket;
|
||||
std::string m_szInstanceSignature = "";
|
||||
std::string m_szCurrentSplash = "error";
|
||||
|
||||
std::list<SMonitor> m_lMonitors;
|
||||
std::list<CWindow> m_lWindows;
|
||||
std::list<SXDGPopup> m_lXDGPopups;
|
||||
std::list<CWorkspace> m_lWorkspaces;
|
||||
std::list<SSubsurface> m_lSubsurfaces;
|
||||
std::list<CWindow*> m_lWindowsFadingOut;
|
||||
std::list<SLayerSurface*> m_lSurfacesFadingOut;
|
||||
std::vector<std::unique_ptr<SMonitor>> m_vMonitors;
|
||||
std::vector<std::unique_ptr<CWindow>> m_vWindows;
|
||||
std::deque<std::unique_ptr<CWindow>> m_dUnmanagedX11Windows;
|
||||
std::vector<std::unique_ptr<SXDGPopup>> m_vXDGPopups;
|
||||
std::vector<std::unique_ptr<CWorkspace>> m_vWorkspaces;
|
||||
std::vector<std::unique_ptr<SSubsurface>> m_vSubsurfaces;
|
||||
std::vector<CWindow*> m_vWindowsFadingOut;
|
||||
std::vector<SLayerSurface*> m_vSurfacesFadingOut;
|
||||
|
||||
void startCompositor();
|
||||
void cleanupExit();
|
||||
void cleanup();
|
||||
|
||||
wlr_surface* m_pLastFocus = nullptr;
|
||||
CWindow* m_pLastWindow = nullptr;
|
||||
@@ -84,6 +91,7 @@ public:
|
||||
SSeat m_sSeat;
|
||||
|
||||
bool m_bReadyToProcess = false;
|
||||
bool m_bSessionActive = true;
|
||||
|
||||
// ------------------------------------------------- //
|
||||
|
||||
@@ -97,9 +105,9 @@ public:
|
||||
bool windowExists(CWindow*);
|
||||
bool windowValidMapped(CWindow*);
|
||||
CWindow* vectorToWindow(const Vector2D&);
|
||||
CWindow* vectorToWindowIdeal(const Vector2D&);
|
||||
CWindow* vectorToWindowIdeal(const Vector2D&); // used only for finding a window to focus on, basically a "findFocusableWindow"
|
||||
CWindow* vectorToWindowTiled(const Vector2D&);
|
||||
wlr_surface* vectorToLayerSurface(const Vector2D&, std::list<SLayerSurface*>*, Vector2D*);
|
||||
wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector<std::unique_ptr<SLayerSurface>>*, Vector2D*, SLayerSurface**);
|
||||
wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl);
|
||||
CWindow* windowFromCursor();
|
||||
CWindow* windowFloatingFromCursor();
|
||||
@@ -111,6 +119,7 @@ public:
|
||||
CWorkspace* getWorkspaceByName(const std::string&);
|
||||
CWorkspace* getWorkspaceByString(const std::string&);
|
||||
void sanityCheckWorkspaces();
|
||||
void updateWorkspaceWindowDecos(const int&);
|
||||
int getWindowsOnWorkspace(const int&);
|
||||
CWindow* getFirstWindowOnWorkspace(const int&);
|
||||
void fixXWaylandWindowsOnWorkspace(const int&);
|
||||
@@ -118,24 +127,34 @@ public:
|
||||
bool doesSeatAcceptInput(wlr_surface*);
|
||||
bool isWindowActive(CWindow*);
|
||||
void moveWindowToTop(CWindow*);
|
||||
void cleanupFadingOut();
|
||||
void cleanupFadingOut(const int& monid);
|
||||
CWindow* getWindowInDirection(CWindow*, char);
|
||||
void deactivateAllWLRWorkspaces(wlr_ext_workspace_handle_v1* exclude = nullptr);
|
||||
CWindow* getNextWindowOnWorkspace(CWindow*);
|
||||
CWindow* getPrevWindowOnWorkspace(CWindow*);
|
||||
int getNextAvailableNamedWorkspace();
|
||||
bool isPointOnAnyMonitor(const Vector2D&);
|
||||
CWindow* getConstraintWindow(SMouse*);
|
||||
SMonitor* getMonitorInDirection(const char&);
|
||||
void updateAllWindowsBorders();
|
||||
void updateWindowBorderColor(CWindow*);
|
||||
void updateAllWindowsAnimatedDecorationValues();
|
||||
void updateWindowAnimatedDecorationValues(CWindow*);
|
||||
void moveWindowToWorkspace(CWindow*, const std::string&);
|
||||
int getNextAvailableMonitorID();
|
||||
void moveWorkspaceToMonitor(CWorkspace*, SMonitor*);
|
||||
bool workspaceIDOutOfBounds(const int&);
|
||||
void setWindowFullscreen(CWindow*, bool, eFullscreenMode);
|
||||
void moveUnmanagedX11ToWindows(CWindow*);
|
||||
CWindow* getX11Parent(CWindow*);
|
||||
void scheduleFrameForMonitor(SMonitor*);
|
||||
void addToFadingOutSafe(SLayerSurface*);
|
||||
void addToFadingOutSafe(CWindow*);
|
||||
CWindow* getWindowByRegex(const std::string&);
|
||||
|
||||
std::string explicitConfigPath;
|
||||
|
||||
private:
|
||||
void initAllSignals();
|
||||
void setRandomSplash();
|
||||
};
|
||||
|
||||
|
||||
|
@@ -7,6 +7,8 @@ CWindow::CWindow() {
|
||||
m_vRealSize.create(AVARTYPE_VECTOR, &g_pConfigManager->getConfigValuePtr("animations:windows_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:windows")->intValue, &g_pConfigManager->getConfigValuePtr("animations:windows_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE);
|
||||
m_cRealBorderColor.create(AVARTYPE_COLOR, &g_pConfigManager->getConfigValuePtr("animations:borders_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:borders")->intValue, &g_pConfigManager->getConfigValuePtr("animations:borders_curve")->strValue, (void*)this, AVARDAMAGE_BORDER);
|
||||
m_fAlpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:fadein_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:fadein")->intValue, &g_pConfigManager->getConfigValuePtr("animations:fadein_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE);
|
||||
m_fActiveInactiveAlpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:fadein_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:fadein")->intValue, &g_pConfigManager->getConfigValuePtr("animations:fadein_curve")->strValue, (void*)this, AVARDAMAGE_ENTIRE);
|
||||
m_cRealShadowColor.create(AVARTYPE_COLOR, &g_pConfigManager->getConfigValuePtr("animations:borders_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:borders")->intValue, &g_pConfigManager->getConfigValuePtr("animations:borders_curve")->strValue, (void*)this, AVARDAMAGE_SHADOW);
|
||||
|
||||
m_dWindowDecorations.emplace_back(std::make_unique<CHyprDropShadowDecoration>(this)); // put the shadow so it's the first deco (has to be rendered first)
|
||||
}
|
||||
@@ -77,6 +79,18 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
||||
void CWindow::updateWindowDecos() {
|
||||
for (auto& wd : m_dWindowDecorations)
|
||||
wd->updateWindow(this);
|
||||
|
||||
for (auto& wd : m_vDecosToRemove) {
|
||||
for (auto it = m_dWindowDecorations.begin(); it != m_dWindowDecorations.end(); it++) {
|
||||
if (it->get() == wd) {
|
||||
it = m_dWindowDecorations.erase(it);
|
||||
if (it == m_dWindowDecorations.end())
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_vDecosToRemove.clear();
|
||||
}
|
||||
|
||||
pid_t CWindow::getPID() {
|
||||
@@ -90,3 +104,12 @@ pid_t CWindow::getPID() {
|
||||
|
||||
return PID;
|
||||
}
|
||||
|
||||
IHyprWindowDecoration* CWindow::getDecorationByType(eDecorationType type) {
|
||||
for (auto& wd : m_dWindowDecorations) {
|
||||
if (wd->getDecorationType() == type)
|
||||
return wd.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
@@ -28,8 +28,13 @@ public:
|
||||
DYNLISTENER(unmapWindow);
|
||||
DYNLISTENER(destroyWindow);
|
||||
DYNLISTENER(setTitleWindow);
|
||||
DYNLISTENER(setGeometryX11U);
|
||||
DYNLISTENER(fullscreenWindow);
|
||||
DYNLISTENER(newPopupXDG);
|
||||
DYNLISTENER(requestMove);
|
||||
DYNLISTENER(requestMinimize);
|
||||
DYNLISTENER(requestMaximize);
|
||||
DYNLISTENER(requestResize);
|
||||
// DYNLISTENER(newSubsurfaceWindow);
|
||||
|
||||
union {
|
||||
@@ -67,6 +72,7 @@ public:
|
||||
// XWayland stuff
|
||||
bool m_bIsX11 = false;
|
||||
bool m_bMappedX11 = false;
|
||||
CWindow* m_pX11Parent = nullptr;
|
||||
uint64_t m_iX11Type = 0;
|
||||
bool m_bIsModal = false;
|
||||
bool m_bX11DoesntWantBorders = false;
|
||||
@@ -98,11 +104,18 @@ public:
|
||||
|
||||
// Window decorations
|
||||
std::deque<std::unique_ptr<IHyprWindowDecoration>> m_dWindowDecorations;
|
||||
std::vector<IHyprWindowDecoration*> m_vDecosToRemove;
|
||||
|
||||
// Special render data, rules, etc
|
||||
SWindowSpecialRenderData m_sSpecialRenderData;
|
||||
SWindowAdditionalConfigData m_sAdditionalConfigData;
|
||||
|
||||
// for alpha
|
||||
CAnimatedVariable m_fActiveInactiveAlpha;
|
||||
|
||||
// animated shadow color
|
||||
CAnimatedVariable m_cRealShadowColor;
|
||||
|
||||
// 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 && m_bFadingOut == rhs.m_bFadingOut;
|
||||
@@ -113,5 +126,6 @@ public:
|
||||
wlr_box getWindowIdealBoundingBoxIgnoreReserved();
|
||||
void updateWindowDecos();
|
||||
pid_t getPID();
|
||||
IHyprWindowDecoration* getDecorationByType(eDecorationType);
|
||||
|
||||
};
|
||||
|
@@ -12,9 +12,19 @@
|
||||
|
||||
CConfigManager::CConfigManager() {
|
||||
setDefaultVars();
|
||||
static const char* const ENVHOME = getenv("HOME");
|
||||
const std::string CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf");
|
||||
|
||||
std::string CONFIGPATH;
|
||||
if (g_pCompositor->explicitConfigPath == "") {
|
||||
static const char* const ENVHOME = getenv("HOME");
|
||||
CONFIGPATH = ENVHOME + (ISDEBUG ? (std::string) "/.config/hypr/hyprlandd.conf" : (std::string) "/.config/hypr/hyprland.conf");
|
||||
} else {
|
||||
CONFIGPATH = g_pCompositor->explicitConfigPath;
|
||||
}
|
||||
|
||||
configPaths.emplace_back(CONFIGPATH);
|
||||
|
||||
Debug::disableLogs = &configValues["debug:disable_logs"].intValue;
|
||||
Debug::disableTime = &configValues["debug:disable_time"].intValue;
|
||||
}
|
||||
|
||||
void CConfigManager::setDefaultVars() {
|
||||
@@ -35,9 +45,18 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["general:col.inactive_border"].intValue = 0xff444444;
|
||||
configValues["general:cursor_inactive_timeout"].intValue = 0;
|
||||
|
||||
configValues["general:layout"].strValue = "dwindle";
|
||||
|
||||
configValues["misc:disable_hyprland_logo"].intValue = 0;
|
||||
configValues["misc:disable_splash_rendering"].intValue = 0;
|
||||
configValues["misc:no_vfr"].intValue = 1;
|
||||
|
||||
configValues["debug:int"].intValue = 0;
|
||||
configValues["debug:log_damage"].intValue = 0;
|
||||
configValues["debug:overlay"].intValue = 0;
|
||||
configValues["debug:damage_blink"].intValue = 0;
|
||||
configValues["debug:disable_logs"].intValue = 0;
|
||||
configValues["debug:disable_time"].intValue = 1;
|
||||
|
||||
configValues["decoration:rounding"].intValue = 1;
|
||||
configValues["decoration:blur"].intValue = 1;
|
||||
@@ -48,13 +67,14 @@ void CConfigManager::setDefaultVars() {
|
||||
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 = 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"].strValue = "0 0";
|
||||
configValues["decoration:col.shadow"].intValue = 0xee1a1a1a;
|
||||
configValues["decoration:col.shadow_inactive"].intValue = INT_MAX;
|
||||
|
||||
configValues["dwindle:pseudotile"].intValue = 0;
|
||||
configValues["dwindle:col.group_border"].intValue = 0x66777700;
|
||||
@@ -62,6 +82,11 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["dwindle:force_split"].intValue = 0;
|
||||
configValues["dwindle:preserve_split"].intValue = 0;
|
||||
configValues["dwindle:special_scale_factor"].floatValue = 0.8f;
|
||||
configValues["dwindle:split_width_multiplier"].floatValue = 1.0f;
|
||||
|
||||
configValues["master:special_scale_factor"].floatValue = 0.8f;
|
||||
configValues["master:new_is_master"].intValue = 1;
|
||||
configValues["master:new_on_top"].intValue = 0;
|
||||
|
||||
configValues["animations:enabled"].intValue = 1;
|
||||
configValues["animations:speed"].floatValue = 7.f;
|
||||
@@ -83,6 +108,7 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["animations:workspaces_speed"].floatValue = 0.f;
|
||||
configValues["animations:workspaces"].intValue = 1;
|
||||
|
||||
configValues["input:sensitivity"].floatValue = 0.f;
|
||||
configValues["input:kb_layout"].strValue = "us";
|
||||
configValues["input:kb_variant"].strValue = STRVAL_EMPTY;
|
||||
configValues["input:kb_options"].strValue = STRVAL_EMPTY;
|
||||
@@ -98,12 +124,42 @@ void CConfigManager::setDefaultVars() {
|
||||
configValues["input:touchpad:clickfinger_behavior"].intValue = 0;
|
||||
configValues["input:touchpad:middle_button_emulation"].intValue = 0;
|
||||
configValues["input:touchpad:tap-to-click"].intValue = 1;
|
||||
configValues["input:touchpad:drag_lock"].intValue = 0;
|
||||
|
||||
configValues["binds:pass_mouse_when_bound"].intValue = 1;
|
||||
|
||||
configValues["gestures:workspace_swipe"].intValue = 0;
|
||||
configValues["gestures:workspace_swipe_fingers"].intValue = 3;
|
||||
configValues["gestures:workspace_swipe_distance"].intValue = 300;
|
||||
configValues["gestures:workspace_swipe_invert"].intValue = 1;
|
||||
configValues["gestures:workspace_swipe_min_speed_to_force"].intValue = 30;
|
||||
configValues["gestures:workspace_swipe_cancel_ratio"].floatValue = 0.5f;
|
||||
|
||||
configValues["input:follow_mouse"].intValue = 1;
|
||||
|
||||
configValues["autogenerated"].intValue = 0;
|
||||
}
|
||||
|
||||
void CConfigManager::setDeviceDefaultVars(const std::string& dev) {
|
||||
auto& cfgValues = deviceConfigs[dev];
|
||||
|
||||
cfgValues["sensitivity"].floatValue = 0.f;
|
||||
cfgValues["kb_layout"].strValue = "us";
|
||||
cfgValues["kb_variant"].strValue = STRVAL_EMPTY;
|
||||
cfgValues["kb_options"].strValue = STRVAL_EMPTY;
|
||||
cfgValues["kb_rules"].strValue = STRVAL_EMPTY;
|
||||
cfgValues["kb_model"].strValue = STRVAL_EMPTY;
|
||||
cfgValues["repeat_rate"].intValue = 25;
|
||||
cfgValues["repeat_delay"].intValue = 600;
|
||||
cfgValues["natural_scroll"].intValue = 0;
|
||||
cfgValues["numlock_by_default"].intValue = 0;
|
||||
cfgValues["disable_while_typing"].intValue = 1;
|
||||
cfgValues["clickfinger_behavior"].intValue = 0;
|
||||
cfgValues["middle_button_emulation"].intValue = 0;
|
||||
cfgValues["tap-to-click"].intValue = 1;
|
||||
cfgValues["drag_lock"].intValue = 0;
|
||||
}
|
||||
|
||||
void CConfigManager::init() {
|
||||
|
||||
loadConfigLoadVars();
|
||||
@@ -125,41 +181,69 @@ void CConfigManager::init() {
|
||||
|
||||
void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::string& VALUE) {
|
||||
if (configValues.find(COMMAND) == configValues.end()) {
|
||||
if (COMMAND[0] == '$') {
|
||||
// register a dynamic var
|
||||
Debug::log(LOG, "Registered dynamic var \"%s\" -> %s", COMMAND.c_str(), VALUE.c_str());
|
||||
configDynamicVars[COMMAND.substr(1)] = VALUE;
|
||||
} else {
|
||||
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">: No such field.";
|
||||
}
|
||||
if (COMMAND.find("device:") != 0 /* devices parsed later */) {
|
||||
if (COMMAND[0] == '$') {
|
||||
// register a dynamic var
|
||||
Debug::log(LOG, "Registered dynamic var \"%s\" -> %s", COMMAND.c_str(), VALUE.c_str());
|
||||
configDynamicVars[COMMAND.substr(1)] = VALUE;
|
||||
} else {
|
||||
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">: No such field.";
|
||||
}
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SConfigValue* CONFIGENTRY = nullptr;
|
||||
|
||||
auto& CONFIGENTRY = configValues.at(COMMAND);
|
||||
if (CONFIGENTRY.intValue != -1) {
|
||||
if (COMMAND.find("device:") == 0) {
|
||||
const auto DEVICE = COMMAND.substr(7).substr(0, COMMAND.find_last_of(':') - 7);
|
||||
const auto CONFIGVAR = COMMAND.substr(COMMAND.find_last_of(':') + 1);
|
||||
|
||||
if (!deviceConfigExists(DEVICE))
|
||||
setDeviceDefaultVars(DEVICE);
|
||||
|
||||
auto it = deviceConfigs.find(DEVICE);
|
||||
|
||||
if (it->second.find(CONFIGVAR) == it->second.end()) {
|
||||
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">: No such field.";
|
||||
return;
|
||||
}
|
||||
|
||||
CONFIGENTRY = &it->second.at(CONFIGVAR);
|
||||
} else {
|
||||
CONFIGENTRY = &configValues.at(COMMAND);
|
||||
}
|
||||
|
||||
CONFIGENTRY->set = true;
|
||||
|
||||
if (CONFIGENTRY->intValue != -1) {
|
||||
try {
|
||||
if (VALUE.find("0x") == 0) {
|
||||
// Values with 0x are hex
|
||||
const auto VALUEWITHOUTHEX = VALUE.substr(2);
|
||||
CONFIGENTRY.intValue = stol(VALUEWITHOUTHEX, nullptr, 16);
|
||||
} else
|
||||
CONFIGENTRY.intValue = stol(VALUE);
|
||||
CONFIGENTRY->intValue = stol(VALUEWITHOUTHEX, nullptr, 16);
|
||||
} else if (VALUE.find("true") == 0 || VALUE.find("on") == 0 || VALUE.find("yes") == 0) {
|
||||
CONFIGENTRY->intValue = 1;
|
||||
} else if (VALUE.find("false") == 0 || VALUE.find("off") == 0 || VALUE.find("no") == 0) {
|
||||
CONFIGENTRY->intValue = 0;
|
||||
}
|
||||
else
|
||||
CONFIGENTRY->intValue = stol(VALUE);
|
||||
} catch (...) {
|
||||
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
|
||||
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
|
||||
}
|
||||
} else if (CONFIGENTRY.floatValue != -1) {
|
||||
} else if (CONFIGENTRY->floatValue != -1) {
|
||||
try {
|
||||
CONFIGENTRY.floatValue = stof(VALUE);
|
||||
CONFIGENTRY->floatValue = stof(VALUE);
|
||||
} catch (...) {
|
||||
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
|
||||
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
|
||||
}
|
||||
} else if (CONFIGENTRY.strValue != "") {
|
||||
} else if (CONFIGENTRY->strValue != "") {
|
||||
try {
|
||||
CONFIGENTRY.strValue = VALUE;
|
||||
CONFIGENTRY->strValue = VALUE;
|
||||
} catch (...) {
|
||||
Debug::log(WARN, "Error reading value of %s", COMMAND.c_str());
|
||||
parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">.";
|
||||
@@ -307,7 +391,7 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string
|
||||
newrule.resolution.x = stoi(curitem.substr(0, curitem.find_first_of('x')));
|
||||
newrule.resolution.y = stoi(curitem.substr(curitem.find_first_of('x') + 1, curitem.find_first_of('@')));
|
||||
|
||||
if (curitem.find_first_of('@') != std::string::npos)
|
||||
if (curitem.contains("@"))
|
||||
newrule.refreshRate = stof(curitem.substr(curitem.find_first_of('@') + 1));
|
||||
|
||||
nextItem();
|
||||
@@ -424,9 +508,33 @@ void CConfigManager::handleAnimation(const std::string& command, const std::stri
|
||||
configSetValueSafe("animations:" + ANIMNAME + "_style", curitem);
|
||||
}
|
||||
|
||||
void CConfigManager::handleBind(const std::string& command, const std::string& value, bool locked) {
|
||||
void CConfigManager::handleBind(const std::string& command, const std::string& value) {
|
||||
// example:
|
||||
// bind=SUPER,G,exec,dmenu_run <args>
|
||||
// bind[fl]=SUPER,G,exec,dmenu_run <args>
|
||||
|
||||
// flags
|
||||
bool locked = false;
|
||||
bool release = false;
|
||||
bool repeat = false;
|
||||
const auto ARGS = command.substr(4);
|
||||
|
||||
for (auto& arg : ARGS) {
|
||||
if (arg == 'l') {
|
||||
locked = true;
|
||||
} else if (arg == 'r') {
|
||||
release = true;
|
||||
} else if (arg == 'e') {
|
||||
repeat = true;
|
||||
} else {
|
||||
parseError = "bind: invalid flag";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (release && repeat) {
|
||||
parseError = "flags r and e are mutually exclusive";
|
||||
return;
|
||||
}
|
||||
|
||||
auto valueCopy = value;
|
||||
|
||||
@@ -456,8 +564,13 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v
|
||||
return;
|
||||
}
|
||||
|
||||
if (KEY != "")
|
||||
g_pKeybindManager->addKeybind(SKeybind{KEY, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap});
|
||||
if (KEY != "") {
|
||||
if (isNumber(KEY) && std::stoi(KEY) > 9)
|
||||
g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat});
|
||||
else
|
||||
g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CConfigManager::handleUnbind(const std::string& command, const std::string& value) {
|
||||
@@ -490,6 +603,7 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str
|
||||
&& RULE.find("monitor") != 0
|
||||
&& RULE != "nofocus"
|
||||
&& RULE != "noblur"
|
||||
&& RULE != "center"
|
||||
&& RULE != "fullscreen"
|
||||
&& RULE.find("animation") != 0
|
||||
&& RULE.find("rounding") != 0
|
||||
@@ -503,6 +617,16 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str
|
||||
|
||||
}
|
||||
|
||||
void CConfigManager::handleBlurLS(const std::string& command, const std::string& value) {
|
||||
if (value.find("remove,") == 0) {
|
||||
const auto TOREMOVE = value.substr(7);
|
||||
m_dBlurLSNamespaces.erase(std::remove(m_dBlurLSNamespaces.begin(), m_dBlurLSNamespaces.end(), TOREMOVE));
|
||||
return;
|
||||
}
|
||||
|
||||
m_dBlurLSNamespaces.emplace_back(value);
|
||||
}
|
||||
|
||||
void CConfigManager::handleDefaultWorkspace(const std::string& command, const std::string& value) {
|
||||
|
||||
const auto DISPLAY = value.substr(0, value.find_first_of(','));
|
||||
@@ -528,6 +652,23 @@ void CConfigManager::handleSource(const std::string& command, const std::string&
|
||||
|
||||
auto value = rawpath;
|
||||
|
||||
if (value.length() < 2) {
|
||||
Debug::log(ERR, "source= path garbage");
|
||||
parseError = "source path " + value + " bogus!";
|
||||
return;
|
||||
}
|
||||
|
||||
if (value[0] == '.') {
|
||||
auto currentDir = configCurrentPath.substr(0, configCurrentPath.find_last_of('/'));
|
||||
|
||||
if (value[1] == '.') {
|
||||
auto parentDir = currentDir.substr(0, currentDir.find_last_of('/'));
|
||||
value.replace(0, 2, parentDir);
|
||||
} else {
|
||||
value.replace(0, 1, currentDir);
|
||||
}
|
||||
}
|
||||
|
||||
if (value[0] == '~') {
|
||||
value.replace(0, 1, std::string(ENVHOME));
|
||||
}
|
||||
@@ -595,8 +736,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
|
||||
}
|
||||
}
|
||||
else if (COMMAND == "monitor") handleMonitor(COMMAND, VALUE);
|
||||
else if (COMMAND == "bind") handleBind(COMMAND, VALUE);
|
||||
else if (COMMAND == "bindl") handleBind(COMMAND, VALUE, true);
|
||||
else if (COMMAND.find("bind") == 0) handleBind(COMMAND, VALUE);
|
||||
else if (COMMAND == "unbind") handleUnbind(COMMAND, VALUE);
|
||||
else if (COMMAND == "workspace") handleDefaultWorkspace(COMMAND, VALUE);
|
||||
else if (COMMAND == "windowrule") handleWindowRule(COMMAND, VALUE);
|
||||
@@ -604,6 +744,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
|
||||
else if (COMMAND == "animation") handleAnimation(COMMAND, VALUE);
|
||||
else if (COMMAND == "source") handleSource(COMMAND, VALUE);
|
||||
else if (COMMAND == "submap") handleSubmap(COMMAND, VALUE);
|
||||
else if (COMMAND == "blurls") handleBlurLS(COMMAND, VALUE);
|
||||
else
|
||||
configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE);
|
||||
|
||||
@@ -612,11 +753,11 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
|
||||
parseError = "";
|
||||
|
||||
// invalidate layouts jic
|
||||
for (auto& m : g_pCompositor->m_lMonitors)
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID);
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||
|
||||
// Update window border colors
|
||||
g_pCompositor->updateAllWindowsBorders();
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
return retval;
|
||||
}
|
||||
@@ -656,7 +797,7 @@ void CConfigManager::parseLine(std::string& line) {
|
||||
line = line.substr(1);
|
||||
}
|
||||
|
||||
if (line.find(" {") != std::string::npos) {
|
||||
if (line.contains(" {")) {
|
||||
auto cat = line.substr(0, line.find(" {"));
|
||||
transform(cat.begin(), cat.end(), cat.begin(), ::tolower);
|
||||
if (currentCategory.length() != 0) {
|
||||
@@ -670,7 +811,7 @@ void CConfigManager::parseLine(std::string& line) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (line.find("}") != std::string::npos && currentCategory != "") {
|
||||
if (line.contains("}") && currentCategory != "") {
|
||||
currentCategory = "";
|
||||
return;
|
||||
}
|
||||
@@ -705,32 +846,43 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
g_pAnimationManager->removeAllBeziers();
|
||||
m_mAdditionalReservedAreas.clear();
|
||||
configDynamicVars.clear();
|
||||
deviceConfigs.clear();
|
||||
m_dBlurLSNamespaces.clear();
|
||||
|
||||
// paths
|
||||
configPaths.clear();
|
||||
|
||||
std::string CONFIGPATH;
|
||||
|
||||
static const char* const ENVHOME = getenv("HOME");
|
||||
const std::string CONFIGPARENTPATH = ENVHOME + (std::string) "/.config/hypr/";
|
||||
const std::string CONFIGPATH = CONFIGPARENTPATH + (ISDEBUG ? "hyprlandd.conf" : "hyprland.conf");
|
||||
|
||||
if (g_pCompositor->explicitConfigPath == "") {
|
||||
CONFIGPATH = CONFIGPARENTPATH + (ISDEBUG ? "hyprlandd.conf" : "hyprland.conf");
|
||||
} else {
|
||||
CONFIGPATH = g_pCompositor->explicitConfigPath;
|
||||
}
|
||||
|
||||
configPaths.push_back(CONFIGPATH);
|
||||
|
||||
|
||||
std::ifstream ifs;
|
||||
ifs.open(CONFIGPATH);
|
||||
|
||||
if (!ifs.good()) {
|
||||
Debug::log(WARN, "Config reading error. (No file? Attempting to generate, backing up old one if exists)");
|
||||
try {
|
||||
std::filesystem::rename(CONFIGPATH, CONFIGPATH + ".backup");
|
||||
} catch(...) { /* Probably doesn't exist */}
|
||||
if(g_pCompositor->explicitConfigPath == "") {
|
||||
Debug::log(WARN, "Config reading error. (No file? Attempting to generate, backing up old one if exists)");
|
||||
try {
|
||||
std::filesystem::rename(CONFIGPATH, CONFIGPATH + ".backup");
|
||||
} catch(...) { /* Probably doesn't exist */}
|
||||
|
||||
try {
|
||||
if (!std::filesystem::is_directory(CONFIGPARENTPATH))
|
||||
std::filesystem::create_directories(CONFIGPARENTPATH);
|
||||
}
|
||||
catch (...) {
|
||||
parseError = "Broken config file! (Could not create directory)";
|
||||
return;
|
||||
try {
|
||||
if (!std::filesystem::is_directory(CONFIGPARENTPATH))
|
||||
std::filesystem::create_directories(CONFIGPARENTPATH);
|
||||
}
|
||||
catch (...) {
|
||||
parseError = "Broken config file! (Could not create directory)";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::ofstream ofs;
|
||||
@@ -773,12 +925,14 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
ifs.close();
|
||||
}
|
||||
|
||||
for (auto& m : g_pCompositor->m_lMonitors)
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID);
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||
|
||||
// Update the keyboard layout to the cfg'd one if this is not the first launch
|
||||
if (!isFirstLaunch)
|
||||
if (!isFirstLaunch) {
|
||||
g_pInputManager->setKeyboardLayout();
|
||||
g_pInputManager->setMouseConfigs();
|
||||
}
|
||||
|
||||
// Calculate the internal vars
|
||||
configValues["general:main_mod_internal"].intValue = g_pKeybindManager->stringToModMask(configValues["general:main_mod"].strValue);
|
||||
@@ -806,11 +960,14 @@ void CConfigManager::loadConfigLoadVars() {
|
||||
}
|
||||
|
||||
// Update window border colors
|
||||
g_pCompositor->updateAllWindowsBorders();
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
// update layout
|
||||
g_pLayoutManager->switchToLayout(configValues["general:layout"].strValue);
|
||||
|
||||
// Force the compositor to fully re-render all monitors
|
||||
for (auto& m : g_pCompositor->m_lMonitors)
|
||||
m.forceFullFrames = 2;
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
m->forceFullFrames = 2;
|
||||
}
|
||||
|
||||
void CConfigManager::tick() {
|
||||
@@ -848,7 +1005,7 @@ void CConfigManager::tick() {
|
||||
}
|
||||
|
||||
std::mutex configmtx;
|
||||
SConfigValue CConfigManager::getConfigValueSafe(std::string val) {
|
||||
SConfigValue CConfigManager::getConfigValueSafe(const std::string& val) {
|
||||
std::lock_guard<std::mutex> lg(configmtx);
|
||||
|
||||
SConfigValue copy = configValues[val];
|
||||
@@ -856,15 +1013,38 @@ SConfigValue CConfigManager::getConfigValueSafe(std::string val) {
|
||||
return copy;
|
||||
}
|
||||
|
||||
int CConfigManager::getInt(std::string v) {
|
||||
SConfigValue CConfigManager::getConfigValueSafeDevice(const std::string& dev, const std::string& val) {
|
||||
std::lock_guard<std::mutex> lg(configmtx);
|
||||
|
||||
const auto it = deviceConfigs.find(dev);
|
||||
|
||||
if (it == deviceConfigs.end()) {
|
||||
return SConfigValue();
|
||||
}
|
||||
|
||||
SConfigValue copy = it->second[val];
|
||||
|
||||
// fallback if not set explicitly
|
||||
if (!copy.set) {
|
||||
for (auto& cv : configValues) {
|
||||
if (cv.first.find(val) == cv.first.length() - val.length()) {
|
||||
copy = cv.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
int CConfigManager::getInt(const std::string& v) {
|
||||
return getConfigValueSafe(v).intValue;
|
||||
}
|
||||
|
||||
float CConfigManager::getFloat(std::string v) {
|
||||
float CConfigManager::getFloat(const std::string& v) {
|
||||
return getConfigValueSafe(v).floatValue;
|
||||
}
|
||||
|
||||
std::string CConfigManager::getString(std::string v) {
|
||||
std::string CConfigManager::getString(const std::string& v) {
|
||||
const auto VAL = getConfigValueSafe(v).strValue;
|
||||
|
||||
if (VAL == STRVAL_EMPTY)
|
||||
@@ -873,6 +1053,23 @@ std::string CConfigManager::getString(std::string v) {
|
||||
return VAL;
|
||||
}
|
||||
|
||||
int CConfigManager::getDeviceInt(const std::string& dev, const std::string& v) {
|
||||
return getConfigValueSafeDevice(dev, v).intValue;
|
||||
}
|
||||
|
||||
float CConfigManager::getDeviceFloat(const std::string& dev, const std::string& v) {
|
||||
return getConfigValueSafeDevice(dev, v).floatValue;
|
||||
}
|
||||
|
||||
std::string CConfigManager::getDeviceString(const std::string& dev, const std::string& v) {
|
||||
const auto VAL = getConfigValueSafeDevice(dev, v).strValue;
|
||||
|
||||
if (VAL == STRVAL_EMPTY)
|
||||
return "";
|
||||
|
||||
return VAL;
|
||||
}
|
||||
|
||||
void CConfigManager::setInt(std::string v, int val) {
|
||||
configValues[v].intValue = val;
|
||||
}
|
||||
@@ -966,17 +1163,51 @@ void CConfigManager::dispatchExecOnce() {
|
||||
}
|
||||
|
||||
firstExecRequests.clear(); // free some kb of memory :P
|
||||
|
||||
// set input, fixes some certain issues
|
||||
g_pInputManager->setKeyboardLayout();
|
||||
g_pInputManager->setMouseConfigs();
|
||||
|
||||
// set ws names again
|
||||
for (auto& ws : g_pCompositor->m_vWorkspaces) {
|
||||
wlr_ext_workspace_handle_v1_set_name(ws->m_pWlrHandle, ws->m_szName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void CConfigManager::performMonitorReload() {
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
auto rule = getMonitorRuleFor(m.szName);
|
||||
g_pHyprRenderer->applyMonitorRule(&m, &rule);
|
||||
|
||||
bool overAgain = false;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
auto rule = getMonitorRuleFor(m->szName);
|
||||
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) {
|
||||
overAgain = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (overAgain)
|
||||
performMonitorReload();
|
||||
|
||||
m_bWantsMonitorReload = false;
|
||||
}
|
||||
|
||||
SConfigValue* CConfigManager::getConfigValuePtr(std::string val) {
|
||||
return &configValues[val];
|
||||
}
|
||||
|
||||
bool CConfigManager::deviceConfigExists(const std::string& dev) {
|
||||
const auto it = deviceConfigs.find(dev);
|
||||
|
||||
return it != deviceConfigs.end();
|
||||
}
|
||||
|
||||
bool CConfigManager::shouldBlurLS(const std::string& ns) {
|
||||
for (auto& bls : m_dBlurLSNamespaces) {
|
||||
if (bls == ns) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@@ -20,6 +20,8 @@ struct SConfigValue {
|
||||
int64_t intValue = -1;
|
||||
float floatValue = -1;
|
||||
std::string strValue = "";
|
||||
|
||||
bool set = false; // used for device configs
|
||||
};
|
||||
|
||||
struct SMonitorRule {
|
||||
@@ -52,13 +54,19 @@ public:
|
||||
void tick();
|
||||
void init();
|
||||
|
||||
int getInt(std::string);
|
||||
float getFloat(std::string);
|
||||
std::string getString(std::string);
|
||||
int getInt(const std::string&);
|
||||
float getFloat(const std::string&);
|
||||
std::string getString(const std::string&);
|
||||
void setFloat(std::string, float);
|
||||
void setInt(std::string, int);
|
||||
void setString(std::string, std::string);
|
||||
|
||||
int getDeviceInt(const std::string&, const std::string&);
|
||||
float getDeviceFloat(const std::string&, const std::string&);
|
||||
std::string getDeviceString(const std::string&, const std::string&);
|
||||
bool deviceConfigExists(const std::string&);
|
||||
bool shouldBlurLS(const std::string&);
|
||||
|
||||
SConfigValue* getConfigValuePtr(std::string);
|
||||
|
||||
SMonitorRule getMonitorRuleFor(std::string);
|
||||
@@ -81,6 +89,7 @@ private:
|
||||
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
|
||||
std::unordered_map<std::string, std::string> configDynamicVars; // stores dynamic vars declared by the user
|
||||
std::unordered_map<std::string, SConfigValue> configValues;
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, SConfigValue>> deviceConfigs; // stores device configs
|
||||
|
||||
std::string configCurrentPath;
|
||||
|
||||
@@ -94,21 +103,25 @@ private:
|
||||
|
||||
std::deque<SMonitorRule> m_dMonitorRules;
|
||||
std::deque<SWindowRule> m_dWindowRules;
|
||||
std::deque<std::string> m_dBlurLSNamespaces;
|
||||
|
||||
bool firstExecDispatched = false;
|
||||
std::deque<std::string> firstExecRequests;
|
||||
|
||||
// internal methods
|
||||
void setDefaultVars();
|
||||
void setDeviceDefaultVars(const std::string&);
|
||||
|
||||
void applyUserDefinedVars(std::string&, const size_t);
|
||||
void loadConfigLoadVars();
|
||||
SConfigValue getConfigValueSafe(std::string);
|
||||
SConfigValue getConfigValueSafe(const std::string&);
|
||||
SConfigValue getConfigValueSafeDevice(const std::string&, const std::string&);
|
||||
void parseLine(std::string&);
|
||||
void configSetValueSafe(const std::string&, const std::string&);
|
||||
void handleDeviceConfig(const std::string&, const std::string&);
|
||||
void handleRawExec(const std::string&, const std::string&);
|
||||
void handleMonitor(const std::string&, const std::string&);
|
||||
void handleBind(const std::string&, const std::string&, bool locked = false);
|
||||
void handleBind(const std::string&, const std::string&);
|
||||
void handleUnbind(const std::string&, const std::string&);
|
||||
void handleWindowRule(const std::string&, const std::string&);
|
||||
void handleDefaultWorkspace(const std::string&, const std::string&);
|
||||
@@ -116,6 +129,7 @@ private:
|
||||
void handleAnimation(const std::string&, const std::string&);
|
||||
void handleSource(const std::string&, const std::string&);
|
||||
void handleSubmap(const std::string&, const std::string&);
|
||||
void handleBlurLS(const std::string&, const std::string&);
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CConfigManager> g_pConfigManager;
|
@@ -9,6 +9,12 @@ PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT,
|
||||
OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
|
||||
########################################################################################
|
||||
|
||||
|
||||
#
|
||||
# Please note not all available settings / options are set here.
|
||||
# For a full list, see the wiki (basic and advanced configuring)
|
||||
#
|
||||
|
||||
autogenerated=1 # remove this line to get rid of the warning on top.
|
||||
|
||||
monitor=,1920x1080@60,0x0,1
|
||||
@@ -21,6 +27,10 @@ input {
|
||||
kb_rules=
|
||||
|
||||
follow_mouse=1
|
||||
|
||||
touchpad {
|
||||
natural_scroll=no
|
||||
}
|
||||
}
|
||||
|
||||
general {
|
||||
@@ -105,4 +115,7 @@ bind=ALT,7,movetoworkspace,7
|
||||
bind=ALT,8,movetoworkspace,8
|
||||
bind=ALT,9,movetoworkspace,9
|
||||
bind=ALT,0,movetoworkspace,10
|
||||
|
||||
bind=SUPER,mouse_down,workspace,e+1
|
||||
bind=SUPER,mouse_up,workspace,e-1
|
||||
)#";
|
@@ -13,95 +13,394 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
std::string monitorsRequest() {
|
||||
std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string result = "";
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tactive workspace: %i (%s)\n\treserved: %i %i %i %i\n\n",
|
||||
m.szName.c_str(), m.ID, (int)m.vecSize.x, (int)m.vecSize.y, m.refreshRate, (int)m.vecPosition.x, (int)m.vecPosition.y, m.activeWorkspace, g_pCompositor->getWorkspaceByID(m.activeWorkspace)->m_szName.c_str(), (int)m.vecReservedTopLeft.x, (int)m.vecReservedTopLeft.y, (int)m.vecReservedBottomRight.x, (int)m.vecReservedBottomRight.y);
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
result += "[";
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
result += getFormat(
|
||||
R"#({
|
||||
"id": %i,
|
||||
"name": "%s",
|
||||
"width": %i,
|
||||
"height": %i,
|
||||
"refreshRate": %f,
|
||||
"x": %i,
|
||||
"y": %i,
|
||||
"activeWorkspace": {
|
||||
"id": %i,
|
||||
"name": "%s"
|
||||
},
|
||||
"reserved": [%i, %i, %i, %i],
|
||||
"scale": %.2f,
|
||||
"transform": %i,
|
||||
"active": "%s"
|
||||
},)#",
|
||||
m->ID,
|
||||
escapeJSONStrings(m->szName).c_str(),
|
||||
(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).c_str(),
|
||||
(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")
|
||||
);
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
|
||||
result += "]";
|
||||
} else {
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
result += getFormat("Monitor %s (ID %i):\n\t%ix%i@%f at %ix%i\n\tactive workspace: %i (%s)\n\treserved: %i %i %i %i\n\tscale: %.2f\n\ttransform: %i\n\tactive: %s\n\n",
|
||||
m->szName.c_str(), m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName.c_str(), (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"));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string clientsRequest() {
|
||||
std::string clientsRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string result = "";
|
||||
for (auto& w : g_pCompositor->m_lWindows) {
|
||||
if (w.m_bIsMapped) {
|
||||
result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\n",
|
||||
&w, w.m_szTitle.c_str(), (int)w.m_vRealPosition.vec().x, (int)w.m_vRealPosition.vec().y, (int)w.m_vRealSize.vec().x, (int)w.m_vRealSize.vec().y, w.m_iWorkspaceID, (w.m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w.m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w.m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w.m_iWorkspaceID)).c_str()), (int)w.m_bIsFloating, w.m_iMonitorID, g_pXWaylandManager->getAppIDClass(&w).c_str(), g_pXWaylandManager->getTitle(&w).c_str(), w.getPID());
|
||||
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
result += "[";
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_bIsMapped) {
|
||||
result += getFormat(
|
||||
R"#({
|
||||
"address": "0x%x",
|
||||
"at": [%i, %i],
|
||||
"size": [%i, %i],
|
||||
"workspace": {
|
||||
"id": %i,
|
||||
"name": "%s"
|
||||
},
|
||||
"floating": %i,
|
||||
"monitor": %i,
|
||||
"class": "%s",
|
||||
"title": "%s",
|
||||
"pid": %i,
|
||||
"xwayland": %i
|
||||
},)#",
|
||||
w.get(),
|
||||
(int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y,
|
||||
(int)w->m_vRealSize.vec().x, (int)w->m_vRealSize.vec().y,
|
||||
w->m_iWorkspaceID, escapeJSONStrings(w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID))).c_str(),
|
||||
(int)w->m_bIsFloating,
|
||||
w->m_iMonitorID,
|
||||
escapeJSONStrings(g_pXWaylandManager->getAppIDClass(w.get())).c_str(),
|
||||
escapeJSONStrings(g_pXWaylandManager->getTitle(w.get())).c_str(),
|
||||
w->getPID(),
|
||||
(int)w->m_bIsX11
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
|
||||
result += "]";
|
||||
} else {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_bIsMapped) {
|
||||
result += getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\txwayland: %i\n\n",
|
||||
w.get(), w->m_szTitle.c_str(), (int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y, (int)w->m_vRealSize.vec().x, (int)w->m_vRealSize.vec().y, w->m_iWorkspaceID, (w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()), (int)w->m_bIsFloating, w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w.get()).c_str(), g_pXWaylandManager->getTitle(w.get()).c_str(), w->getPID(), (int)w->m_bIsX11);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string workspacesRequest() {
|
||||
std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string result = "";
|
||||
for (auto& w : g_pCompositor->m_lWorkspaces) {
|
||||
result += getFormat("workspace ID %i (%s) on monitor %s:\n\twindows: %i\n\thasfullscreen: %i\n\n",
|
||||
w.m_iID, w.m_szName.c_str(), g_pCompositor->getMonitorFromID(w.m_iMonitorID)->szName.c_str(), g_pCompositor->getWindowsOnWorkspace(w.m_iID), (int)w.m_bHasFullscreenWindow);
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
result += "[";
|
||||
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
result += getFormat(
|
||||
R"#({
|
||||
"id": %i,
|
||||
"name": "%s",
|
||||
"monitor": "%s",
|
||||
"windows": %i,
|
||||
"hasfullscreen": %i
|
||||
},)#",
|
||||
w->m_iID,
|
||||
escapeJSONStrings(w->m_szName).c_str(),
|
||||
escapeJSONStrings(g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName).c_str(),
|
||||
g_pCompositor->getWindowsOnWorkspace(w->m_iID),
|
||||
(int)w->m_bHasFullscreenWindow
|
||||
);
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
|
||||
result += "]";
|
||||
} else {
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
result += getFormat("workspace ID %i (%s) on monitor %s:\n\twindows: %i\n\thasfullscreen: %i\n\n",
|
||||
w->m_iID, w->m_szName.c_str(), g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName.c_str(), g_pCompositor->getWindowsOnWorkspace(w->m_iID), (int)w->m_bHasFullscreenWindow);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string activeWindowRequest() {
|
||||
std::string activeWindowRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
return "Invalid";
|
||||
|
||||
return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\n",
|
||||
PWINDOW, PWINDOW->m_szTitle.c_str(), (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y, PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()), (int)PWINDOW->m_bIsFloating, (int)PWINDOW->m_iMonitorID, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str(), g_pXWaylandManager->getTitle(PWINDOW).c_str(), PWINDOW->getPID());
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
return getFormat(
|
||||
R"#({
|
||||
"address": "0x%x",
|
||||
"at": [%i, %i],
|
||||
"size": [%i, %i],
|
||||
"workspace": {
|
||||
"id": %i,
|
||||
"name": "%s"
|
||||
},
|
||||
"floating": %i,
|
||||
"monitor": %i,
|
||||
"class": "%s",
|
||||
"title": "%s",
|
||||
"pid": %i,
|
||||
"xwayland": %i
|
||||
})#",
|
||||
PWINDOW,
|
||||
(int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y,
|
||||
(int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y,
|
||||
PWINDOW->m_iWorkspaceID, escapeJSONStrings(PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName).c_str(),
|
||||
(int)PWINDOW->m_bIsFloating,
|
||||
PWINDOW->m_iMonitorID,
|
||||
escapeJSONStrings(g_pXWaylandManager->getAppIDClass(PWINDOW)).c_str(),
|
||||
escapeJSONStrings(g_pXWaylandManager->getTitle(PWINDOW)).c_str(),
|
||||
PWINDOW->getPID(),
|
||||
(int)PWINDOW->m_bIsX11
|
||||
);
|
||||
} else {
|
||||
return getFormat("Window %x -> %s:\n\tat: %i,%i\n\tsize: %i,%i\n\tworkspace: %i (%s)\n\tfloating: %i\n\tmonitor: %i\n\tclass: %s\n\ttitle: %s\n\tpid: %i\n\txwayland: %i\n\n",
|
||||
PWINDOW, PWINDOW->m_szTitle.c_str(), (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y, PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()), (int)PWINDOW->m_bIsFloating, (int)PWINDOW->m_iMonitorID, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str(), g_pXWaylandManager->getTitle(PWINDOW).c_str(), PWINDOW->getPID(), (int)PWINDOW->m_bIsX11);
|
||||
}
|
||||
}
|
||||
|
||||
std::string layersRequest() {
|
||||
std::string layersRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string result = "";
|
||||
|
||||
for (auto& mon : g_pCompositor->m_lMonitors) {
|
||||
result += getFormat("Monitor %s:\n");
|
||||
int layerLevel = 0;
|
||||
for (auto& level : mon.m_aLayerSurfaceLists) {
|
||||
result += getFormat("\tLayer level %i:\n", layerLevel);
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
result += "{\n";
|
||||
|
||||
for (auto& layer : level) {
|
||||
result += getFormat("\t\tLayer %x: xywh: %i %i %i %i\n", layer, layer->geometry.x, layer->geometry.y, layer->geometry.width, layer->geometry.height);
|
||||
for (auto& mon : g_pCompositor->m_vMonitors) {
|
||||
result += getFormat(
|
||||
R"#("%s": {
|
||||
"levels": {
|
||||
)#",
|
||||
escapeJSONStrings(mon->szName).c_str()
|
||||
);
|
||||
|
||||
int layerLevel = 0;
|
||||
for (auto& level : mon->m_aLayerSurfaceLists) {
|
||||
result += getFormat(
|
||||
R"#(
|
||||
"%i": [
|
||||
)#",
|
||||
layerLevel
|
||||
);
|
||||
for (auto& layer : level) {
|
||||
result += getFormat(
|
||||
R"#( {
|
||||
"address": "0x%x",
|
||||
"x": %i,
|
||||
"y": %i,
|
||||
"w": %i,
|
||||
"h": %i,
|
||||
"namespace": "%s"
|
||||
},)#",
|
||||
layer.get(),
|
||||
layer->geometry.x,
|
||||
layer->geometry.y,
|
||||
layer->geometry.width,
|
||||
layer->geometry.height,
|
||||
escapeJSONStrings(layer->szNamespace).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
|
||||
if (level.size() > 0)
|
||||
result += "\n ";
|
||||
|
||||
result += "],";
|
||||
|
||||
layerLevel++;
|
||||
}
|
||||
|
||||
layerLevel++;
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
|
||||
result += "\n }\n},";
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
|
||||
result += "\n}\n";
|
||||
|
||||
} else {
|
||||
for (auto& mon : g_pCompositor->m_vMonitors) {
|
||||
result += getFormat("Monitor %s:\n", mon->szName.c_str());
|
||||
int layerLevel = 0;
|
||||
for (auto& level : mon->m_aLayerSurfaceLists) {
|
||||
result += getFormat("\tLayer level %i:\n", layerLevel);
|
||||
|
||||
for (auto& layer : level) {
|
||||
result += getFormat("\t\tLayer %x: xywh: %i %i %i %i, namespace: %s\n", layer.get(), layer->geometry.x, layer->geometry.y, layer->geometry.width, layer->geometry.height, layer->szNamespace.c_str());
|
||||
}
|
||||
|
||||
layerLevel++;
|
||||
}
|
||||
result += "\n\n";
|
||||
}
|
||||
result += "\n\n";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string devicesRequest() {
|
||||
std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) {
|
||||
std::string result = "";
|
||||
|
||||
result += "mice:\n";
|
||||
if (format == HyprCtl::FORMAT_JSON) {
|
||||
result += "{\n";
|
||||
result += "\"mice\": [\n";
|
||||
|
||||
for (auto& m : g_pInputManager->m_lMice) {
|
||||
result += getFormat("\tMouse at %x:\n\t\t%s\n", &m, m.mouse->name);
|
||||
}
|
||||
for (auto& m : g_pInputManager->m_lMice) {
|
||||
result += getFormat(
|
||||
R"#( {
|
||||
"address": "0x%x",
|
||||
"name": "%s"
|
||||
},)#",
|
||||
&m,
|
||||
escapeJSONStrings(m.mouse->name).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
result += "\n\nKeyboards:\n";
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
result += "\n],\n";
|
||||
|
||||
for (auto& k : g_pInputManager->m_lKeyboards) {
|
||||
result += getFormat("\tKeyboard at %x:\n\t\t%s\n", &k, k.keyboard->name);
|
||||
}
|
||||
result += "\"keyboards\": [\n";
|
||||
for (auto& k : g_pInputManager->m_lKeyboards) {
|
||||
const auto KM = xkb_keymap_layout_get_name(wlr_keyboard_from_input_device(k.keyboard)->keymap, 0);
|
||||
result += getFormat(
|
||||
R"#( {
|
||||
"address": "0x%x",
|
||||
"name": "%s",
|
||||
"rules": "%s",
|
||||
"model": "%s",
|
||||
"layout": "%s",
|
||||
"variant": "%s",
|
||||
"options": "%s",
|
||||
"active_keymap": "%s"
|
||||
},)#",
|
||||
&k,
|
||||
escapeJSONStrings(k.keyboard->name).c_str(),
|
||||
escapeJSONStrings(k.currentRules.rules).c_str(),
|
||||
escapeJSONStrings(k.currentRules.model).c_str(),
|
||||
escapeJSONStrings(k.currentRules.layout).c_str(),
|
||||
escapeJSONStrings(k.currentRules.variant).c_str(),
|
||||
escapeJSONStrings(k.currentRules.options).c_str(),
|
||||
escapeJSONStrings(KM).c_str()
|
||||
);
|
||||
}
|
||||
|
||||
result += "\n\nTablets:\n";
|
||||
// remove trailing comma
|
||||
result.pop_back();
|
||||
result += "\n],\n";
|
||||
|
||||
for (auto& d : g_pInputManager->m_lTabletPads) {
|
||||
result += getFormat("\tTablet Pad at %x (belongs to %x -> %s)\n", &d, d.pTabletParent, d.pTabletParent ? d.pTabletParent->wlrDevice ? d.pTabletParent->wlrDevice->name : "" : "");
|
||||
}
|
||||
result += "\"tablets\": [\n";
|
||||
|
||||
for (auto& d : g_pInputManager->m_lTablets) {
|
||||
result += getFormat("\tTablet at %x:\n\t\t%s\n", &d, d.wlrDevice ? d.wlrDevice->name : "");
|
||||
}
|
||||
for (auto& d : g_pInputManager->m_lTabletPads) {
|
||||
result += getFormat(
|
||||
R"#( {
|
||||
"address": "0x%x",
|
||||
"type": "tabletPad",
|
||||
"belongsTo": {
|
||||
"address": "0x%x",
|
||||
"name": "%s"
|
||||
}
|
||||
},)#",
|
||||
&d,
|
||||
d.pTabletParent,
|
||||
escapeJSONStrings(d.pTabletParent ? d.pTabletParent->wlrDevice ? d.pTabletParent->wlrDevice->name : "" : "").c_str()
|
||||
);
|
||||
}
|
||||
|
||||
for (auto& d : g_pInputManager->m_lTabletTools) {
|
||||
result += getFormat("\tTablet Tool at %x (belongs to %x)\n", &d, d.wlrTabletTool ? d.wlrTabletTool->data : 0);
|
||||
for (auto& d : g_pInputManager->m_lTablets) {
|
||||
result += getFormat(
|
||||
R"#( {
|
||||
"address": "0x%x",
|
||||
"name": "%s"
|
||||
},)#",
|
||||
&d,
|
||||
escapeJSONStrings(d.wlrDevice ? d.wlrDevice->name : "").c_str()
|
||||
);
|
||||
}
|
||||
|
||||
for (auto& d : g_pInputManager->m_lTabletTools) {
|
||||
result += getFormat(
|
||||
R"#( {
|
||||
"address": "0x%x",
|
||||
"type": "tabletTool",
|
||||
"belongsTo": "0x%x"
|
||||
},)#",
|
||||
&d,
|
||||
d.wlrTabletTool ? d.wlrTabletTool->data : 0
|
||||
);
|
||||
}
|
||||
|
||||
// remove trailing comma
|
||||
if (result[result.size() - 1] == ',')
|
||||
result.pop_back();
|
||||
result += "\n]\n";
|
||||
|
||||
result += "}\n";
|
||||
|
||||
} else {
|
||||
result += "mice:\n";
|
||||
|
||||
for (auto& m : g_pInputManager->m_lMice) {
|
||||
result += getFormat("\tMouse at %x:\n\t\t%s\n", &m, m.mouse->name);
|
||||
}
|
||||
|
||||
result += "\n\nKeyboards:\n";
|
||||
|
||||
for (auto& k : g_pInputManager->m_lKeyboards) {
|
||||
const auto KM = xkb_keymap_layout_get_name(wlr_keyboard_from_input_device(k.keyboard)->keymap, 0);
|
||||
result += getFormat("\tKeyboard at %x:\n\t\t%s\n\t\t\trules: r \"%s\", m \"%s\", l \"%s\", v \"%s\", o \"%s\"\n\t\t\tactive keymap: %s\n", &k, k.keyboard->name, k.currentRules.rules.c_str(), k.currentRules.model.c_str(), k.currentRules.layout.c_str(), k.currentRules.variant.c_str(), k.currentRules.options.c_str(), KM);
|
||||
}
|
||||
|
||||
result += "\n\nTablets:\n";
|
||||
|
||||
for (auto& d : g_pInputManager->m_lTabletPads) {
|
||||
result += getFormat("\tTablet Pad at %x (belongs to %x -> %s)\n", &d, d.pTabletParent, d.pTabletParent ? d.pTabletParent->wlrDevice ? d.pTabletParent->wlrDevice->name : "" : "");
|
||||
}
|
||||
|
||||
for (auto& d : g_pInputManager->m_lTablets) {
|
||||
result += getFormat("\tTablet at %x:\n\t\t%s\n", &d, d.wlrDevice ? d.wlrDevice->name : "");
|
||||
}
|
||||
|
||||
for (auto& d : g_pInputManager->m_lTabletTools) {
|
||||
result += getFormat("\tTablet Tool at %x (belongs to %x)\n", &d, d.wlrTabletTool ? d.wlrTabletTool->data : 0);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -158,9 +457,12 @@ std::string dispatchKeyword(std::string in) {
|
||||
if (COMMAND == "monitor")
|
||||
g_pConfigManager->m_bWantsMonitorReload = true; // for monitor keywords
|
||||
|
||||
if (COMMAND.find("input") != std::string::npos)
|
||||
if (COMMAND.contains("input"))
|
||||
g_pInputManager->setKeyboardLayout(); // update kb layout
|
||||
|
||||
if (COMMAND.contains("general:layout"))
|
||||
g_pLayoutManager->switchToLayout(g_pConfigManager->getString("general:layout")); // update layout
|
||||
|
||||
Debug::log(LOG, "Hyprctl: keyword %s : %s", COMMAND.c_str(), VALUE.c_str());
|
||||
|
||||
if (retval == "")
|
||||
@@ -181,6 +483,10 @@ std::string killRequest() {
|
||||
return "ok";
|
||||
}
|
||||
|
||||
std::string splashRequest() {
|
||||
return g_pCompositor->m_szCurrentSplash;
|
||||
}
|
||||
|
||||
std::string getReply(std::string);
|
||||
|
||||
std::string dispatchBatch(std::string request) {
|
||||
@@ -216,24 +522,46 @@ std::string dispatchBatch(std::string request) {
|
||||
}
|
||||
|
||||
std::string getReply(std::string request) {
|
||||
auto format = HyprCtl::FORMAT_NORMAL;
|
||||
|
||||
// process flags for non-batch requests
|
||||
if (!request.contains("[[BATCH]]") && request.contains("/")) {
|
||||
long unsigned int sepIndex = 0;
|
||||
for (const auto& c : request) {
|
||||
if (c == '/') { // stop at separator
|
||||
break;
|
||||
}
|
||||
|
||||
sepIndex++;
|
||||
|
||||
if (c == 'j')
|
||||
format = HyprCtl::FORMAT_JSON;
|
||||
}
|
||||
|
||||
if (sepIndex < request.size())
|
||||
request = request.substr(sepIndex + 1); // remove flags and separator so we can compare the rest of the string
|
||||
}
|
||||
|
||||
if (request == "monitors")
|
||||
return monitorsRequest();
|
||||
return monitorsRequest(format);
|
||||
else if (request == "workspaces")
|
||||
return workspacesRequest();
|
||||
return workspacesRequest(format);
|
||||
else if (request == "clients")
|
||||
return clientsRequest();
|
||||
return clientsRequest(format);
|
||||
else if (request == "kill")
|
||||
return killRequest();
|
||||
else if (request == "activewindow")
|
||||
return activeWindowRequest();
|
||||
return activeWindowRequest(format);
|
||||
else if (request == "layers")
|
||||
return layersRequest();
|
||||
return layersRequest(format);
|
||||
else if (request == "version")
|
||||
return versionRequest();
|
||||
else if (request == "reload")
|
||||
return reloadRequest();
|
||||
else if (request == "devices")
|
||||
return devicesRequest();
|
||||
return devicesRequest(format);
|
||||
else if (request == "splash")
|
||||
return splashRequest();
|
||||
else if (request.find("dispatch") == 0)
|
||||
return dispatchRequest(request);
|
||||
else if (request.find("keyword") == 0)
|
||||
@@ -264,6 +592,16 @@ void HyprCtl::tickHyprCtl() {
|
||||
}
|
||||
|
||||
std::string getRequestFromThread(std::string rq) {
|
||||
// we need to do something to wake hyprland up if VFR is enabled
|
||||
|
||||
static auto *const PNOVFR = &g_pConfigManager->getConfigValuePtr("misc:no_vfr")->intValue;
|
||||
|
||||
// TODO: is this safe...?
|
||||
// this might be a race condition
|
||||
// tested with 2 instances of `watch -n 0.1 hyprctl splash` and seems to not crash so I'll take that as a yes
|
||||
if (!*PNOVFR)
|
||||
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->m_vMonitors.front().get());
|
||||
|
||||
while (HyprCtl::request != "" || HyprCtl::requestMade || HyprCtl::requestReady) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
}
|
||||
|
@@ -14,4 +14,9 @@ namespace HyprCtl {
|
||||
inline std::string request = "";
|
||||
|
||||
inline std::ifstream requestStream;
|
||||
|
||||
enum eHyprCtlOutputFormat {
|
||||
FORMAT_NORMAL = 0,
|
||||
FORMAT_JSON
|
||||
};
|
||||
};
|
@@ -120,7 +120,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
|
||||
yOffset += 11;
|
||||
|
||||
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
|
||||
m_wbLastDrawnBox = {(int)g_pCompositor->m_lMonitors.front().vecPosition.x, (int)g_pCompositor->m_lMonitors.front().vecPosition.y + offset - 1, (int)maxX + 2, yOffset - offset + 2};
|
||||
m_wbLastDrawnBox = {(int)g_pCompositor->m_vMonitors.front()->vecPosition.x, (int)g_pCompositor->m_vMonitors.front()->vecPosition.y + offset - 1, (int)maxX + 2, yOffset - offset + 2};
|
||||
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
|
||||
|
||||
return yOffset - offset;
|
||||
@@ -140,7 +140,7 @@ void CHyprDebugOverlay::frameData(SMonitor* pMonitor) {
|
||||
|
||||
void CHyprDebugOverlay::draw() {
|
||||
|
||||
const auto PMONITOR = &g_pCompositor->m_lMonitors.front();
|
||||
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
|
||||
|
||||
if (!m_pCairoSurface || !m_pCairo) {
|
||||
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecSize.x, PMONITOR->vecSize.y);
|
||||
@@ -155,8 +155,8 @@ void CHyprDebugOverlay::draw() {
|
||||
|
||||
// draw the things
|
||||
int offsetY = 0;
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
offsetY += m_mMonitorOverlays[&m].draw(offsetY);
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
offsetY += m_mMonitorOverlays[m.get()].draw(offsetY);
|
||||
offsetY += 5; // for padding between mons
|
||||
}
|
||||
|
||||
|
@@ -14,6 +14,9 @@ void Debug::init(std::string IS) {
|
||||
|
||||
void Debug::log(LogLevel level, const char* fmt, ...) {
|
||||
|
||||
if (disableLogs && *disableLogs)
|
||||
return;
|
||||
|
||||
// log to a file
|
||||
std::ofstream ofs;
|
||||
ofs.open(logFile, std::ios::out | std::ios::app);
|
||||
@@ -38,37 +41,37 @@ void Debug::log(LogLevel level, const char* fmt, ...) {
|
||||
break;
|
||||
}
|
||||
|
||||
char buf[LOGMESSAGESIZE] = "";
|
||||
char* outputStr;
|
||||
int logLen;
|
||||
// print date and time to the ofs
|
||||
if (disableTime && !*disableTime) {
|
||||
auto timet = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
|
||||
const auto MILLIS = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() % 1000;
|
||||
|
||||
ofs << std::put_time(std::localtime(&timet), "[%H:%M:%S:");
|
||||
|
||||
if (MILLIS > 99)
|
||||
ofs << MILLIS;
|
||||
else if (MILLIS > 9)
|
||||
ofs << "0" << MILLIS;
|
||||
else
|
||||
ofs << "00" << MILLIS;
|
||||
|
||||
ofs << "] ";
|
||||
}
|
||||
|
||||
char* outputStr = nullptr;
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
logLen = vsnprintf(buf, sizeof buf, fmt, args);
|
||||
vasprintf(&outputStr, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if ((long unsigned int)logLen < sizeof buf) {
|
||||
outputStr = strdup(buf);
|
||||
} else {
|
||||
outputStr = (char*)malloc(logLen + 1);
|
||||
std::string output = std::string(outputStr);
|
||||
free(outputStr);
|
||||
|
||||
if (!outputStr) {
|
||||
printf("CRITICAL: Cannot alloc size %d for log! (Out of memory?)", logLen + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(args, fmt);
|
||||
vsnprintf(outputStr, logLen + 1U, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
ofs << outputStr << "\n";
|
||||
ofs << output << "\n";
|
||||
|
||||
ofs.close();
|
||||
|
||||
// log it to the stdout too.
|
||||
std::cout << outputStr << "\n";
|
||||
|
||||
// free the log
|
||||
free(outputStr);
|
||||
std::cout << output << "\n";
|
||||
}
|
||||
|
@@ -17,4 +17,6 @@ namespace Debug {
|
||||
void log(LogLevel level, const char* fmt, ...);
|
||||
|
||||
inline std::string logFile;
|
||||
inline int64_t* disableLogs = nullptr;
|
||||
inline int64_t* disableTime = nullptr;
|
||||
};
|
@@ -16,8 +16,6 @@
|
||||
#define ISDEBUG false
|
||||
#endif
|
||||
|
||||
#define RIP(format, ... ) { fprintf(stderr, format "\n", ##__VA_ARGS__); exit(EXIT_FAILURE); }
|
||||
|
||||
#define LISTENER(name) void listener_##name(wl_listener*, void*); inline wl_listener listen_##name = { .notify = listener_##name };
|
||||
#define DYNLISTENFUNC(name) void listener_##name(void*, void*);
|
||||
#define DYNLISTENER(name) CHyprWLListener hyprListener_##name;
|
||||
@@ -56,6 +54,12 @@
|
||||
|
||||
#define ASSERT(expr) RASSERT(expr, "?")
|
||||
|
||||
#if ISDEBUG
|
||||
#define UNREACHABLE() { Debug::log(CRIT, "\n\nMEMORY CORRUPTED: Unreachable failed! (Reached an unreachable position, memory corruption!!!)"); *((int*)nullptr) = 1; }
|
||||
#else
|
||||
#define UNREACHABLE() std::unreachable();
|
||||
#endif
|
||||
|
||||
// git stuff
|
||||
#ifndef GIT_COMMIT_HASH
|
||||
#define GIT_COMMIT_HASH "?"
|
||||
|
@@ -49,9 +49,7 @@ void Events::listener_mouseButton(wl_listener* listener, void* data) {
|
||||
}
|
||||
|
||||
void Events::listener_mouseAxis(wl_listener* listener, void* data) {
|
||||
const auto E = (wlr_pointer_axis_event*)data;
|
||||
|
||||
wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, E->time_msec, E->orientation, E->delta, E->delta_discrete, E->source);
|
||||
g_pInputManager->onMouseWheel((wlr_pointer_axis_event*)data);
|
||||
}
|
||||
|
||||
void Events::listener_requestMouse(wl_listener* listener, void* data) {
|
||||
@@ -151,11 +149,44 @@ void Events::listener_newVirtPtr(wl_listener* listener, void* data) {
|
||||
const auto POINTER = EV->new_pointer;
|
||||
const auto DEVICE = &POINTER->pointer.base;
|
||||
|
||||
g_pInputManager->newMouse(DEVICE);
|
||||
g_pInputManager->newMouse(DEVICE, true);
|
||||
}
|
||||
|
||||
void Events::listener_destroyMouse(void* owner, void* data) {
|
||||
const auto PMOUSE = (SMouse*)owner;
|
||||
|
||||
g_pInputManager->destroyMouse(PMOUSE->mouse);
|
||||
}
|
||||
|
||||
void Events::listener_swipeBegin(wl_listener* listener, void* data) {
|
||||
const auto EVENT = (wlr_pointer_swipe_begin_event*)data;
|
||||
|
||||
g_pInputManager->onSwipeBegin(EVENT);
|
||||
}
|
||||
|
||||
void Events::listener_swipeUpdate(wl_listener* listener, void* data) {
|
||||
const auto EVENT = (wlr_pointer_swipe_update_event*)data;
|
||||
|
||||
g_pInputManager->onSwipeUpdate(EVENT);
|
||||
}
|
||||
|
||||
void Events::listener_swipeEnd(wl_listener* listener, void* data) {
|
||||
const auto EVENT = (wlr_pointer_swipe_end_event*)data;
|
||||
|
||||
g_pInputManager->onSwipeEnd(EVENT);
|
||||
}
|
||||
|
||||
void Events::listener_pinchBegin(wl_listener* listener, void* data) {
|
||||
const auto EV = (wlr_pointer_pinch_begin_event*)data;
|
||||
wlr_pointer_gestures_v1_send_pinch_begin(g_pCompositor->m_sWLRPointerGestures, g_pCompositor->m_sSeat.seat, EV->time_msec, EV->fingers);
|
||||
}
|
||||
|
||||
void Events::listener_pinchUpdate(wl_listener* listener, void* data) {
|
||||
const auto EV = (wlr_pointer_pinch_update_event*)data;
|
||||
wlr_pointer_gestures_v1_send_pinch_update(g_pCompositor->m_sWLRPointerGestures, g_pCompositor->m_sSeat.seat, EV->time_msec, EV->dx, EV->dy, EV->scale, EV->rotation);
|
||||
}
|
||||
|
||||
void Events::listener_pinchEnd(wl_listener* listener, void* data) {
|
||||
const auto EV = (wlr_pointer_pinch_end_event*)data;
|
||||
wlr_pointer_gestures_v1_send_pinch_end(g_pCompositor->m_sWLRPointerGestures, g_pCompositor->m_sSeat.seat, EV->time_msec, EV->cancelled);
|
||||
}
|
@@ -49,6 +49,11 @@ namespace Events {
|
||||
DYNLISTENFUNC(fullscreenWindow);
|
||||
DYNLISTENFUNC(activateX11);
|
||||
DYNLISTENFUNC(configureX11);
|
||||
DYNLISTENFUNC(unmanagedSetGeometry);
|
||||
DYNLISTENFUNC(requestMove);
|
||||
DYNLISTENFUNC(requestResize);
|
||||
DYNLISTENFUNC(requestMinimize);
|
||||
DYNLISTENFUNC(requestMaximize);
|
||||
|
||||
// Window subsurfaces
|
||||
// LISTENER(newSubsurfaceWindow);
|
||||
@@ -112,4 +117,17 @@ namespace Events {
|
||||
|
||||
// Renderer destroy
|
||||
LISTENER(RendererDestroy);
|
||||
|
||||
LISTENER(newIdleInhibitor);
|
||||
|
||||
// session
|
||||
LISTENER(sessionActive);
|
||||
|
||||
// Touchpad shit
|
||||
LISTENER(swipeBegin);
|
||||
LISTENER(swipeEnd);
|
||||
LISTENER(swipeUpdate);
|
||||
LISTENER(pinchBegin);
|
||||
LISTENER(pinchUpdate);
|
||||
LISTENER(pinchEnd);
|
||||
};
|
@@ -32,15 +32,16 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
|
||||
}
|
||||
|
||||
const auto PMONITOR = (SMonitor*)g_pCompositor->getMonitorFromOutput(WLRLAYERSURFACE->output);
|
||||
PMONITOR->m_aLayerSurfaceLists[WLRLAYERSURFACE->pending.layer].push_back(new SLayerSurface());
|
||||
SLayerSurface* layerSurface = PMONITOR->m_aLayerSurfaceLists[WLRLAYERSURFACE->pending.layer].back();
|
||||
SLayerSurface* layerSurface = PMONITOR->m_aLayerSurfaceLists[WLRLAYERSURFACE->pending.layer].emplace_back(std::make_unique<SLayerSurface>()).get();
|
||||
|
||||
layerSurface->szNamespace = WLRLAYERSURFACE->_namespace;
|
||||
|
||||
if (!WLRLAYERSURFACE->output) {
|
||||
WLRLAYERSURFACE->output = g_pCompositor->m_lMonitors.front().output; // TODO: current mon
|
||||
WLRLAYERSURFACE->output = g_pCompositor->m_vMonitors.front()->output; // TODO: current mon
|
||||
}
|
||||
|
||||
layerSurface->hyprListener_commitLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.commit, &Events::listener_commitLayerSurface, layerSurface, "layerSurface");
|
||||
layerSurface->hyprListener_destroyLayerSurface.initCallback(&WLRLAYERSURFACE->surface->events.destroy, &Events::listener_destroyLayerSurface, layerSurface, "layerSurface");
|
||||
layerSurface->hyprListener_destroyLayerSurface.initCallback(&WLRLAYERSURFACE->events.destroy, &Events::listener_destroyLayerSurface, layerSurface, "layerSurface");
|
||||
layerSurface->hyprListener_mapLayerSurface.initCallback(&WLRLAYERSURFACE->events.map, &Events::listener_mapLayerSurface, layerSurface, "layerSurface");
|
||||
layerSurface->hyprListener_unmapLayerSurface.initCallback(&WLRLAYERSURFACE->events.unmap, &Events::listener_unmapLayerSurface, layerSurface, "layerSurface");
|
||||
layerSurface->hyprListener_newPopup.initCallback(&WLRLAYERSURFACE->events.new_popup, &Events::listener_newPopup, layerSurface, "layerSurface");
|
||||
@@ -50,6 +51,8 @@ void Events::listener_newLayerSurface(wl_listener* listener, void* data) {
|
||||
WLRLAYERSURFACE->data = layerSurface;
|
||||
layerSurface->monitorID = PMONITOR->ID;
|
||||
|
||||
layerSurface->forceBlur = g_pConfigManager->shouldBlurLS(layerSurface->szNamespace);
|
||||
|
||||
Debug::log(LOG, "LayerSurface %x (namespace %s layer %d) created on monitor %s", layerSurface->layerSurface, layerSurface->layerSurface->_namespace, layerSurface->layer, PMONITOR->szName.c_str());
|
||||
}
|
||||
|
||||
@@ -63,12 +66,20 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
|
||||
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID))
|
||||
Debug::log(WARN, "Layersurface destroyed on an invalid monitor (removed?)");
|
||||
|
||||
if (!layersurface->fadingOut && PMONITOR) {
|
||||
Debug::log(LOG, "Removing LayerSurface that wasn't mapped.");
|
||||
layersurface->alpha.setValueAndWarp(0.f);
|
||||
layersurface->fadingOut = true;
|
||||
if (!layersurface->fadingOut) {
|
||||
if (layersurface->mapped) {
|
||||
Debug::log(LOG, "Forcing an unmap of a LS that did a straight destroy!");
|
||||
listener_unmapLayerSurface(layersurface, nullptr);
|
||||
} else {
|
||||
Debug::log(LOG, "Removing LayerSurface that wasn't mapped.");
|
||||
layersurface->alpha.setValueAndWarp(0.f);
|
||||
layersurface->fadingOut = true;
|
||||
g_pCompositor->addToFadingOutSafe(layersurface);
|
||||
}
|
||||
}
|
||||
|
||||
layersurface->noProcess = true;
|
||||
|
||||
layersurface->hyprListener_commitLayerSurface.removeCallback();
|
||||
layersurface->hyprListener_destroyLayerSurface.removeCallback();
|
||||
layersurface->hyprListener_mapLayerSurface.removeCallback();
|
||||
@@ -78,7 +89,7 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) {
|
||||
// rearrange to fix the reserved areas
|
||||
if (PMONITOR) {
|
||||
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
|
||||
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};
|
||||
@@ -95,8 +106,7 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||
Debug::log(LOG, "LayerSurface %x mapped", layersurface->layerSurface);
|
||||
|
||||
layersurface->layerSurface->mapped = true;
|
||||
|
||||
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
|
||||
layersurface->mapped = true;
|
||||
|
||||
// fix if it changed its mon
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output);
|
||||
@@ -106,18 +116,29 @@ void Events::listener_mapLayerSurface(void* owner, void* data) {
|
||||
|
||||
if ((uint64_t)layersurface->monitorID != PMONITOR->ID) {
|
||||
const auto POLDMON = g_pCompositor->getMonitorFromID(layersurface->monitorID);
|
||||
POLDMON->m_aLayerSurfaceLists[layersurface->layer].remove(layersurface);
|
||||
PMONITOR->m_aLayerSurfaceLists[layersurface->layer].push_back(layersurface);
|
||||
for (auto it = POLDMON->m_aLayerSurfaceLists[layersurface->layer].begin(); it != POLDMON->m_aLayerSurfaceLists[layersurface->layer].end(); it++) {
|
||||
if (it->get() == layersurface) {
|
||||
PMONITOR->m_aLayerSurfaceLists[layersurface->layer].emplace_back(std::move(*it));
|
||||
POLDMON->m_aLayerSurfaceLists[layersurface->layer].erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
layersurface->monitorID = PMONITOR->ID;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->ID);
|
||||
PMONITOR->scheduledRecalc = true;
|
||||
g_pHyprRenderer->arrangeLayersForMonitor(POLDMON->ID);
|
||||
}
|
||||
|
||||
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
|
||||
|
||||
if (layersurface->layerSurface->current.keyboard_interactive)
|
||||
if (layersurface->layerSurface->current.keyboard_interactive && (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint)) { // don't focus if constrained
|
||||
wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output);
|
||||
g_pCompositor->focusSurface(layersurface->layerSurface->surface);
|
||||
|
||||
const auto LOCAL = g_pInputManager->getMouseCoordsInternal() - Vector2D(layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y);
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, layersurface->layerSurface->surface, LOCAL.x, LOCAL.y);
|
||||
wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, 0, LOCAL.x, LOCAL.y);
|
||||
}
|
||||
|
||||
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};
|
||||
@@ -136,6 +157,14 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
||||
|
||||
if (!g_pCompositor->getMonitorFromID(layersurface->monitorID)) {
|
||||
Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring.");
|
||||
|
||||
g_pCompositor->addToFadingOutSafe(layersurface);
|
||||
|
||||
layersurface->mapped = false;
|
||||
|
||||
layersurface->fadingOut = true;
|
||||
|
||||
layersurface->alpha.setValueAndWarp(0.f);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -143,21 +172,26 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) {
|
||||
g_pHyprOpenGL->makeLayerSnapshot(layersurface);
|
||||
layersurface->alpha = 0.f;
|
||||
|
||||
layersurface->mapped = false;
|
||||
|
||||
layersurface->fadingOut = true;
|
||||
|
||||
g_pCompositor->m_lSurfacesFadingOut.push_back(layersurface);
|
||||
g_pCompositor->addToFadingOutSafe(layersurface);
|
||||
|
||||
if (layersurface->layerSurface->mapped)
|
||||
layersurface->layerSurface->mapped = false;
|
||||
|
||||
if (layersurface->layerSurface->surface == g_pCompositor->m_pLastFocus)
|
||||
g_pCompositor->m_pLastFocus = nullptr;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(layersurface->layerSurface->output);
|
||||
|
||||
if (!PMONITOR)
|
||||
return;
|
||||
|
||||
// refocus if needed
|
||||
if (layersurface->layerSurface->surface == g_pCompositor->m_pLastFocus) {
|
||||
g_pCompositor->m_pLastFocus = nullptr;
|
||||
g_pInputManager->refocus();
|
||||
}
|
||||
|
||||
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
|
||||
@@ -179,33 +213,49 @@ void Events::listener_commitLayerSurface(void* owner, void* data) {
|
||||
if (!PMONITOR)
|
||||
return;
|
||||
|
||||
wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, layersurface->geometry.height};
|
||||
wlr_box geomFixed = {layersurface->geometry.x, layersurface->geometry.y, layersurface->geometry.width, layersurface->geometry.height};
|
||||
g_pHyprRenderer->damageBox(&geomFixed);
|
||||
|
||||
// fix if it changed its mon
|
||||
if ((uint64_t)layersurface->monitorID != PMONITOR->ID) {
|
||||
const auto POLDMON = g_pCompositor->getMonitorFromID(layersurface->monitorID);
|
||||
POLDMON->m_aLayerSurfaceLists[layersurface->layer].remove(layersurface);
|
||||
PMONITOR->m_aLayerSurfaceLists[layersurface->layer].push_back(layersurface);
|
||||
|
||||
for (auto it = POLDMON->m_aLayerSurfaceLists[layersurface->layer].begin(); it != POLDMON->m_aLayerSurfaceLists[layersurface->layer].end(); it++) {
|
||||
if (it->get() == layersurface) {
|
||||
PMONITOR->m_aLayerSurfaceLists[layersurface->layer].emplace_back(std::move(*it));
|
||||
POLDMON->m_aLayerSurfaceLists[layersurface->layer].erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
layersurface->monitorID = PMONITOR->ID;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(POLDMON->ID);
|
||||
PMONITOR->scheduledRecalc = true;
|
||||
g_pHyprRenderer->arrangeLayersForMonitor(POLDMON->ID);
|
||||
}
|
||||
|
||||
if (layersurface->layerSurface->current.committed != 0) {
|
||||
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
|
||||
|
||||
if (layersurface->layer != layersurface->layerSurface->current.layer) {
|
||||
PMONITOR->m_aLayerSurfaceLists[layersurface->layer].remove(layersurface);
|
||||
PMONITOR->m_aLayerSurfaceLists[layersurface->layerSurface->current.layer].push_back(layersurface);
|
||||
|
||||
for (auto it = PMONITOR->m_aLayerSurfaceLists[layersurface->layer].begin(); it != PMONITOR->m_aLayerSurfaceLists[layersurface->layer].end(); it++) {
|
||||
if (it->get() == layersurface) {
|
||||
PMONITOR->m_aLayerSurfaceLists[layersurface->layerSurface->current.layer].emplace_back(std::move(*it));
|
||||
PMONITOR->m_aLayerSurfaceLists[layersurface->layer].erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
layersurface->layer = layersurface->layerSurface->current.layer;
|
||||
}
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
|
||||
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
|
||||
|
||||
PMONITOR->scheduledRecalc = true;
|
||||
}
|
||||
|
||||
layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y);
|
||||
|
||||
// TODO: optimize this. This does NOT need to be here but it prevents some issues with full DT.
|
||||
g_pHyprRenderer->damageMonitor(PMONITOR);
|
||||
// update geom if it changed
|
||||
layersurface->geometry = {layersurface->geometry.x, layersurface->geometry.y, layersurface->layerSurface->surface->current.width, layersurface->layerSurface->surface->current.height};
|
||||
|
||||
g_pHyprRenderer->damageSurface(layersurface->layerSurface->surface, layersurface->position.x, layersurface->position.y);
|
||||
}
|
@@ -157,4 +157,10 @@ void Events::listener_InhibitDeactivate(wl_listener* listener, void* data) {
|
||||
|
||||
void Events::listener_RendererDestroy(wl_listener* listener, void* data) {
|
||||
Debug::log(LOG, "!!Renderer destroyed!!");
|
||||
}
|
||||
|
||||
void Events::listener_sessionActive(wl_listener* listener, void* data) {
|
||||
Debug::log(LOG, "Session got activated!");
|
||||
|
||||
g_pCompositor->m_bSessionActive = true;
|
||||
}
|
@@ -21,24 +21,24 @@ void Events::listener_change(wl_listener* listener, void* data) {
|
||||
// layout got changed, let's update monitors.
|
||||
const auto CONFIG = wlr_output_configuration_v1_create();
|
||||
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
const auto CONFIGHEAD = wlr_output_configuration_head_v1_create(CONFIG, m.output);
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
const auto CONFIGHEAD = wlr_output_configuration_head_v1_create(CONFIG, m->output);
|
||||
|
||||
// TODO: clients off of disabled
|
||||
wlr_box BOX;
|
||||
wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m.output, &BOX);
|
||||
wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m->output, &BOX);
|
||||
|
||||
//m.vecSize.x = BOX.width;
|
||||
// m.vecSize.y = BOX.height;
|
||||
m.vecPosition.x = BOX.x;
|
||||
m.vecPosition.y = BOX.y;
|
||||
//m->vecSize.x = BOX.width;
|
||||
// m->vecSize.y = BOX.height;
|
||||
m->vecPosition.x = BOX.x;
|
||||
m->vecPosition.y = BOX.y;
|
||||
|
||||
CONFIGHEAD->state.enabled = m.output->enabled;
|
||||
CONFIGHEAD->state.mode = m.output->current_mode;
|
||||
CONFIGHEAD->state.x = m.vecPosition.x;
|
||||
CONFIGHEAD->state.y = m.vecPosition.y;
|
||||
CONFIGHEAD->state.enabled = m->output->enabled;
|
||||
CONFIGHEAD->state.mode = m->output->current_mode;
|
||||
CONFIGHEAD->state.x = m->vecPosition.x;
|
||||
CONFIGHEAD->state.y = m->vecPosition.y;
|
||||
|
||||
wlr_output_set_custom_mode(m.output, m.vecPixelSize.x, m.vecPixelSize.y, (int)(round(m.refreshRate * 1000)));
|
||||
wlr_output_set_custom_mode(m->output, m->vecPixelSize.x, m->vecPixelSize.y, (int)(round(m->refreshRate * 1000)));
|
||||
}
|
||||
|
||||
wlr_output_manager_v1_set_configuration(g_pCompositor->m_sWLROutputMgr, CONFIG);
|
||||
@@ -72,10 +72,11 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||
return;
|
||||
}
|
||||
|
||||
SMonitor newMonitor;
|
||||
newMonitor.output = OUTPUT;
|
||||
newMonitor.ID = g_pCompositor->getNextAvailableMonitorID();
|
||||
newMonitor.szName = OUTPUT->name;
|
||||
const auto PNEWMONITOR = g_pCompositor->m_vMonitors.emplace_back(std::make_unique<SMonitor>()).get();
|
||||
|
||||
PNEWMONITOR->output = OUTPUT;
|
||||
PNEWMONITOR->ID = g_pCompositor->getNextAvailableMonitorID();
|
||||
PNEWMONITOR->szName = OUTPUT->name;
|
||||
|
||||
wlr_output_init_render(OUTPUT, g_pCompositor->m_sWLRAllocator, g_pCompositor->m_sWLRRenderer);
|
||||
|
||||
@@ -86,12 +87,9 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||
wlr_output_enable_adaptive_sync(OUTPUT, 1);
|
||||
|
||||
// create it in the arr
|
||||
newMonitor.vecPosition = monitorRule.offset;
|
||||
newMonitor.vecSize = monitorRule.resolution;
|
||||
newMonitor.refreshRate = monitorRule.refreshRate;
|
||||
|
||||
g_pCompositor->m_lMonitors.push_back(newMonitor);
|
||||
const auto PNEWMONITOR = &g_pCompositor->m_lMonitors.back();
|
||||
PNEWMONITOR->vecPosition = monitorRule.offset;
|
||||
PNEWMONITOR->vecSize = monitorRule.resolution;
|
||||
PNEWMONITOR->refreshRate = monitorRule.refreshRate;
|
||||
|
||||
PNEWMONITOR->hyprListener_monitorFrame.initCallback(&OUTPUT->events.frame, &Events::listener_monitorFrame, PNEWMONITOR);
|
||||
PNEWMONITOR->hyprListener_monitorDestroy.initCallback(&OUTPUT->events.destroy, &Events::listener_monitorDestroy, PNEWMONITOR);
|
||||
@@ -115,13 +113,13 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||
|
||||
// Workspace
|
||||
std::string newDefaultWorkspaceName = "";
|
||||
auto WORKSPACEID = monitorRule.defaultWorkspace == "" ? g_pCompositor->m_lWorkspaces.size() + 1 : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
|
||||
auto WORKSPACEID = monitorRule.defaultWorkspace == "" ? g_pCompositor->m_vWorkspaces.size() + 1 : getWorkspaceIDFromString(monitorRule.defaultWorkspace, newDefaultWorkspaceName);
|
||||
|
||||
if (WORKSPACEID == INT_MAX || WORKSPACEID == (long unsigned int)SPECIAL_WORKSPACE_ID) {
|
||||
WORKSPACEID = g_pCompositor->m_lWorkspaces.size() + 1;
|
||||
WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1;
|
||||
newDefaultWorkspaceName = std::to_string(WORKSPACEID);
|
||||
|
||||
Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace);
|
||||
Debug::log(LOG, "Invalid workspace= directive name in monitor parsing, workspace name \"%s\" is invalid.", monitorRule.defaultWorkspace.c_str());
|
||||
}
|
||||
|
||||
auto PNEWWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID);
|
||||
@@ -135,7 +133,7 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PNEWMONITOR->ID);
|
||||
PNEWWORKSPACE->startAnim(true,true,true);
|
||||
} else {
|
||||
PNEWWORKSPACE = &g_pCompositor->m_lWorkspaces.emplace_back(newMonitor.ID, newDefaultWorkspaceName);
|
||||
PNEWWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(PNEWMONITOR->ID, newDefaultWorkspaceName)).get();
|
||||
|
||||
// We are required to set the name here immediately
|
||||
wlr_ext_workspace_handle_v1_set_name(PNEWWORKSPACE->m_pWlrHandle, newDefaultWorkspaceName.c_str());
|
||||
@@ -150,15 +148,15 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||
|
||||
g_pCompositor->deactivateAllWLRWorkspaces(PNEWWORKSPACE->m_pWlrHandle);
|
||||
PNEWWORKSPACE->setActive(true);
|
||||
//
|
||||
|
||||
if (!pMostHzMonitor || monitorRule.refreshRate > pMostHzMonitor->refreshRate)
|
||||
pMostHzMonitor = PNEWMONITOR;
|
||||
//
|
||||
|
||||
if (!g_pCompositor->m_pLastMonitor) // set the last monitor if it isnt set yet
|
||||
g_pCompositor->m_pLastMonitor = PNEWMONITOR;
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent("monitoradded", PNEWMONITOR->szName));
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", PNEWMONITOR->szName});
|
||||
|
||||
// ready to process cuz we have a monitor
|
||||
g_pCompositor->m_bReadyToProcess = true;
|
||||
@@ -167,40 +165,32 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
|
||||
void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
SMonitor* const PMONITOR = (SMonitor*)owner;
|
||||
|
||||
if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive) {
|
||||
Debug::log(WARN, "Attempted to render frame on inactive session!");
|
||||
return; // cannot draw on session inactive (different tty)
|
||||
}
|
||||
|
||||
static std::chrono::high_resolution_clock::time_point startRender = std::chrono::high_resolution_clock::now();
|
||||
static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
|
||||
static auto *const PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue;
|
||||
static auto *const PDAMAGETRACKINGMODE = &g_pConfigManager->getConfigValuePtr("general:damage_tracking_internal")->intValue;
|
||||
static auto *const PDAMAGEBLINK = &g_pConfigManager->getConfigValuePtr("debug:damage_blink")->intValue;
|
||||
static auto *const PNOVFR = &g_pConfigManager->getConfigValuePtr("misc:no_vfr")->intValue;
|
||||
|
||||
static int damageBlinkCleanup = 0; // because double-buffered
|
||||
|
||||
if (*PDEBUGOVERLAY == 1) {
|
||||
startRender = std::chrono::high_resolution_clock::now();
|
||||
g_pDebugOverlay->frameData(PMONITOR);
|
||||
}
|
||||
|
||||
// Hack: only check when monitor with top hz refreshes, saves a bit of resources.
|
||||
// This is for stuff that should be run every frame
|
||||
if (PMONITOR->ID == pMostHzMonitor->ID) {
|
||||
g_pCompositor->sanityCheckWorkspaces();
|
||||
g_pAnimationManager->tick();
|
||||
g_pCompositor->cleanupFadingOut();
|
||||
|
||||
HyprCtl::tickHyprCtl(); // so that we dont get that race condition multithread bullshit
|
||||
|
||||
g_pConfigManager->dispatchExecOnce(); // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd
|
||||
|
||||
if (g_pConfigManager->m_bWantsMonitorReload)
|
||||
g_pConfigManager->performMonitorReload();
|
||||
|
||||
g_pHyprRenderer->ensureCursorRenderingMode(); // so that the cursor gets hidden/shown if the user requested timeouts
|
||||
}
|
||||
|
||||
if (PMONITOR->framesToSkip > 0) {
|
||||
PMONITOR->framesToSkip -= 1;
|
||||
|
||||
if (!PMONITOR->noFrameSchedule)
|
||||
wlr_output_schedule_frame(PMONITOR->output);
|
||||
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
||||
else {
|
||||
Debug::log(LOG, "NoFrameSchedule hit for %s.", PMONITOR->szName.c_str());
|
||||
}
|
||||
@@ -208,6 +198,27 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
return;
|
||||
}
|
||||
|
||||
// checks //
|
||||
if (PMONITOR->ID == pMostHzMonitor->ID || !*PNOVFR) { // unfortunately with VFR we don't have the guarantee mostHz is going to be updated all the time, so we have to ignore that
|
||||
g_pCompositor->sanityCheckWorkspaces();
|
||||
g_pAnimationManager->tick();
|
||||
|
||||
HyprCtl::tickHyprCtl(); // so that we dont get that race condition multithread bullshit
|
||||
|
||||
g_pConfigManager->dispatchExecOnce(); // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd
|
||||
|
||||
if (g_pConfigManager->m_bWantsMonitorReload)
|
||||
g_pConfigManager->performMonitorReload();
|
||||
|
||||
g_pHyprRenderer->ensureCursorRenderingMode(); // so that the cursor gets hidden/shown if the user requested timeouts
|
||||
}
|
||||
// //
|
||||
|
||||
if (PMONITOR->scheduledRecalc) {
|
||||
PMONITOR->scheduledRecalc = false;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
|
||||
}
|
||||
|
||||
timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
|
||||
@@ -226,15 +237,21 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && PMONITOR->forceFullFrames == 0) {
|
||||
// we need to cleanup fading out when rendering the appropriate context
|
||||
g_pCompositor->cleanupFadingOut(PMONITOR->ID);
|
||||
|
||||
if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && PMONITOR->forceFullFrames == 0 && damageBlinkCleanup == 0) {
|
||||
pixman_region32_fini(&damage);
|
||||
wlr_output_rollback(PMONITOR->output);
|
||||
wlr_output_schedule_frame(PMONITOR->output); // we update shit at the monitor's Hz so we need to schedule frames because rollback wont
|
||||
|
||||
if (*PDAMAGEBLINK || *PNOVFR)
|
||||
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// if we have no tracking or full tracking, invalidate the entire monitor
|
||||
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0) {
|
||||
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0 || damageBlinkCleanup > 0) {
|
||||
pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
|
||||
|
||||
pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
|
||||
@@ -264,7 +281,7 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
// potentially can save on resources.
|
||||
|
||||
g_pHyprOpenGL->begin(PMONITOR, &damage);
|
||||
g_pHyprOpenGL->clear(CColor(100, 11, 11, 255));
|
||||
g_pHyprOpenGL->clear(CColor(17, 17, 17, 255));
|
||||
g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
|
||||
|
||||
g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
|
||||
@@ -280,6 +297,16 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
endRenderOverlay = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
if (*PDAMAGEBLINK && damageBlinkCleanup == 0) {
|
||||
wlr_box monrect = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
g_pHyprOpenGL->renderRect(&monrect, CColor(255,0,255,100), 0);
|
||||
damageBlinkCleanup = 1;
|
||||
} else if (*PDAMAGEBLINK) {
|
||||
damageBlinkCleanup++;
|
||||
if (damageBlinkCleanup > 3)
|
||||
damageBlinkCleanup = 0;
|
||||
}
|
||||
|
||||
wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||
|
||||
wlr_output_render_software_cursors(PMONITOR->output, NULL);
|
||||
@@ -298,13 +325,17 @@ void Events::listener_monitorFrame(void* owner, void* data) {
|
||||
if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR)
|
||||
pixman_region32_union_rect(&frameDamage, &frameDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
|
||||
|
||||
if (*PDAMAGEBLINK)
|
||||
pixman_region32_union(&frameDamage, &frameDamage, &damage);
|
||||
|
||||
wlr_output_set_damage(PMONITOR->output, &frameDamage);
|
||||
pixman_region32_fini(&frameDamage);
|
||||
pixman_region32_fini(&damage);
|
||||
|
||||
wlr_output_commit(PMONITOR->output);
|
||||
|
||||
wlr_output_schedule_frame(PMONITOR->output);
|
||||
if (*PDAMAGEBLINK || *PNOVFR)
|
||||
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
||||
|
||||
if (*PDEBUGOVERLAY == 1) {
|
||||
const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f;
|
||||
@@ -323,9 +354,9 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||
|
||||
SMonitor* pMonitor = nullptr;
|
||||
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
if (m.szName == OUTPUT->name) {
|
||||
pMonitor = &m;
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->szName == OUTPUT->name) {
|
||||
pMonitor = m.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -334,12 +365,11 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||
return;
|
||||
|
||||
// Cleanup everything. Move windows back, snap cursor, shit.
|
||||
const auto BACKUPMON = &g_pCompositor->m_lMonitors.front();
|
||||
const auto BACKUPMON = g_pCompositor->m_vMonitors.front().get();
|
||||
|
||||
if (!BACKUPMON) {
|
||||
Debug::log(CRIT, "No monitors! Unplugged last! Exiting.");
|
||||
g_pCompositor->cleanupExit();
|
||||
exit(1);
|
||||
g_pCompositor->cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -350,9 +380,9 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||
|
||||
// move workspaces
|
||||
std::deque<CWorkspace*> wspToMove;
|
||||
for (auto& w : g_pCompositor->m_lWorkspaces) {
|
||||
if (w.m_iMonitorID == pMonitor->ID) {
|
||||
wspToMove.push_back(&w);
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (w->m_iMonitorID == pMonitor->ID) {
|
||||
wspToMove.push_back(w.get());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,27 +393,22 @@ void Events::listener_monitorDestroy(void* owner, void* data) {
|
||||
|
||||
pMonitor->activeWorkspace = -1;
|
||||
|
||||
for (auto it = g_pCompositor->m_lWorkspaces.begin(); it != g_pCompositor->m_lWorkspaces.end(); ++it) {
|
||||
if (it->m_iMonitorID == pMonitor->ID) {
|
||||
it = g_pCompositor->m_lWorkspaces.erase(it);
|
||||
}
|
||||
}
|
||||
g_pCompositor->m_vWorkspaces.erase(std::remove_if(g_pCompositor->m_vWorkspaces.begin(), g_pCompositor->m_vWorkspaces.end(), [&](std::unique_ptr<CWorkspace>& el) { return el->m_iMonitorID == pMonitor->ID; }));
|
||||
|
||||
Debug::log(LOG, "Removed monitor %s!", pMonitor->szName.c_str());
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent("monitorremoved", pMonitor->szName));
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", pMonitor->szName});
|
||||
|
||||
g_pCompositor->m_lMonitors.remove(*pMonitor);
|
||||
g_pCompositor->m_vMonitors.erase(std::remove_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](std::unique_ptr<SMonitor>& el) { return el.get() == pMonitor; }));
|
||||
|
||||
// update the pMostHzMonitor
|
||||
if (pMostHzMonitor == pMonitor) {
|
||||
int mostHz = 0;
|
||||
SMonitor* pMonitorMostHz = nullptr;
|
||||
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
if (m.refreshRate > mostHz) {
|
||||
pMonitorMostHz = &m;
|
||||
mostHz = m.refreshRate;
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->refreshRate > mostHz) {
|
||||
pMonitorMostHz = m.get();
|
||||
mostHz = m->refreshRate;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -51,7 +51,7 @@ void addPopupGlobalCoords(void* pPopup, int* x, int* y) {
|
||||
void createNewPopup(wlr_xdg_popup* popup, SXDGPopup* pHyprPopup) {
|
||||
pHyprPopup->popup = popup;
|
||||
|
||||
pHyprPopup->hyprListener_destroyPopupXDG.initCallback(&popup->base->surface->events.destroy, &Events::listener_destroyPopupXDG, pHyprPopup, "HyprPopup");
|
||||
pHyprPopup->hyprListener_destroyPopupXDG.initCallback(&popup->base->events.destroy, &Events::listener_destroyPopupXDG, pHyprPopup, "HyprPopup");
|
||||
pHyprPopup->hyprListener_mapPopupXDG.initCallback(&popup->base->events.map, &Events::listener_mapPopupXDG, pHyprPopup, "HyprPopup");
|
||||
pHyprPopup->hyprListener_unmapPopupXDG.initCallback(&popup->base->events.unmap, &Events::listener_unmapPopupXDG, pHyprPopup, "HyprPopup");
|
||||
pHyprPopup->hyprListener_newPopupFromPopupXDG.initCallback(&popup->base->events.new_popup, &Events::listener_newPopupFromPopupXDG, pHyprPopup, "HyprPopup");
|
||||
@@ -76,8 +76,7 @@ void Events::listener_newPopup(void* owner, void* data) {
|
||||
|
||||
const auto WLRPOPUP = (wlr_xdg_popup*)data;
|
||||
|
||||
g_pCompositor->m_lXDGPopups.push_back(SXDGPopup());
|
||||
const auto PNEWPOPUP = &g_pCompositor->m_lXDGPopups.back();
|
||||
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(layersurface->monitorID);
|
||||
|
||||
@@ -93,12 +92,14 @@ void Events::listener_newPopupXDG(void* owner, void* data) {
|
||||
|
||||
ASSERT(PWINDOW);
|
||||
|
||||
if (!PWINDOW->m_bIsMapped)
|
||||
return;
|
||||
|
||||
Debug::log(LOG, "New layer popup created from XDG window %x -> %s", PWINDOW, PWINDOW->m_szTitle.c_str());
|
||||
|
||||
const auto WLRPOPUP = (wlr_xdg_popup*)data;
|
||||
|
||||
g_pCompositor->m_lXDGPopups.push_back(SXDGPopup());
|
||||
const auto PNEWPOPUP = &g_pCompositor->m_lXDGPopups.back();
|
||||
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
|
||||
@@ -122,8 +123,7 @@ void Events::listener_newPopupFromPopupXDG(void* owner, void* data) {
|
||||
|
||||
const auto WLRPOPUP = (wlr_xdg_popup*)data;
|
||||
|
||||
g_pCompositor->m_lXDGPopups.push_back(SXDGPopup());
|
||||
const auto PNEWPOPUP = &g_pCompositor->m_lXDGPopups.back();
|
||||
const auto PNEWPOPUP = g_pCompositor->m_vXDGPopups.emplace_back(std::make_unique<SXDGPopup>()).get();
|
||||
|
||||
PNEWPOPUP->popup = WLRPOPUP;
|
||||
PNEWPOPUP->parentPopup = PPOPUP;
|
||||
@@ -170,5 +170,5 @@ void Events::listener_destroyPopupXDG(void* owner, void* data) {
|
||||
PPOPUP->pSurfaceTree = nullptr;
|
||||
}
|
||||
|
||||
g_pCompositor->m_lXDGPopups.remove(*PPOPUP);
|
||||
g_pCompositor->m_vXDGPopups.erase(std::remove_if(g_pCompositor->m_vXDGPopups.begin(), g_pCompositor->m_vXDGPopups.end(), [&](std::unique_ptr<SXDGPopup>& el) { return el.get() == PPOPUP; }));
|
||||
}
|
@@ -32,6 +32,9 @@ void addViewCoords(void* pWindow, int* x, int* y) {
|
||||
void Events::listener_mapWindow(void* owner, void* data) {
|
||||
CWindow* PWINDOW = (CWindow*)owner;
|
||||
|
||||
static auto *const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue;
|
||||
static auto *const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
|
||||
const auto PWORKSPACE = PMONITOR->specialWorkspaceOpen ? g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
PWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||
@@ -43,6 +46,11 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
|
||||
PWINDOW->m_fAlpha = 255.f;
|
||||
|
||||
if (PWINDOW->m_iX11Type == 2)
|
||||
g_pCompositor->moveUnmanagedX11ToWindows(PWINDOW);
|
||||
|
||||
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
|
||||
|
||||
// Set all windows tiled regardless of anything
|
||||
g_pXWaylandManager->setWindowStyleTiled(PWINDOW, WLR_EDGE_LEFT | WLR_EDGE_RIGHT | WLR_EDGE_TOP | WLR_EDGE_BOTTOM);
|
||||
|
||||
@@ -57,7 +65,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(PWINDOW);
|
||||
|
||||
if (!PWINDOWSURFACE) {
|
||||
g_pCompositor->m_lWindows.remove(*PWINDOW);
|
||||
g_pCompositor->removeWindowFromVectorSafe(PWINDOW);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -97,7 +105,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||
} else {
|
||||
const long int MONITOR = std::stoi(MONITORSTR);
|
||||
if (MONITOR >= (long int)g_pCompositor->m_lMonitors.size() || MONITOR < (long int)0)
|
||||
if (MONITOR >= (long int)g_pCompositor->m_vMonitors.size() || MONITOR < (long int)0)
|
||||
PWINDOW->m_iMonitorID = 0;
|
||||
else
|
||||
PWINDOW->m_iMonitorID = MONITOR;
|
||||
@@ -142,7 +150,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
try {
|
||||
std::string alphaPart = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
||||
|
||||
if (alphaPart.find_first_of(' ') != std::string::npos) {
|
||||
if (alphaPart.contains(' ')) {
|
||||
// we have a comma, 2 values
|
||||
PWINDOW->m_sSpecialRenderData.alpha = std::stof(alphaPart.substr(0, alphaPart.find_first_of(' ')));
|
||||
PWINDOW->m_sSpecialRenderData.alphaInactive = std::stof(alphaPart.substr(alphaPart.find_first_of(' ') + 1));
|
||||
@@ -160,13 +168,17 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
|
||||
if (requestedWorkspace != "") {
|
||||
// process requested workspace
|
||||
if (requestedWorkspace.find_first_of(' ') != std::string::npos) {
|
||||
if (requestedWorkspace.contains(' ')) {
|
||||
// check for silent
|
||||
if (requestedWorkspace.find("silent") != std::string::npos) {
|
||||
if (requestedWorkspace.contains("silent")) {
|
||||
workspaceSilent = true;
|
||||
}
|
||||
|
||||
requestedWorkspace = requestedWorkspace.substr(0, requestedWorkspace.find_first_of(' '));
|
||||
|
||||
if (requestedWorkspace == "special") {
|
||||
workspaceSilent = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!workspaceSilent) {
|
||||
@@ -189,8 +201,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(" "));
|
||||
const auto SIZEYSTR = VALUE.substr(VALUE.find(" ") + 1);
|
||||
|
||||
const auto SIZEX = SIZEXSTR.find('%') == std::string::npos ? std::stoi(SIZEXSTR) : std::stoi(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
|
||||
const auto SIZEY = SIZEYSTR.find('%') == std::string::npos ? std::stoi(SIZEYSTR) : std::stoi(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
|
||||
const auto SIZEX = !SIZEXSTR.contains('%') ? std::stoi(SIZEXSTR) : std::stoi(SIZEXSTR.substr(0, SIZEXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
|
||||
const auto SIZEY = !SIZEYSTR.contains('%') ? std::stoi(SIZEYSTR) : std::stoi(SIZEYSTR.substr(0, SIZEYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
|
||||
|
||||
Debug::log(LOG, "Rule size, applying to window %x", PWINDOW);
|
||||
|
||||
@@ -205,8 +217,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
const auto POSXSTR = VALUE.substr(0, VALUE.find(" "));
|
||||
const auto POSYSTR = VALUE.substr(VALUE.find(" ") + 1);
|
||||
|
||||
const auto POSX = POSXSTR.find('%') == std::string::npos ? std::stoi(POSXSTR) : std::stoi(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
|
||||
const auto POSY = POSYSTR.find('%') == std::string::npos ? std::stoi(POSYSTR) : std::stoi(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
|
||||
const auto POSX = !POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stoi(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.x;
|
||||
const auto POSY = !POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stoi(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01f * PMONITOR->vecSize.y;
|
||||
|
||||
Debug::log(LOG, "Rule move, applying to window %x", PWINDOW);
|
||||
|
||||
@@ -214,6 +226,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
} catch (...) {
|
||||
Debug::log(LOG, "Rule move failed, rule: %s -> %s", r.szRule.c_str(), r.szValue.c_str());
|
||||
}
|
||||
} else if (r.szRule == "center") {
|
||||
PWINDOW->m_vRealPosition = PMONITOR->vecPosition + PMONITOR->vecSize / 2.f - PWINDOW->m_vRealSize.goalv() / 2.f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,8 +242,11 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goalv() - Vector2D(10,10);
|
||||
}
|
||||
|
||||
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus)
|
||||
if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus && PWINDOW->m_iX11Type != 2) {
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA);
|
||||
} else
|
||||
PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PINACTIVEALPHA);
|
||||
|
||||
Debug::log(LOG, "Window got assigned a surfaceTreeNode %x", PWINDOW->m_pSurfaceTree);
|
||||
|
||||
@@ -238,11 +255,18 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.set_title, &Events::listener_setTitleWindow, 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_newPopupXDG.initCallback(&PWINDOW->m_uSurface.xdg->events.new_popup, &Events::listener_newPopupXDG, PWINDOW, "XDG Window Late");
|
||||
PWINDOW->hyprListener_requestMaximize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_maximize, &Events::listener_requestMaximize, PWINDOW, "XDG Window Late");
|
||||
PWINDOW->hyprListener_requestMinimize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_minimize, &Events::listener_requestMinimize, PWINDOW, "XDG Window Late");
|
||||
PWINDOW->hyprListener_requestMove.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_move, &Events::listener_requestMove, PWINDOW, "XDG Window Late");
|
||||
PWINDOW->hyprListener_requestResize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_resize, &Events::listener_requestResize, PWINDOW, "XDG Window Late");
|
||||
} else {
|
||||
PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW, "XWayland Window Late");
|
||||
PWINDOW->hyprListener_activateX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_activate, &Events::listener_activateX11, PWINDOW, "XWayland Window Late");
|
||||
PWINDOW->hyprListener_configureX11.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_configure, &Events::listener_configureX11, PWINDOW, "XWayland Window Late");
|
||||
PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XWayland Window Late");
|
||||
|
||||
if (PWINDOW->m_iX11Type == 2)
|
||||
PWINDOW->hyprListener_setGeometryX11U.initCallback(&PWINDOW->m_uSurface.xwayland->events.set_geometry, &Events::listener_unmanagedSetGeometry, PWINDOW, "XWayland Window Late");
|
||||
}
|
||||
|
||||
// do the animation thing
|
||||
@@ -251,7 +275,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
if (workspaceSilent) {
|
||||
// move the window
|
||||
if (g_pCompositor->m_pLastWindow == PWINDOW) {
|
||||
g_pKeybindManager->m_mDispatchers["movetoworkspacesilent"](requestedWorkspace);
|
||||
if (requestedWorkspace != "special")
|
||||
g_pKeybindManager->m_mDispatchers["movetoworkspacesilent"](requestedWorkspace);
|
||||
else
|
||||
g_pKeybindManager->m_mDispatchers["movetoworkspace"]("special");
|
||||
} else {
|
||||
Debug::log(ERR, "Tried to set workspace silent rule to a nofocus window!");
|
||||
}
|
||||
@@ -265,9 +292,15 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||
g_pXWaylandManager->setWindowFullscreen(PFULLWINDOW, PFULLWINDOW->m_bIsFullscreen);
|
||||
}
|
||||
|
||||
PWINDOW->m_vRealPosition.warp();
|
||||
PWINDOW->m_vRealSize.warp();
|
||||
|
||||
g_pCompositor->setWindowFullscreen(PWINDOW, true, FULLSCREEN_FULL);
|
||||
}
|
||||
|
||||
// recheck idle inhibitors
|
||||
g_pInputManager->recheckIdleInhibitorStatus();
|
||||
|
||||
PWINDOW->m_pSurfaceTree = SubsurfaceTree::createTreeRoot(g_pXWaylandManager->getWindowSurface(PWINDOW), addViewCoords, PWINDOW, PWINDOW);
|
||||
|
||||
Debug::log(LOG, "Map request dispatched, monitor %s, xywh: %f %f %f %f", PMONITOR->szName.c_str(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_vRealSize.goalv().x, PWINDOW->m_vRealSize.goalv().y);
|
||||
@@ -279,17 +312,22 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
Debug::log(LOG, "Window %x unmapped (class %s)", PWINDOW, g_pXWaylandManager->getAppIDClass(PWINDOW).c_str());
|
||||
|
||||
if (!PWINDOW->m_bIsX11) {
|
||||
Debug::log(LOG, "Unregistered late callbacks XDG: %x %x %x %x", &PWINDOW->hyprListener_commitWindow.m_sListener.link, &PWINDOW->hyprListener_setTitleWindow.m_sListener.link, &PWINDOW->hyprListener_fullscreenWindow.m_sListener.link, &PWINDOW->hyprListener_newPopupXDG.m_sListener.link);
|
||||
Debug::log(LOG, "Unregistered late callbacks XDG");
|
||||
PWINDOW->hyprListener_commitWindow.removeCallback();
|
||||
PWINDOW->hyprListener_setTitleWindow.removeCallback();
|
||||
PWINDOW->hyprListener_fullscreenWindow.removeCallback();
|
||||
PWINDOW->hyprListener_newPopupXDG.removeCallback();
|
||||
PWINDOW->hyprListener_requestMaximize.removeCallback();
|
||||
PWINDOW->hyprListener_requestMinimize.removeCallback();
|
||||
PWINDOW->hyprListener_requestMove.removeCallback();
|
||||
PWINDOW->hyprListener_requestResize.removeCallback();
|
||||
} else {
|
||||
Debug::log(LOG, "Unregistered late callbacks XWL: %x %x %x %x", &PWINDOW->hyprListener_fullscreenWindow.m_sListener.link, &PWINDOW->hyprListener_activateX11.m_sListener.link, &PWINDOW->hyprListener_configureX11.m_sListener.link, &PWINDOW->hyprListener_setTitleWindow.m_sListener.link);
|
||||
Debug::log(LOG, "Unregistered late callbacks XWL");
|
||||
PWINDOW->hyprListener_fullscreenWindow.removeCallback();
|
||||
PWINDOW->hyprListener_activateX11.removeCallback();
|
||||
PWINDOW->hyprListener_configureX11.removeCallback();
|
||||
PWINDOW->hyprListener_setTitleWindow.removeCallback();
|
||||
PWINDOW->hyprListener_setGeometryX11U.removeCallback();
|
||||
}
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen) {
|
||||
@@ -330,12 +368,14 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
|
||||
PWINDOW->m_bFadingOut = true;
|
||||
|
||||
g_pCompositor->m_lWindowsFadingOut.push_back(PWINDOW);
|
||||
g_pCompositor->addToFadingOutSafe(PWINDOW);
|
||||
|
||||
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID));
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
|
||||
// do the animation thing
|
||||
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec();
|
||||
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec() - PMONITOR->vecPosition;
|
||||
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec();
|
||||
|
||||
if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in.
|
||||
@@ -345,14 +385,19 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||
// Destroy Foreign Toplevel
|
||||
wlr_foreign_toplevel_handle_v1_destroy(PWINDOW->m_phForeignToplevel);
|
||||
PWINDOW->m_phForeignToplevel = nullptr;
|
||||
|
||||
// recheck idle inhibitors
|
||||
g_pInputManager->recheckIdleInhibitorStatus();
|
||||
}
|
||||
|
||||
void Events::listener_commitWindow(void* owner, void* data) {
|
||||
CWindow* PWINDOW = (CWindow*)owner;
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
if (!PWINDOW->m_bMappedX11 || PWINDOW->m_bHidden || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11))
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->damageSurface(g_pXWaylandManager->getWindowSurface(PWINDOW), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y);
|
||||
|
||||
// Debug::log(LOG, "Window %x committed", PWINDOW); // SPAM!
|
||||
}
|
||||
|
||||
@@ -393,7 +438,7 @@ void Events::listener_setTitleWindow(void* owner, void* data) {
|
||||
PWINDOW->m_szTitle = g_pXWaylandManager->getTitle(PWINDOW);
|
||||
|
||||
if (PWINDOW == g_pCompositor->m_pLastWindow) // if it's the active, let's post an event to update others
|
||||
g_pEventManager->postEvent(SHyprIPCEvent("activewindow", g_pXWaylandManager->getAppIDClass(PWINDOW) + "," + PWINDOW->m_szTitle));
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", g_pXWaylandManager->getAppIDClass(PWINDOW) + "," + PWINDOW->m_szTitle});
|
||||
|
||||
if (PWINDOW->m_phForeignToplevel)
|
||||
wlr_foreign_toplevel_handle_v1_set_title(PWINDOW->m_phForeignToplevel, PWINDOW->m_szTitle.c_str());
|
||||
@@ -409,6 +454,8 @@ void Events::listener_fullscreenWindow(void* owner, void* data) {
|
||||
|
||||
if (REQUESTED->fullscreen != PWINDOW->m_bIsFullscreen)
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, REQUESTED->fullscreen);
|
||||
|
||||
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
|
||||
} else {
|
||||
g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(PWINDOW, FULLSCREEN_FULL, !PWINDOW->m_bIsFullscreen);
|
||||
}
|
||||
@@ -458,6 +505,8 @@ void Events::listener_configureX11(void* owner, void* data) {
|
||||
|
||||
wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height);
|
||||
|
||||
PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.vec() + PWINDOW->m_vRealSize.vec() / 2.f)->activeWorkspace;
|
||||
|
||||
g_pCompositor->moveWindowToTop(PWINDOW);
|
||||
|
||||
PWINDOW->m_bCreatedOverFullscreen = true;
|
||||
@@ -467,6 +516,32 @@ void Events::listener_configureX11(void* owner, void* data) {
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
}
|
||||
|
||||
void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
|
||||
CWindow* PWINDOW = (CWindow*)owner;
|
||||
|
||||
if (!PWINDOW->m_bMappedX11 || PWINDOW->m_bHidden)
|
||||
return;
|
||||
|
||||
const auto POS = PWINDOW->m_vRealPosition.goalv();
|
||||
const auto SIZ = PWINDOW->m_vRealSize.goalv();
|
||||
|
||||
if (abs(std::floor(POS.x) - PWINDOW->m_uSurface.xwayland->x) > 2 || abs(std::floor(POS.y) - PWINDOW->m_uSurface.xwayland->y) > 2 || abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2) {
|
||||
Debug::log(LOG, "Unmanaged window %x requests geometry update to %i %i %i %i", PWINDOW, (int)PWINDOW->m_uSurface.xwayland->x, (int)PWINDOW->m_uSurface.xwayland->y, (int)PWINDOW->m_uSurface.xwayland->width, (int)PWINDOW->m_uSurface.xwayland->height);
|
||||
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
PWINDOW->m_vRealPosition.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y));
|
||||
|
||||
if (abs(std::floor(SIZ.x) - PWINDOW->m_uSurface.xwayland->width) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_uSurface.xwayland->height) > 2)
|
||||
PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->width, PWINDOW->m_uSurface.xwayland->height));
|
||||
|
||||
PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.vec() + PWINDOW->m_vRealSize.vec() / 2.f)->activeWorkspace;
|
||||
|
||||
g_pCompositor->moveWindowToTop(PWINDOW);
|
||||
PWINDOW->updateWindowDecos();
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
}
|
||||
}
|
||||
|
||||
void Events::listener_surfaceXWayland(wl_listener* listener, void* data) {
|
||||
const auto XWSURFACE = (wlr_xwayland_surface*)data;
|
||||
|
||||
@@ -474,13 +549,14 @@ void Events::listener_surfaceXWayland(wl_listener* listener, void* data) {
|
||||
if (XWSURFACE->parent)
|
||||
Debug::log(LOG, "Window parent data: %s at %x", XWSURFACE->parent->_class, XWSURFACE->parent);
|
||||
|
||||
g_pCompositor->m_lWindows.emplace_back();
|
||||
const auto PNEWWINDOW = &g_pCompositor->m_lWindows.back();
|
||||
const auto PNEWWINDOW = XWSURFACE->override_redirect ? g_pCompositor->m_dUnmanagedX11Windows.emplace_back(std::make_unique<CWindow>()).get() : g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
|
||||
|
||||
PNEWWINDOW->m_uSurface.xwayland = XWSURFACE;
|
||||
PNEWWINDOW->m_iX11Type = XWSURFACE->override_redirect ? 2 : 1;
|
||||
PNEWWINDOW->m_bIsX11 = true;
|
||||
|
||||
PNEWWINDOW->m_pX11Parent = g_pCompositor->getX11Parent(PNEWWINDOW);
|
||||
|
||||
PNEWWINDOW->hyprListener_mapWindow.initCallback(&XWSURFACE->events.map, &Events::listener_mapWindow, PNEWWINDOW, "XWayland Window");
|
||||
PNEWWINDOW->hyprListener_unmapWindow.initCallback(&XWSURFACE->events.unmap, &Events::listener_unmapWindow, PNEWWINDOW, "XWayland Window");
|
||||
PNEWWINDOW->hyprListener_destroyWindow.initCallback(&XWSURFACE->events.destroy, &Events::listener_destroyWindow, PNEWWINDOW, "XWayland Window");
|
||||
@@ -495,8 +571,7 @@ void Events::listener_newXDGSurface(wl_listener* listener, void* data) {
|
||||
if (XDGSURFACE->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL)
|
||||
return; // TODO: handle?
|
||||
|
||||
g_pCompositor->m_lWindows.emplace_back();
|
||||
const auto PNEWWINDOW = &g_pCompositor->m_lWindows.back();
|
||||
const auto PNEWWINDOW = g_pCompositor->m_vWindows.emplace_back(std::make_unique<CWindow>()).get();
|
||||
PNEWWINDOW->m_uSurface.xdg = XDGSURFACE;
|
||||
|
||||
PNEWWINDOW->hyprListener_mapWindow.initCallback(&XDGSURFACE->events.map, &Events::listener_mapWindow, PNEWWINDOW, "XDG Window");
|
||||
@@ -508,3 +583,28 @@ void Events::listener_NewXDGDeco(wl_listener* listener, void* data) {
|
||||
const auto WLRDECO = (wlr_xdg_toplevel_decoration_v1*)data;
|
||||
wlr_xdg_toplevel_decoration_v1_set_mode(WLRDECO, WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
||||
}
|
||||
|
||||
void Events::listener_requestMaximize(void* owner, void* data) {
|
||||
const auto PWINDOW = (CWindow*)owner;
|
||||
|
||||
// ignore
|
||||
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
|
||||
}
|
||||
|
||||
void Events::listener_requestMinimize(void* owner, void* data) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
void Events::listener_requestMove(void* owner, void* data) {
|
||||
const auto PWINDOW = (CWindow*)owner;
|
||||
|
||||
// ignore
|
||||
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
|
||||
}
|
||||
|
||||
void Events::listener_requestResize(void* owner, void* data) {
|
||||
const auto PWINDOW = (CWindow*)owner;
|
||||
|
||||
// ignore
|
||||
wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg);
|
||||
}
|
@@ -13,7 +13,8 @@ enum ANIMATEDVARTYPE {
|
||||
enum AVARDAMAGEPOLICY {
|
||||
AVARDAMAGE_INVALID = -1,
|
||||
AVARDAMAGE_ENTIRE = 0,
|
||||
AVARDAMAGE_BORDER
|
||||
AVARDAMAGE_BORDER,
|
||||
AVARDAMAGE_SHADOW
|
||||
};
|
||||
|
||||
class CAnimationManager;
|
||||
@@ -33,56 +34,47 @@ public:
|
||||
|
||||
// gets the current vector value (real time)
|
||||
const Vector2D& vec() const {
|
||||
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access vec() of AVARTYPE %i!", m_eVarType);
|
||||
return m_vValue;
|
||||
}
|
||||
|
||||
// gets the current float value (real time)
|
||||
const float& fl() const {
|
||||
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access fl() of AVARTYPE %i!", m_eVarType);
|
||||
return m_fValue;
|
||||
}
|
||||
|
||||
// gets the current color value (real time)
|
||||
const CColor& col() const {
|
||||
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access col() of AVARTYPE %i!", m_eVarType);
|
||||
return m_cValue;
|
||||
}
|
||||
|
||||
// gets the goal vector value
|
||||
const Vector2D& goalv() const {
|
||||
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access goalv() of AVARTYPE %i!", m_eVarType);
|
||||
return m_vGoal;
|
||||
}
|
||||
|
||||
// gets the goal float value
|
||||
const float& goalf() const {
|
||||
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access goalf() of AVARTYPE %i!", m_eVarType);
|
||||
return m_fGoal;
|
||||
}
|
||||
|
||||
// gets the goal color value
|
||||
const CColor& goalc() const {
|
||||
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access goalc() of AVARTYPE %i!", m_eVarType);
|
||||
return m_cGoal;
|
||||
}
|
||||
|
||||
void operator=(const Vector2D& v) {
|
||||
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access =v of AVARTYPE %i!", m_eVarType);
|
||||
m_vGoal = v;
|
||||
animationBegin = std::chrono::system_clock::now();
|
||||
m_vBegun = m_vValue;
|
||||
}
|
||||
|
||||
void operator=(const float& v) {
|
||||
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access =f of AVARTYPE %i!", m_eVarType);
|
||||
m_fGoal = v;
|
||||
animationBegin = std::chrono::system_clock::now();
|
||||
m_fBegun = m_fValue;
|
||||
}
|
||||
|
||||
void operator=(const CColor& v) {
|
||||
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access =c of AVARTYPE %i!", m_eVarType);
|
||||
m_cGoal = v;
|
||||
animationBegin = std::chrono::system_clock::now();
|
||||
m_cBegun = m_cValue;
|
||||
@@ -90,7 +82,6 @@ public:
|
||||
|
||||
// Sets the actual stored value, without affecting the goal, but resets the timer
|
||||
void setValue(const Vector2D& v) {
|
||||
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access setValue(v) of AVARTYPE %i!", m_eVarType);
|
||||
m_vValue = v;
|
||||
animationBegin = std::chrono::system_clock::now();
|
||||
m_vBegun = m_vValue;
|
||||
@@ -98,7 +89,6 @@ public:
|
||||
|
||||
// Sets the actual stored value, without affecting the goal, but resets the timer
|
||||
void setValue(const float& v) {
|
||||
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access setValue(f) of AVARTYPE %i!", m_eVarType);
|
||||
m_fValue = v;
|
||||
animationBegin = std::chrono::system_clock::now();
|
||||
m_vBegun = m_vValue;
|
||||
@@ -106,7 +96,6 @@ public:
|
||||
|
||||
// Sets the actual stored value, without affecting the goal, but resets the timer
|
||||
void setValue(const CColor& v) {
|
||||
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access setValue(c) of AVARTYPE %i!", m_eVarType);
|
||||
m_cValue = v;
|
||||
animationBegin = std::chrono::system_clock::now();
|
||||
m_vBegun = m_vValue;
|
||||
@@ -114,21 +103,18 @@ public:
|
||||
|
||||
// Sets the actual value and goal
|
||||
void setValueAndWarp(const Vector2D& v) {
|
||||
RASSERT(m_eVarType == AVARTYPE_VECTOR, "Tried to access setValueAndWarp(v) of AVARTYPE %i!", m_eVarType);
|
||||
m_vGoal = v;
|
||||
warp();
|
||||
}
|
||||
|
||||
// Sets the actual value and goal
|
||||
void setValueAndWarp(const float& v) {
|
||||
RASSERT(m_eVarType == AVARTYPE_FLOAT, "Tried to access setValueAndWarp(f) of AVARTYPE %i!", m_eVarType);
|
||||
m_fGoal = v;
|
||||
warp();
|
||||
}
|
||||
|
||||
// Sets the actual value and goal
|
||||
void setValueAndWarp(const CColor& v) {
|
||||
RASSERT(m_eVarType == AVARTYPE_COLOR, "Tried to access setValueAndWarp(c) of AVARTYPE %i!", m_eVarType);
|
||||
m_cGoal = v;
|
||||
warp();
|
||||
}
|
||||
@@ -143,10 +129,12 @@ public:
|
||||
case AVARTYPE_COLOR:
|
||||
return m_cValue != m_cGoal;
|
||||
default:
|
||||
return false;
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
return false; // unreachable
|
||||
UNREACHABLE();
|
||||
|
||||
return false; // just so that the warning is suppressed
|
||||
}
|
||||
|
||||
void warp() {
|
||||
@@ -164,7 +152,7 @@ public:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,7 @@
|
||||
#include <algorithm>
|
||||
#include "../Compositor.hpp"
|
||||
#include <sys/utsname.h>
|
||||
#include <iomanip>
|
||||
|
||||
static const float transforms[][9] = {{
|
||||
1.0f, 0.0f, 0.0f,
|
||||
@@ -82,40 +83,45 @@ void wlr_signal_emit_safe(struct wl_signal *signal, void *data) {
|
||||
}
|
||||
|
||||
std::string getFormat(const char *fmt, ...) {
|
||||
char buf[LOGMESSAGESIZE] = "";
|
||||
char* outputStr;
|
||||
int logLen;
|
||||
char* outputStr = nullptr;
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
logLen = vsnprintf(buf, sizeof buf, fmt, args);
|
||||
vasprintf(&outputStr, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if ((long unsigned int)logLen < sizeof buf) {
|
||||
outputStr = strdup(buf);
|
||||
} else {
|
||||
outputStr = (char*)malloc(logLen + 1);
|
||||
|
||||
if (!outputStr) {
|
||||
printf("CRITICAL: Cannot alloc size %d for log! (Out of memory?)", logLen + 1);
|
||||
return "";
|
||||
}
|
||||
|
||||
va_start(args, fmt);
|
||||
vsnprintf(outputStr, logLen + 1U, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
std::string output = std::string(outputStr);
|
||||
|
||||
free(outputStr);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
std::string escapeJSONStrings(const std::string& str) {
|
||||
std::ostringstream oss;
|
||||
for (auto &c : str) {
|
||||
switch (c) {
|
||||
case '"': oss << "\\\""; break;
|
||||
case '\\': oss << "\\\\"; break;
|
||||
case '\b': oss << "\\b"; break;
|
||||
case '\f': oss << "\\f"; break;
|
||||
case '\n': oss << "\\n"; break;
|
||||
case '\r': oss << "\\r"; break;
|
||||
case '\t': oss << "\\t"; break;
|
||||
default:
|
||||
if ('\x00' <= c && c <= '\x1f') {
|
||||
oss << "\\u"
|
||||
<< std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(c);
|
||||
} else {
|
||||
oss << c;
|
||||
}
|
||||
}
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
void scaleBox(wlr_box* box, float scale) {
|
||||
box->width = std::round((box->x + box->width) * scale) - std::round(box->x * scale);
|
||||
box->height = std::round((box->y + box->height) * scale) - std::round(box->y * 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);
|
||||
}
|
||||
@@ -137,7 +143,7 @@ float getPlusMinusKeywordResult(std::string source, float relative) {
|
||||
|
||||
if (source.find_first_of("+") == 0) {
|
||||
try {
|
||||
if (source.find('.') != std::string::npos)
|
||||
if (source.contains("."))
|
||||
result = relative + std::stof(source.substr(1));
|
||||
else
|
||||
result = relative + std::stoi(source.substr(1));
|
||||
@@ -147,7 +153,7 @@ float getPlusMinusKeywordResult(std::string source, float relative) {
|
||||
}
|
||||
} else if (source.find_first_of("-") == 0) {
|
||||
try {
|
||||
if (source.find('.') != std::string::npos)
|
||||
if (source.contains("."))
|
||||
result = relative - std::stof(source.substr(1));
|
||||
else
|
||||
result = relative - std::stoi(source.substr(1));
|
||||
@@ -157,7 +163,7 @@ float getPlusMinusKeywordResult(std::string source, float relative) {
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (source.find('.') != std::string::npos)
|
||||
if (source.contains("."))
|
||||
result = stof(source);
|
||||
else
|
||||
result = stoi(source);
|
||||
@@ -193,7 +199,9 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
}
|
||||
outName = WORKSPACENAME;
|
||||
} else {
|
||||
if (in[0] == 'm') {
|
||||
if (in[0] == 'm' || in[0] == 'e') {
|
||||
bool onAllMonitors = in[0] == 'e';
|
||||
|
||||
if (!g_pCompositor->m_pLastMonitor) {
|
||||
Debug::log(ERR, "Relative monitor workspace on monitor null!");
|
||||
result = INT_MAX;
|
||||
@@ -219,12 +227,12 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
int lowestID = 99999;
|
||||
int highestID = -99999;
|
||||
|
||||
for (auto& w : g_pCompositor->m_lWorkspaces) {
|
||||
if (w.m_iID < lowestID)
|
||||
lowestID = w.m_iID;
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (w->m_iID < lowestID)
|
||||
lowestID = w->m_iID;
|
||||
|
||||
if (w.m_iID > highestID)
|
||||
highestID = w.m_iID;
|
||||
if (w->m_iID > highestID)
|
||||
highestID = w->m_iID;
|
||||
}
|
||||
|
||||
if (remains < 0)
|
||||
@@ -234,7 +242,7 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) {
|
||||
}
|
||||
|
||||
if (const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(searchID); PWORKSPACE && PWORKSPACE->m_iID != SPECIAL_WORKSPACE_ID) {
|
||||
if (PWORKSPACE->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) {
|
||||
if (onAllMonitors || PWORKSPACE->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) {
|
||||
currentID = PWORKSPACE->m_iID;
|
||||
|
||||
if (remains < 0)
|
||||
|
@@ -5,6 +5,7 @@
|
||||
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, std::string ownerString);
|
||||
void wlr_signal_emit_safe(struct wl_signal *signal, void *data);
|
||||
std::string getFormat(const char *fmt, ...); // Basically Debug::log to a string
|
||||
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);
|
||||
|
@@ -3,8 +3,9 @@
|
||||
#include "../defines.hpp"
|
||||
#include <deque>
|
||||
#include "WLClasses.hpp"
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
struct SMonitor {
|
||||
Vector2D vecPosition = Vector2D(0,0);
|
||||
@@ -30,6 +31,7 @@ struct SMonitor {
|
||||
int framesToSkip = 0;
|
||||
int forceFullFrames = 0;
|
||||
bool noFrameSchedule = false;
|
||||
bool scheduledRecalc = false;
|
||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||
|
||||
// for the special workspace
|
||||
@@ -38,7 +40,7 @@ struct SMonitor {
|
||||
// Double-linked list because we need to have constant mem addresses for signals
|
||||
// We have to store pointers and use raw new/delete because they might be moved between them
|
||||
// and I am lazy
|
||||
std::array<std::list<SLayerSurface*>, 4> m_aLayerSurfaceLists;
|
||||
std::array<std::vector<std::unique_ptr<SLayerSurface>>, 4> m_aLayerSurfaceLists;
|
||||
|
||||
DYNLISTENER(monitorFrame);
|
||||
DYNLISTENER(monitorDestroy);
|
||||
|
56
src/helpers/Splashes.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
inline const std::vector<std::string> SPLASHES = {
|
||||
"Woo, animations!",
|
||||
"It's like Hypr, but better.",
|
||||
"Release 1.0 when?",
|
||||
"It's not awesome, it's Hyprland!",
|
||||
"\"I commit too often, people can't catch up lmao\" - Vaxry",
|
||||
"This text is random.",
|
||||
"\"There are reasons to not use rust.\" - Boga",
|
||||
"Read the wiki.",
|
||||
"\"Hello everyone this is YOUR daily dose of ‘read the wiki’\" - Vaxry",
|
||||
"h",
|
||||
"\"‘why no work’, bro I haven't hacked your pc to get live feeds yet\" - Vaxry",
|
||||
"Compile, wait for 20 minutes, notice a new commit, compile again.",
|
||||
"To rice, or not to rice, that is the question.",
|
||||
"Now available on Fedora!",
|
||||
// music reference / quote section
|
||||
"J'remue le ciel, le jour, la nuit.",
|
||||
"aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi, aezakmi!",
|
||||
"Wir sind schon sehr lang zusammen...",
|
||||
"I see a red door and I want it painted black.",
|
||||
"Take on me, take me on...",
|
||||
"You spin me right round baby right round",
|
||||
"Stayin' alive, stayin' alive",
|
||||
"Say no way, say no way ya, no way!",
|
||||
"Ground control to Major Tom...",
|
||||
"Alors on danse",
|
||||
"And all that I can see, is just a yellow lemon tree.",
|
||||
"Got a one-way ticket to the blues",
|
||||
"Is this the real life, is this just fantasy",
|
||||
"What's in your head, in your head?",
|
||||
"We're all living in America, America, America.",
|
||||
"I'm still standing, better than I ever did",
|
||||
"Here comes the sun, bringing you love and shining on everyone",
|
||||
"Two trailer park girls go round the outside",
|
||||
"With the lights out, it's less dangerous",
|
||||
"Here we go back, this is the moment, tonight is the night",
|
||||
"Now you're just somebody that I used to know...",
|
||||
"Black bird, black moon, black sky",
|
||||
"Some legends are told, some turn to dust or to gold",
|
||||
"Your brain gets smart, but your head gets dumb.",
|
||||
"Save your mercy for someone who needs it more",
|
||||
"You're gonna hear my voice when I shout it out loud",
|
||||
"Ding ding pch n daa, bam-ba-ba-re-bam baram bom bom baba-bam-bam-bommm",
|
||||
"Súbeme la radio que esta es mi canción",
|
||||
"I'm beggin', beggin' you",
|
||||
//
|
||||
"Join the discord server!",
|
||||
"Thanks ThatOneCalculator!",
|
||||
"The AUR packages always work, except for the times they don't.",
|
||||
"Funny animation compositor woo"
|
||||
};
|
@@ -21,9 +21,7 @@ void addSurfaceGlobalOffset(SSurfaceTreeNode* node, int* lx, int* ly) {
|
||||
}
|
||||
|
||||
SSurfaceTreeNode* createTree(wlr_surface* pSurface, CWindow* pWindow) {
|
||||
SubsurfaceTree::surfaceTreeNodes.push_back(SSurfaceTreeNode());
|
||||
|
||||
const auto PNODE = &SubsurfaceTree::surfaceTreeNodes.back();
|
||||
const auto PNODE = &SubsurfaceTree::surfaceTreeNodes.emplace_back();
|
||||
|
||||
PNODE->pSurface = pSurface;
|
||||
PNODE->pWindowOwner = pWindow;
|
||||
@@ -128,8 +126,7 @@ void Events::listener_newSubsurfaceNode(void* owner, void* data) {
|
||||
|
||||
const auto PSUBSURFACE = (wlr_subsurface*)data;
|
||||
|
||||
pNode->childSubsurfaces.push_back(SSubsurface());
|
||||
const auto PNEWSUBSURFACE = &pNode->childSubsurfaces.back();
|
||||
const auto PNEWSUBSURFACE = &pNode->childSubsurfaces.emplace_back();
|
||||
|
||||
Debug::log(LOG, "Added a new subsurface %x", PSUBSURFACE);
|
||||
|
||||
@@ -171,12 +168,14 @@ void Events::listener_unmapSubsurface(void* owner, void* data) {
|
||||
addSurfaceGlobalOffset(PNODE, &lx, &ly);
|
||||
|
||||
wlr_box extents = {0};
|
||||
wlr_surface_get_extends(PNODE->pSurface, &extents);
|
||||
if (PNODE->pSurface) {
|
||||
wlr_surface_get_extends(PNODE->pSurface, &extents);
|
||||
|
||||
extents.x += lx;
|
||||
extents.y += ly;
|
||||
extents.x += lx;
|
||||
extents.y += ly;
|
||||
|
||||
g_pHyprRenderer->damageBox(&extents);
|
||||
g_pHyprRenderer->damageBox(&extents);
|
||||
}
|
||||
|
||||
SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
|
||||
subsurface->pChild = nullptr;
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include "Vector2D.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
Vector2D::Vector2D(double xx, double yy) {
|
||||
x = xx;
|
||||
@@ -20,4 +21,11 @@ double Vector2D::normalize() {
|
||||
|
||||
Vector2D Vector2D::floor() {
|
||||
return Vector2D((int)x, (int)y);
|
||||
}
|
||||
|
||||
Vector2D Vector2D::clamp(const Vector2D& min, const Vector2D& max) {
|
||||
return Vector2D(
|
||||
std::clamp(this->x, min.x, max.x == 0 ? INFINITY : max.x),
|
||||
std::clamp(this->y, min.y, max.y == 0 ? INFINITY : max.y)
|
||||
);
|
||||
}
|
@@ -35,5 +35,7 @@ class Vector2D {
|
||||
return a.x != x || a.y != y;
|
||||
}
|
||||
|
||||
Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D());
|
||||
|
||||
Vector2D floor();
|
||||
};
|
@@ -19,15 +19,22 @@ struct SLayerSurface {
|
||||
DYNLISTENER(commitLayerSurface);
|
||||
DYNLISTENER(newPopup);
|
||||
|
||||
wlr_box geometry;
|
||||
wlr_box geometry = {0,0,0,0};
|
||||
Vector2D position;
|
||||
zwlr_layer_shell_v1_layer layer;
|
||||
|
||||
bool mapped = false;
|
||||
|
||||
int monitorID = -1;
|
||||
|
||||
std::string szNamespace = "";
|
||||
|
||||
CAnimatedVariable alpha;
|
||||
bool fadingOut = false;
|
||||
bool readyToDelete = false;
|
||||
bool noProcess = false;
|
||||
|
||||
bool forceBlur = false;
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const SLayerSurface& rhs) {
|
||||
@@ -60,6 +67,26 @@ struct SRenderData {
|
||||
|
||||
// for custom round values
|
||||
int rounding = -1; // -1 means not set
|
||||
|
||||
// for blurring
|
||||
bool blur = false;
|
||||
|
||||
// only for windows, not popups
|
||||
bool squishOversized = true;
|
||||
};
|
||||
|
||||
struct SExtensionFindingData {
|
||||
Vector2D origin;
|
||||
Vector2D vec;
|
||||
wlr_surface** found;
|
||||
};
|
||||
|
||||
struct SStringRuleNames {
|
||||
std::string layout = "";
|
||||
std::string model = "";
|
||||
std::string variant = "";
|
||||
std::string options = "";
|
||||
std::string rules = "";
|
||||
};
|
||||
|
||||
struct SKeyboard {
|
||||
@@ -71,7 +98,12 @@ struct SKeyboard {
|
||||
|
||||
bool active = false;
|
||||
|
||||
xkb_rule_names currentRules = {0};
|
||||
std::string name = "";
|
||||
|
||||
SStringRuleNames currentRules;
|
||||
int repeatRate = 0;
|
||||
int repeatDelay = 0;
|
||||
int numlockOn = -1;
|
||||
|
||||
// For the list lookup
|
||||
bool operator==(const SKeyboard& rhs) {
|
||||
@@ -87,6 +119,10 @@ struct SMouse {
|
||||
|
||||
pixman_region32_t confinedTo;
|
||||
|
||||
std::string name = "";
|
||||
|
||||
bool virt = false;
|
||||
|
||||
DYNLISTENER(commitConstraint);
|
||||
DYNLISTENER(destroyMouse);
|
||||
|
||||
@@ -168,6 +204,8 @@ struct STablet {
|
||||
wlr_tablet_v2_tablet* wlrTabletV2 = nullptr;
|
||||
wlr_input_device* wlrDevice = nullptr;
|
||||
|
||||
std::string name = "";
|
||||
|
||||
bool operator==(const STablet& b) {
|
||||
return wlrDevice == b.wlrDevice;
|
||||
}
|
||||
@@ -186,6 +224,8 @@ struct STabletTool {
|
||||
|
||||
bool active = true;
|
||||
|
||||
std::string name = "";
|
||||
|
||||
DYNLISTENER(TabletToolDestroy);
|
||||
DYNLISTENER(TabletToolSetCursor);
|
||||
|
||||
@@ -198,6 +238,8 @@ struct STabletPad {
|
||||
wlr_tablet_v2_tablet_pad* wlrTabletPadV2 = nullptr;
|
||||
STablet* pTabletParent = nullptr;
|
||||
|
||||
std::string name = "";
|
||||
|
||||
DYNLISTENER(Attach);
|
||||
DYNLISTENER(Button);
|
||||
DYNLISTENER(Strip);
|
||||
@@ -208,3 +250,25 @@ struct STabletPad {
|
||||
return wlrTabletPadV2 == b.wlrTabletPadV2;
|
||||
}
|
||||
};
|
||||
|
||||
struct SIdleInhibitor {
|
||||
wlr_idle_inhibitor_v1* pWlrInhibitor = nullptr;
|
||||
CWindow* pWindow = nullptr;
|
||||
|
||||
DYNLISTENER(Destroy);
|
||||
|
||||
bool operator==(const SIdleInhibitor& b) {
|
||||
return pWlrInhibitor == b.pWlrInhibitor;
|
||||
}
|
||||
};
|
||||
|
||||
struct SSwipeGesture {
|
||||
CWorkspace* pWorkspaceBegin = nullptr;
|
||||
|
||||
double delta = 0;
|
||||
|
||||
float avgSpeed = 0;
|
||||
int speedPoints = 0;
|
||||
|
||||
SMonitor* pMonitor = nullptr;
|
||||
};
|
@@ -4,9 +4,9 @@
|
||||
#include "../debug/Log.hpp"
|
||||
|
||||
void handleWrapped(wl_listener* listener, void* data) {
|
||||
CHyprWLListener* pListener = wl_container_of(listener, pListener, m_sListener);
|
||||
CHyprWLListener::SWrapper* pWrap = wl_container_of(listener, pWrap, m_sListener);
|
||||
|
||||
pListener->emit(data);
|
||||
pWrap->m_pSelf->emit(data);
|
||||
}
|
||||
|
||||
CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function<void(void*, void*)> callback, void* pOwner) {
|
||||
@@ -14,7 +14,9 @@ CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function<void(void*, v
|
||||
}
|
||||
|
||||
CHyprWLListener::CHyprWLListener() {
|
||||
; //
|
||||
m_swWrapper.m_pSelf = this;
|
||||
m_swWrapper.m_sListener.notify = &handleWrapped;
|
||||
wl_list_init(&m_swWrapper.m_sListener.link);
|
||||
}
|
||||
|
||||
CHyprWLListener::~CHyprWLListener() {
|
||||
@@ -22,31 +24,28 @@ CHyprWLListener::~CHyprWLListener() {
|
||||
}
|
||||
|
||||
void CHyprWLListener::removeCallback() {
|
||||
if (m_bIsConnected) {
|
||||
Debug::log(LOG, "Callback %x -> %x, %s removed.", m_pCallback, m_pOwner, m_szAuthor.c_str());
|
||||
wl_list_remove(&m_sListener.link);
|
||||
if (isConnected()) {
|
||||
Debug::log(LOG, "Callback %x -> %x, %s removed.", &m_pCallback, &m_pOwner, m_szAuthor.c_str());
|
||||
wl_list_remove(&m_swWrapper.m_sListener.link);
|
||||
wl_list_init(&m_swWrapper.m_sListener.link);
|
||||
}
|
||||
|
||||
m_bIsConnected = false;
|
||||
}
|
||||
|
||||
bool CHyprWLListener::isConnected() {
|
||||
return m_bIsConnected;
|
||||
return !wl_list_empty(&m_swWrapper.m_sListener.link);
|
||||
}
|
||||
|
||||
void CHyprWLListener::initCallback(wl_signal* pSignal, std::function<void(void*, void*)> callback, void* pOwner, std::string author) {
|
||||
if (m_bIsConnected)
|
||||
removeCallback();
|
||||
if (isConnected()) {
|
||||
Debug::log(ERR, "Tried to connect a listener twice?!");
|
||||
return;
|
||||
}
|
||||
|
||||
m_pOwner = pOwner;
|
||||
m_pCallback = callback;
|
||||
m_szAuthor = author;
|
||||
|
||||
m_sListener.notify = &handleWrapped;
|
||||
|
||||
m_bIsConnected = true;
|
||||
|
||||
addWLSignal(pSignal, &m_sListener, pOwner, m_szAuthor);
|
||||
addWLSignal(pSignal, &m_swWrapper.m_sListener, pOwner, m_szAuthor);
|
||||
}
|
||||
|
||||
void CHyprWLListener::emit(void* data) {
|
||||
|
@@ -9,18 +9,26 @@ public:
|
||||
CHyprWLListener();
|
||||
~CHyprWLListener();
|
||||
|
||||
CHyprWLListener(const CHyprWLListener&) = delete;
|
||||
CHyprWLListener(CHyprWLListener&&) = delete;
|
||||
CHyprWLListener& operator=(const CHyprWLListener&) = delete;
|
||||
CHyprWLListener& operator=(CHyprWLListener&&) = delete;
|
||||
|
||||
void initCallback(wl_signal*, std::function<void(void*, void*)>, void* owner, std::string author = "");
|
||||
|
||||
void removeCallback();
|
||||
|
||||
bool isConnected();
|
||||
|
||||
wl_listener m_sListener;
|
||||
struct SWrapper {
|
||||
wl_listener m_sListener;
|
||||
CHyprWLListener* m_pSelf;
|
||||
};
|
||||
|
||||
void emit(void*);
|
||||
|
||||
private:
|
||||
bool m_bIsConnected = false;
|
||||
SWrapper m_swWrapper;
|
||||
|
||||
void* m_pOwner = nullptr;
|
||||
|
||||
|
@@ -31,7 +31,7 @@ CWorkspace::CWorkspace(int monitorID, std::string name, bool special) {
|
||||
m_fAlpha.create(AVARTYPE_FLOAT, &g_pConfigManager->getConfigValuePtr("animations:workspaces_speed")->floatValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces")->intValue, &g_pConfigManager->getConfigValuePtr("animations:workspaces_curve")->strValue, nullptr, AVARDAMAGE_ENTIRE);
|
||||
m_fAlpha.setValueAndWarp(255.f);
|
||||
|
||||
g_pEventManager->postEvent({"createworkspace", m_szName});
|
||||
g_pEventManager->postEvent({"createworkspace", m_szName}, true);
|
||||
}
|
||||
|
||||
CWorkspace::~CWorkspace() {
|
||||
@@ -45,7 +45,7 @@ CWorkspace::~CWorkspace() {
|
||||
m_pWlrHandle = nullptr;
|
||||
}
|
||||
|
||||
g_pEventManager->postEvent({"destroyworkspace", m_szName});
|
||||
g_pEventManager->postEvent({"destroyworkspace", m_szName}, true);
|
||||
}
|
||||
|
||||
void CWorkspace::startAnim(bool in, bool left, bool instant) {
|
||||
|
@@ -28,6 +28,7 @@ public:
|
||||
// for animations
|
||||
CAnimatedVariable m_vRenderOffset;
|
||||
CAnimatedVariable m_fAlpha;
|
||||
bool m_bForceRendering = false;
|
||||
|
||||
// "scratchpad"
|
||||
bool m_bIsSpecialWorkspace = false;
|
||||
|
@@ -12,9 +12,9 @@ void CHyprError::createQueued() {
|
||||
m_tTexture.destroyTexture();
|
||||
}
|
||||
|
||||
const auto PMONITOR = &g_pCompositor->m_lMonitors.front();
|
||||
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
|
||||
|
||||
const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecSize.x, PMONITOR->vecSize.y);
|
||||
const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||
|
||||
const auto CAIRO = cairo_create(CAIROSURFACE);
|
||||
|
||||
@@ -27,12 +27,12 @@ void CHyprError::createQueued() {
|
||||
const auto LINECOUNT = 1 + std::count(m_szQueued.begin(), m_szQueued.end(), '\n');
|
||||
|
||||
cairo_set_source_rgba(CAIRO, m_cQueued.r / 255.f, m_cQueued.g / 255.f, m_cQueued.b / 255.f, m_cQueued.a / 255.f);
|
||||
cairo_rectangle(CAIRO, 0, 0, PMONITOR->vecSize.x, 10 * LINECOUNT);
|
||||
cairo_rectangle(CAIRO, 0, 0, PMONITOR->vecPixelSize.x, 10 * LINECOUNT);
|
||||
|
||||
// outline
|
||||
cairo_rectangle(CAIRO, 0, 0, 1, PMONITOR->vecSize.y); // left
|
||||
cairo_rectangle(CAIRO, PMONITOR->vecSize.x - 1, 0, PMONITOR->vecSize.x, PMONITOR->vecSize.y); // right
|
||||
cairo_rectangle(CAIRO, 0, PMONITOR->vecSize.y - 1, PMONITOR->vecSize.x, PMONITOR->vecSize.y); // bottom
|
||||
cairo_rectangle(CAIRO, 0, 0, 1, PMONITOR->vecPixelSize.y); // left
|
||||
cairo_rectangle(CAIRO, PMONITOR->vecPixelSize.x - 1, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); // right
|
||||
cairo_rectangle(CAIRO, 0, PMONITOR->vecPixelSize.y - 1, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); // bottom
|
||||
|
||||
cairo_fill(CAIRO);
|
||||
|
||||
@@ -70,7 +70,7 @@ void CHyprError::createQueued() {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
||||
#endif
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecSize.x, PMONITOR->vecSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
||||
|
||||
// delete cairo
|
||||
cairo_destroy(CAIRO);
|
||||
@@ -95,16 +95,16 @@ void CHyprError::draw() {
|
||||
m_tTexture.destroyTexture();
|
||||
m_bIsCreated = false;
|
||||
m_szQueued = "";
|
||||
g_pHyprRenderer->damageMonitor(&g_pCompositor->m_lMonitors.front());
|
||||
g_pHyprRenderer->damageMonitor(g_pCompositor->m_vMonitors.front().get());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PMONITOR = &g_pCompositor->m_lMonitors.front();
|
||||
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
|
||||
|
||||
if (g_pHyprOpenGL->m_RenderData.pMonitor != PMONITOR)
|
||||
return; // wrong mon
|
||||
|
||||
wlr_box windowBox = {0, 0, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
||||
wlr_box windowBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
|
||||
g_pHyprOpenGL->renderTexture(m_tTexture, &windowBox, 255.f, 0);
|
||||
}
|
||||
|
@@ -74,6 +74,7 @@ extern "C" {
|
||||
#include <wlr/types/wlr_keyboard_shortcuts_inhibit_v1.h>
|
||||
#include <wlr/types/wlr_virtual_pointer_v1.h>
|
||||
#include <wlr/types/wlr_foreign_toplevel_management_v1.h>
|
||||
#include <wlr/types/wlr_idle_inhibit_v1.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include <wlr/xwayland.h>
|
||||
#include <wlr/util/region.h>
|
||||
@@ -88,6 +89,10 @@ extern "C" {
|
||||
#include <wlr/types/wlr_pointer_constraints_v1.h>
|
||||
#include <wlr/types/wlr_relative_pointer_v1.h>
|
||||
#include <wlr/interfaces/wlr_keyboard.h>
|
||||
#include <wlr/types/wlr_xdg_foreign_registry.h>
|
||||
#include <wlr/types/wlr_xdg_foreign_v1.h>
|
||||
#include <wlr/types/wlr_xdg_foreign_v2.h>
|
||||
#include <wlr/types/wlr_pointer_gestures_v1.h>
|
||||
}
|
||||
|
||||
#undef class
|
||||
@@ -114,3 +119,6 @@ extern "C" {
|
||||
#include "helpers/Vector2D.hpp"
|
||||
|
||||
#include "ext-workspace-unstable-v1-protocol.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
@@ -23,19 +23,21 @@ void SDwindleNodeData::recalcSizePosRecursive() {
|
||||
|
||||
const auto REVERSESPLITRATIO = 2.f - splitRatio;
|
||||
|
||||
if (g_pConfigManager->getInt("dwindle:preserve_split") == 0)
|
||||
splitTop = size.y > size.x;
|
||||
if (g_pConfigManager->getInt("dwindle:preserve_split") == 0) {
|
||||
const auto WIDTHMULTIPLIER = g_pConfigManager->getFloat("dwindle:split_width_multiplier");
|
||||
splitTop = size.y * WIDTHMULTIPLIER > size.x;
|
||||
}
|
||||
|
||||
const auto SPLITSIDE = !splitTop;
|
||||
|
||||
if (SPLITSIDE) {
|
||||
// split sidey
|
||||
// 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);
|
||||
} else {
|
||||
// split toppy bottomy
|
||||
// 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);
|
||||
@@ -93,17 +95,28 @@ SDwindleNodeData* CHyprDwindleLayout::getMasterNodeOnWorkspace(const int& id) {
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID);
|
||||
|
||||
if (!PMONITOR){
|
||||
Debug::log(ERR, "Orphaned Node %x (workspace ID: %i)!!", pNode, pNode->workspaceID);
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't set nodes, only windows.
|
||||
if (pNode->isNode)
|
||||
return;
|
||||
|
||||
SMonitor* PMONITOR = nullptr;
|
||||
|
||||
if (pNode->workspaceID == SPECIAL_WORKSPACE_ID) {
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->specialWorkspaceOpen) {
|
||||
PMONITOR = m.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID);
|
||||
}
|
||||
|
||||
if (!PMONITOR) {
|
||||
Debug::log(ERR, "Orphaned Node %x (workspace ID: %i)!!", pNode, pNode->workspaceID);
|
||||
return;
|
||||
}
|
||||
|
||||
// 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);
|
||||
@@ -160,9 +173,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
|
||||
}
|
||||
}
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE->m_bIsSpecialWorkspace) {
|
||||
if (PWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) {
|
||||
// if special, we adjust the coords a bit
|
||||
static auto *const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("dwindle:special_scale_factor")->floatValue;
|
||||
|
||||
@@ -180,7 +191,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
|
||||
PWINDOW->updateWindowDecos();
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
|
||||
void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
if (pWindow->m_bIsFloating)
|
||||
return;
|
||||
|
||||
@@ -206,7 +217,7 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
|
||||
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
|
||||
|
||||
} else
|
||||
OPENINGON = getFirstNodeOnWorkspace(PMONITOR->activeWorkspace);
|
||||
OPENINGON = getFirstNodeOnWorkspace(pWindow->m_iWorkspaceID);
|
||||
|
||||
Debug::log(LOG, "OPENINGON: %x, Workspace: %i, Monitor: %i", OPENINGON, PNODE->workspaceID, PMONITOR->ID);
|
||||
|
||||
@@ -237,16 +248,19 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
|
||||
NEWPARENT->pParent = OPENINGON->pParent;
|
||||
NEWPARENT->isNode = true; // it is a node
|
||||
|
||||
const auto WIDTHMULTIPLIER = g_pConfigManager->getFloat("dwindle:split_width_multiplier");
|
||||
|
||||
// if cursor over first child, make it first, etc
|
||||
const auto SIDEBYSIDE = NEWPARENT->size.x / NEWPARENT->size.y > 1.f;
|
||||
const auto SIDEBYSIDE = NEWPARENT->size.x > NEWPARENT->size.y * WIDTHMULTIPLIER;
|
||||
NEWPARENT->splitTop = !SIDEBYSIDE;
|
||||
|
||||
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
|
||||
|
||||
const auto FORCESPLIT = g_pConfigManager->getInt("dwindle:force_split");
|
||||
|
||||
if (FORCESPLIT == 0) {
|
||||
if ((SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y, NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y + NEWPARENT->size.y))
|
||||
|| (!SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y, NEWPARENT->position.x + NEWPARENT->size.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f))) {
|
||||
if ((SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / WIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y + NEWPARENT->size.y))
|
||||
|| (!SIDEBYSIDE && VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / WIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f))) {
|
||||
// we are hovering over the first node, make PNODE first.
|
||||
NEWPARENT->children[1] = OPENINGON;
|
||||
NEWPARENT->children[0] = PNODE;
|
||||
@@ -275,14 +289,16 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
|
||||
}
|
||||
|
||||
// Update the children
|
||||
if (NEWPARENT->size.x > NEWPARENT->size.y) {
|
||||
// split sidey
|
||||
|
||||
|
||||
if (NEWPARENT->size.x * WIDTHMULTIPLIER > NEWPARENT->size.y) {
|
||||
// split left/right
|
||||
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);
|
||||
} else {
|
||||
// split toppy bottomy
|
||||
// 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);
|
||||
@@ -311,7 +327,7 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::onWindowRemoved(CWindow* pWindow) {
|
||||
void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
|
||||
@@ -378,6 +394,8 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
|
||||
if (!PWORKSPACE)
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->damageMonitor(PMONITOR);
|
||||
|
||||
if (PMONITOR->specialWorkspaceOpen) {
|
||||
const auto TOPNODE = getMasterNodeOnWorkspace(SPECIAL_WORKSPACE_ID);
|
||||
|
||||
@@ -388,9 +406,26 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore any recalc events if we have a fullscreen window.
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow)
|
||||
// Ignore any recalc events if we have a fullscreen window, but process if fullscreen mode 2
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL)
|
||||
return;
|
||||
|
||||
// massive hack from the fullscreen func
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
|
||||
SDwindleNodeData fakeNode;
|
||||
fakeNode.pWindow = PFULLWINDOW;
|
||||
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
fakeNode.workspaceID = PWORKSPACE->m_iID;
|
||||
PFULLWINDOW->m_vPosition = fakeNode.position;
|
||||
PFULLWINDOW->m_vSize = fakeNode.size;
|
||||
|
||||
applyNodeDataToWindow(&fakeNode);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->activeWorkspace);
|
||||
|
||||
@@ -401,150 +436,8 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::changeWindowFloatingMode(CWindow* pWindow) {
|
||||
|
||||
if (pWindow->m_bIsFullscreen) {
|
||||
Debug::log(LOG, "Rejecting a change float order because window is fullscreen.");
|
||||
|
||||
// restore its' floating mode
|
||||
pWindow->m_bIsFloating = !pWindow->m_bIsFloating;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
|
||||
if (!PNODE) {
|
||||
const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.vec() + pWindow->m_vRealSize.vec() / 2.f);
|
||||
pWindow->m_iMonitorID = PNEWMON->ID;
|
||||
pWindow->m_iWorkspaceID = PNEWMON->activeWorkspace;
|
||||
|
||||
// save real pos cuz the func applies the default 5,5 mid
|
||||
const auto PSAVEDPOS = pWindow->m_vRealPosition.vec();
|
||||
const auto PSAVEDSIZE = pWindow->m_vRealSize.vec();
|
||||
|
||||
// if the window is pseudo, update its size
|
||||
pWindow->m_vPseudoSize = pWindow->m_vRealSize.vec();
|
||||
|
||||
onWindowCreated(pWindow);
|
||||
|
||||
pWindow->m_vRealPosition.setValue(PSAVEDPOS);
|
||||
pWindow->m_vRealSize.setValue(PSAVEDSIZE);
|
||||
|
||||
// fix pseudo leaving artifacts
|
||||
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
|
||||
} else {
|
||||
onWindowRemoved(pWindow);
|
||||
|
||||
g_pCompositor->moveWindowToTop(pWindow);
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::onBeginDragWindow() {
|
||||
|
||||
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
|
||||
|
||||
m_vBeginDragSizeXY = Vector2D();
|
||||
|
||||
// Window will be floating. Let's check if it's valid. It should be, but I don't like crashing.
|
||||
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW)) {
|
||||
Debug::log(ERR, "Dragging attempted on an invalid window!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (DRAGGINGWINDOW->m_bIsFullscreen) {
|
||||
Debug::log(LOG, "Rejecting drag on a fullscreen window.");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(DRAGGINGWINDOW->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
Debug::log(LOG, "Rejecting drag on a fullscreen workspace.");
|
||||
return;
|
||||
}
|
||||
|
||||
DRAGGINGWINDOW->m_bDraggingTiled = false;
|
||||
|
||||
if (!DRAGGINGWINDOW->m_bIsFloating) {
|
||||
if (g_pInputManager->dragButton == BTN_LEFT) {
|
||||
changeWindowFloatingMode(DRAGGINGWINDOW);
|
||||
DRAGGINGWINDOW->m_bIsFloating = true;
|
||||
DRAGGINGWINDOW->m_bDraggingTiled = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal();
|
||||
m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.vec();
|
||||
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.vec();
|
||||
m_vLastDragXY = m_vBeginDragXY;
|
||||
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::onEndDragWindow() {
|
||||
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW))
|
||||
return;
|
||||
|
||||
if (DRAGGINGWINDOW->m_bDraggingTiled) {
|
||||
DRAGGINGWINDOW->m_bIsFloating = false;
|
||||
changeWindowFloatingMode(DRAGGINGWINDOW);
|
||||
}
|
||||
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
|
||||
|
||||
// Window invalid or drag begin size 0,0 meaning we rejected it.
|
||||
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW) || m_vBeginDragSizeXY == Vector2D()) {
|
||||
g_pInputManager->currentlyDraggedWindow = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
|
||||
const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y);
|
||||
|
||||
if (abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f)
|
||||
return;
|
||||
|
||||
m_vLastDragXY = mousePos;
|
||||
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
|
||||
if (g_pInputManager->dragButton == BTN_LEFT) {
|
||||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA);
|
||||
|
||||
DRAGGINGWINDOW->updateWindowDecos();
|
||||
|
||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
||||
} else {
|
||||
if (DRAGGINGWINDOW->m_bIsFloating) {
|
||||
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(m_vBeginDragSizeXY + DELTA);
|
||||
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(Vector2D(std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().x, (double)20, (double)999999), std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().y, (double)20, (double)999999)));
|
||||
|
||||
DRAGGINGWINDOW->updateWindowDecos();
|
||||
|
||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
||||
} else {
|
||||
resizeActiveWindow(TICKDELTA, DRAGGINGWINDOW);
|
||||
}
|
||||
}
|
||||
|
||||
// get middle point
|
||||
Vector2D middle = DRAGGINGWINDOW->m_vRealPosition.vec() + DRAGGINGWINDOW->m_vRealSize.vec() / 2.f;
|
||||
|
||||
// and check its monitor
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle);
|
||||
|
||||
if (PMONITOR) {
|
||||
DRAGGINGWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||
DRAGGINGWINDOW->m_iWorkspaceID = PMONITOR->activeWorkspace;
|
||||
}
|
||||
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
bool CHyprDwindleLayout::isWindowTiled(CWindow* pWindow) {
|
||||
return getNodeFromWindow(pWindow) != nullptr;
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* pWindow) {
|
||||
@@ -635,55 +528,6 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow*
|
||||
TOPCONTAINER->recalcSizePosRecursive();
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||
wlr_box desiredGeometry = {0};
|
||||
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
if (!PMONITOR){
|
||||
Debug::log(ERR, "Window %x (%s) has an invalid monitor in onWindowCreatedFloating!!!", pWindow, pWindow->m_szTitle.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (desiredGeometry.width <= 0 || desiredGeometry.height <= 0) {
|
||||
const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(pWindow);
|
||||
pWindow->m_vRealSize = Vector2D(PWINDOWSURFACE->current.width, PWINDOWSURFACE->current.height);
|
||||
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.vec().x) / 2.f, PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.vec().y) / 2.f);
|
||||
|
||||
} else {
|
||||
// we respect the size.
|
||||
pWindow->m_vRealSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
|
||||
|
||||
// check if it's on the correct monitor!
|
||||
Vector2D middlePoint = Vector2D(desiredGeometry.x, desiredGeometry.y) + Vector2D(desiredGeometry.width, desiredGeometry.height) / 2.f;
|
||||
|
||||
// TODO: detect a popup in a more consistent way.
|
||||
if (!g_pCompositor->isPointOnAnyMonitor(middlePoint) || (desiredGeometry.x == 0 && desiredGeometry.y == 0)) {
|
||||
// if it's not, fall back to the center placement
|
||||
pWindow->m_vRealPosition = PMONITOR->vecPosition + Vector2D((PMONITOR->vecSize.x - desiredGeometry.width) / 2.f, (PMONITOR->vecSize.y - desiredGeometry.height) / 2.f);
|
||||
} else {
|
||||
// if it is, we respect where it wants to put itself, but apply monitor offset if outside
|
||||
// most of these are popups
|
||||
|
||||
if (const auto POPENMON = g_pCompositor->getMonitorFromVector(middlePoint); POPENMON->ID != PMONITOR->ID) {
|
||||
pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y) - POPENMON->vecPosition + PMONITOR->vecPosition;
|
||||
} else {
|
||||
pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pWindow->m_bX11DoesntWantBorders) {
|
||||
pWindow->m_vRealPosition.setValue(pWindow->m_vRealPosition.goalv());
|
||||
pWindow->m_vRealSize.setValue(pWindow->m_vRealSize.goalv());
|
||||
}
|
||||
|
||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
|
||||
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
|
||||
|
||||
g_pCompositor->moveWindowToTop(pWindow);
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode, bool on) {
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return;
|
||||
@@ -704,6 +548,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
||||
pWindow->m_bIsFullscreen = on;
|
||||
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)});
|
||||
|
||||
if (!pWindow->m_bIsFullscreen) {
|
||||
// if it got its fullscreen disabled, set back its node if it had one
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
@@ -739,11 +585,15 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
||||
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;
|
||||
|
||||
applyNodeDataToWindow(&fakeNode);
|
||||
}
|
||||
}
|
||||
|
||||
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
|
||||
|
||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
|
||||
|
||||
g_pCompositor->moveWindowToTop(pWindow);
|
||||
@@ -751,6 +601,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree
|
||||
// we need to fix XWayland windows by sending them to NARNIA
|
||||
// because otherwise they'd still be recieving mouse events
|
||||
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
|
||||
|
||||
recalculateMonitor(PMONITOR->ID);
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::recalculateWindow(CWindow* pWindow) {
|
||||
@@ -826,6 +678,8 @@ void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
|
||||
|
||||
PPARENT->recalcSizePosRecursive();
|
||||
}
|
||||
|
||||
g_pInputManager->refocus();
|
||||
}
|
||||
|
||||
std::deque<CWindow*> CHyprDwindleLayout::getGroupMembers(CWindow* pWindow) {
|
||||
@@ -1011,18 +865,15 @@ std::string CHyprDwindleLayout::getLayoutName() {
|
||||
return "dwindle";
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::moveActiveWindow(const Vector2D& delta, CWindow* pWindow) {
|
||||
const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
|
||||
void CHyprDwindleLayout::onEnable() {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_bIsFloating || !w->m_bMappedX11 || !w->m_bIsMapped || w->m_bHidden)
|
||||
continue;
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
return;
|
||||
|
||||
if (!PWINDOW->m_bIsFloating) {
|
||||
Debug::log(LOG, "Dwindle cannot move a tiled window in moveActiveWindow!");
|
||||
return;
|
||||
onWindowCreatedTiling(w.get());
|
||||
}
|
||||
}
|
||||
|
||||
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goalv() + delta;
|
||||
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
void CHyprDwindleLayout::onDisable() {
|
||||
m_lDwindleNodesData.clear();
|
||||
}
|
@@ -42,17 +42,12 @@ struct SDwindleNodeData {
|
||||
|
||||
class CHyprDwindleLayout : public IHyprLayout {
|
||||
public:
|
||||
virtual void onWindowCreated(CWindow*);
|
||||
virtual void onWindowRemoved(CWindow*);
|
||||
virtual void onWindowCreatedTiling(CWindow*);
|
||||
virtual void onWindowRemovedTiling(CWindow*);
|
||||
virtual bool isWindowTiled(CWindow*);
|
||||
virtual void recalculateMonitor(const int&);
|
||||
virtual void recalculateWindow(CWindow*);
|
||||
virtual void changeWindowFloatingMode(CWindow*);
|
||||
virtual void onBeginDragWindow();
|
||||
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
|
||||
virtual void moveActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
|
||||
virtual void onEndDragWindow();
|
||||
virtual void onMouseMove(const Vector2D&);
|
||||
virtual void onWindowCreatedFloating(CWindow*);
|
||||
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
|
||||
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
|
||||
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
|
||||
@@ -60,15 +55,13 @@ public:
|
||||
virtual void alterSplitRatioBy(CWindow*, float);
|
||||
virtual std::string getLayoutName();
|
||||
|
||||
private:
|
||||
virtual void onEnable();
|
||||
virtual void onDisable();
|
||||
|
||||
private:
|
||||
|
||||
std::list<SDwindleNodeData> m_lDwindleNodesData;
|
||||
|
||||
Vector2D m_vBeginDragXY;
|
||||
Vector2D m_vLastDragXY;
|
||||
Vector2D m_vBeginDragPositionXY;
|
||||
Vector2D m_vBeginDragSizeXY;
|
||||
|
||||
int getNodesOnWorkspace(const int&);
|
||||
void applyNodeDataToWindow(SDwindleNodeData*);
|
||||
SDwindleNodeData* getNodeFromWindow(CWindow*);
|
||||
|
257
src/layout/IHyprLayout.cpp
Normal file
@@ -0,0 +1,257 @@
|
||||
#include "IHyprLayout.hpp"
|
||||
#include "../defines.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
void IHyprLayout::onWindowCreated(CWindow* pWindow) {
|
||||
if (pWindow->m_bIsFloating) {
|
||||
onWindowCreatedFloating(pWindow);
|
||||
} else {
|
||||
onWindowCreatedTiling(pWindow);
|
||||
}
|
||||
}
|
||||
|
||||
void IHyprLayout::onWindowRemoved(CWindow* pWindow) {
|
||||
if (pWindow->m_bIsFloating) {
|
||||
onWindowRemovedFloating(pWindow);
|
||||
} else {
|
||||
onWindowRemovedTiling(pWindow);
|
||||
}
|
||||
}
|
||||
|
||||
void IHyprLayout::onWindowRemovedFloating(CWindow* pWindow) {
|
||||
return; // no-op
|
||||
}
|
||||
|
||||
void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) {
|
||||
wlr_box desiredGeometry = {0};
|
||||
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
|
||||
if (!PMONITOR) {
|
||||
Debug::log(ERR, "Window %x (%s) has an invalid monitor in onWindowCreatedFloating!!!", pWindow, pWindow->m_szTitle.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
|
||||
const auto PWINDOWSURFACE = g_pXWaylandManager->getWindowSurface(pWindow);
|
||||
pWindow->m_vRealSize = Vector2D(PWINDOWSURFACE->current.width, PWINDOWSURFACE->current.height);
|
||||
|
||||
// reject any windows with size <= 5x5
|
||||
if (pWindow->m_vRealSize.goalv().x <= 5 || pWindow->m_vRealSize.goalv().y <= 5) {
|
||||
pWindow->m_vRealSize = PMONITOR->vecSize / 2.f;
|
||||
}
|
||||
|
||||
pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goalv().x) / 2.f, PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goalv().y) / 2.f);
|
||||
} else {
|
||||
// we respect the size.
|
||||
pWindow->m_vRealSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
|
||||
|
||||
// check if it's on the correct monitor!
|
||||
Vector2D middlePoint = Vector2D(desiredGeometry.x, desiredGeometry.y) + Vector2D(desiredGeometry.width, desiredGeometry.height) / 2.f;
|
||||
|
||||
// TODO: detect a popup in a more consistent way.
|
||||
if ((desiredGeometry.x == 0 && desiredGeometry.y == 0)) {
|
||||
// if it's not, fall back to the center placement
|
||||
pWindow->m_vRealPosition = PMONITOR->vecPosition + Vector2D((PMONITOR->vecSize.x - desiredGeometry.width) / 2.f, (PMONITOR->vecSize.y - desiredGeometry.height) / 2.f);
|
||||
} else {
|
||||
// if it is, we respect where it wants to put itself, but apply monitor offset if outside
|
||||
// most of these are popups
|
||||
|
||||
if (const auto POPENMON = g_pCompositor->getMonitorFromVector(middlePoint); POPENMON->ID != PMONITOR->ID) {
|
||||
pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y) - POPENMON->vecPosition + PMONITOR->vecPosition;
|
||||
} else {
|
||||
pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pWindow->m_bX11DoesntWantBorders) {
|
||||
pWindow->m_vRealPosition.setValue(pWindow->m_vRealPosition.goalv());
|
||||
pWindow->m_vRealSize.setValue(pWindow->m_vRealSize.goalv());
|
||||
}
|
||||
|
||||
if (pWindow->m_iX11Type != 2) {
|
||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
|
||||
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
|
||||
|
||||
g_pCompositor->moveWindowToTop(pWindow);
|
||||
}
|
||||
}
|
||||
|
||||
void IHyprLayout::onBeginDragWindow() {
|
||||
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
|
||||
|
||||
m_vBeginDragSizeXY = Vector2D();
|
||||
|
||||
// Window will be floating. Let's check if it's valid. It should be, but I don't like crashing.
|
||||
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW)) {
|
||||
Debug::log(ERR, "Dragging attempted on an invalid window!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (DRAGGINGWINDOW->m_bIsFullscreen) {
|
||||
Debug::log(LOG, "Rejecting drag on a fullscreen window.");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(DRAGGINGWINDOW->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
Debug::log(LOG, "Rejecting drag on a fullscreen workspace.");
|
||||
return;
|
||||
}
|
||||
|
||||
DRAGGINGWINDOW->m_bDraggingTiled = false;
|
||||
|
||||
if (!DRAGGINGWINDOW->m_bIsFloating) {
|
||||
if (g_pInputManager->dragButton == BTN_LEFT) {
|
||||
changeWindowFloatingMode(DRAGGINGWINDOW);
|
||||
DRAGGINGWINDOW->m_bIsFloating = true;
|
||||
DRAGGINGWINDOW->m_bDraggingTiled = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal();
|
||||
m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.vec();
|
||||
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.vec();
|
||||
m_vLastDragXY = m_vBeginDragXY;
|
||||
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
|
||||
// shadow to ignore any bound to MAIN_MOD
|
||||
g_pKeybindManager->shadowKeybinds();
|
||||
}
|
||||
|
||||
void IHyprLayout::onEndDragWindow() {
|
||||
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW))
|
||||
return;
|
||||
|
||||
if (DRAGGINGWINDOW->m_bDraggingTiled) {
|
||||
DRAGGINGWINDOW->m_bIsFloating = false;
|
||||
changeWindowFloatingMode(DRAGGINGWINDOW);
|
||||
}
|
||||
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
}
|
||||
|
||||
void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||
const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow;
|
||||
|
||||
// Window invalid or drag begin size 0,0 meaning we rejected it.
|
||||
if (!g_pCompositor->windowValidMapped(DRAGGINGWINDOW) || m_vBeginDragSizeXY == Vector2D()) {
|
||||
g_pInputManager->currentlyDraggedWindow = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto DELTA = Vector2D(mousePos.x - m_vBeginDragXY.x, mousePos.y - m_vBeginDragXY.y);
|
||||
const auto TICKDELTA = Vector2D(mousePos.x - m_vLastDragXY.x, mousePos.y - m_vLastDragXY.y);
|
||||
|
||||
if (abs(TICKDELTA.x) < 1.f && abs(TICKDELTA.y) < 1.f)
|
||||
return;
|
||||
|
||||
m_vLastDragXY = mousePos;
|
||||
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
|
||||
if (g_pInputManager->dragButton == BTN_LEFT) {
|
||||
DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA);
|
||||
|
||||
DRAGGINGWINDOW->updateWindowDecos();
|
||||
|
||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
||||
} else {
|
||||
if (DRAGGINGWINDOW->m_bIsFloating) {
|
||||
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(m_vBeginDragSizeXY + DELTA);
|
||||
DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(Vector2D(std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().x, (double)20, (double)999999), std::clamp(DRAGGINGWINDOW->m_vRealSize.vec().y, (double)20, (double)999999)));
|
||||
|
||||
DRAGGINGWINDOW->updateWindowDecos();
|
||||
|
||||
g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv());
|
||||
} else {
|
||||
resizeActiveWindow(TICKDELTA, DRAGGINGWINDOW);
|
||||
}
|
||||
}
|
||||
|
||||
// get middle point
|
||||
Vector2D middle = DRAGGINGWINDOW->m_vRealPosition.vec() + DRAGGINGWINDOW->m_vRealSize.vec() / 2.f;
|
||||
|
||||
// and check its monitor
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle);
|
||||
|
||||
if (PMONITOR) {
|
||||
DRAGGINGWINDOW->m_iMonitorID = PMONITOR->ID;
|
||||
DRAGGINGWINDOW->m_iWorkspaceID = PMONITOR->activeWorkspace;
|
||||
}
|
||||
|
||||
g_pHyprRenderer->damageWindow(DRAGGINGWINDOW);
|
||||
}
|
||||
|
||||
void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) {
|
||||
|
||||
if (pWindow->m_bIsFullscreen) {
|
||||
Debug::log(LOG, "Rejecting a change float order because window is fullscreen.");
|
||||
|
||||
// restore its' floating mode
|
||||
pWindow->m_bIsFloating = !pWindow->m_bIsFloating;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto TILED = isWindowTiled(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->m_iWorkspaceID = PNEWMON->activeWorkspace;
|
||||
|
||||
// save real pos cuz the func applies the default 5,5 mid
|
||||
const auto PSAVEDPOS = pWindow->m_vRealPosition.vec();
|
||||
const auto PSAVEDSIZE = pWindow->m_vRealSize.vec();
|
||||
|
||||
// if the window is pseudo, update its size
|
||||
pWindow->m_vPseudoSize = pWindow->m_vRealSize.vec();
|
||||
|
||||
onWindowCreatedTiling(pWindow);
|
||||
|
||||
pWindow->m_vRealPosition.setValue(PSAVEDPOS);
|
||||
pWindow->m_vRealSize.setValue(PSAVEDSIZE);
|
||||
|
||||
// fix pseudo leaving artifacts
|
||||
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
|
||||
} else {
|
||||
pWindow->m_vSize = pWindow->m_vRealSize.vec();
|
||||
pWindow->m_vPosition = pWindow->m_vRealPosition.vec();
|
||||
|
||||
onWindowRemovedTiling(pWindow);
|
||||
|
||||
g_pCompositor->moveWindowToTop(pWindow);
|
||||
|
||||
const auto POS = pWindow->m_vRealPosition.goalv();
|
||||
const auto SIZ = pWindow->m_vRealSize.goalv();
|
||||
|
||||
pWindow->m_vRealPosition.setValueAndWarp(POS + Vector2D(5, 5));
|
||||
pWindow->m_vRealSize.setValueAndWarp(SIZ - Vector2D(10, 10));
|
||||
|
||||
pWindow->m_vRealPosition = POS;
|
||||
pWindow->m_vRealSize = SIZ;
|
||||
|
||||
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID));
|
||||
}
|
||||
}
|
||||
|
||||
void IHyprLayout::moveActiveWindow(const Vector2D& delta, CWindow* pWindow) {
|
||||
const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
return;
|
||||
|
||||
if (!PWINDOW->m_bIsFloating) {
|
||||
Debug::log(LOG, "Dwindle cannot move a tiled window in moveActiveWindow!");
|
||||
return;
|
||||
}
|
||||
|
||||
PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goalv() + delta;
|
||||
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
}
|
@@ -16,17 +16,29 @@ enum eFullscreenMode : uint8_t;
|
||||
|
||||
interface IHyprLayout {
|
||||
public:
|
||||
virtual void onEnable() = 0;
|
||||
virtual void onDisable() = 0;
|
||||
|
||||
/*
|
||||
Called when a window is created (mapped)
|
||||
The layout HAS TO set the goal pos and size (anim mgr will use it)
|
||||
If !animationinprogress, then the anim mgr will not apply an anim.
|
||||
*/
|
||||
virtual void onWindowCreated(CWindow*) = 0;
|
||||
virtual void onWindowCreated(CWindow*);
|
||||
virtual void onWindowCreatedTiling(CWindow*) = 0;
|
||||
virtual void onWindowCreatedFloating(CWindow*);
|
||||
|
||||
/*
|
||||
Return tiled status
|
||||
*/
|
||||
virtual bool isWindowTiled(CWindow*) = 0;
|
||||
|
||||
/*
|
||||
Called when a window is removed (unmapped)
|
||||
*/
|
||||
virtual void onWindowRemoved(CWindow*) = 0;
|
||||
virtual void onWindowRemoved(CWindow*);
|
||||
virtual void onWindowRemovedTiling(CWindow*) = 0;
|
||||
virtual void onWindowRemovedFloating(CWindow*);
|
||||
/*
|
||||
Called when the monitor requires a layout recalculation
|
||||
this usually means reserved area changes
|
||||
@@ -42,13 +54,13 @@ public:
|
||||
/*
|
||||
Called when a window is requested to be floated
|
||||
*/
|
||||
virtual void changeWindowFloatingMode(CWindow*) = 0;
|
||||
virtual void changeWindowFloatingMode(CWindow*);
|
||||
/*
|
||||
Called when a window is clicked on, beginning a drag
|
||||
this might be a resize, move, whatever the layout defines it
|
||||
as.
|
||||
*/
|
||||
virtual void onBeginDragWindow() = 0;
|
||||
virtual void onBeginDragWindow();
|
||||
/*
|
||||
Called when a user requests a resize of the current window by a vec
|
||||
Vector2D holds pixel values
|
||||
@@ -60,24 +72,18 @@ public:
|
||||
Vector2D holds pixel values
|
||||
Optional pWindow for a specific window
|
||||
*/
|
||||
virtual void moveActiveWindow(const Vector2D&, CWindow* pWindow = nullptr) = 0;
|
||||
virtual void moveActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
|
||||
/*
|
||||
Called when a window is ended being dragged
|
||||
(mouse up)
|
||||
*/
|
||||
virtual void onEndDragWindow() = 0;
|
||||
virtual void onEndDragWindow();
|
||||
/*
|
||||
Called whenever the mouse moves, should the layout want to
|
||||
do anything with it.
|
||||
Useful for dragging.
|
||||
*/
|
||||
virtual void onMouseMove(const Vector2D&) = 0;
|
||||
/*
|
||||
Called when a window is created, but is requesting to be floated.
|
||||
Warning: this also includes stuff like popups, incorrect handling
|
||||
of which can result in a crash!
|
||||
*/
|
||||
virtual void onWindowCreatedFloating(CWindow*) = 0;
|
||||
virtual void onMouseMove(const Vector2D&);
|
||||
|
||||
/*
|
||||
Called when a window / the user requests to toggle the fullscreen state of a window
|
||||
@@ -116,4 +122,10 @@ public:
|
||||
Called when something wants the current layout's name
|
||||
*/
|
||||
virtual std::string getLayoutName() = 0;
|
||||
|
||||
private:
|
||||
Vector2D m_vBeginDragXY;
|
||||
Vector2D m_vLastDragXY;
|
||||
Vector2D m_vBeginDragPositionXY;
|
||||
Vector2D m_vBeginDragSizeXY;
|
||||
};
|
423
src/layout/MasterLayout.cpp
Normal file
@@ -0,0 +1,423 @@
|
||||
#include "MasterLayout.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
SMasterNodeData* CHyprMasterLayout::getNodeFromWindow(CWindow* pWindow) {
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
if (nd.pWindow == pWindow)
|
||||
return &nd;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int CHyprMasterLayout::getNodesOnWorkspace(const int& ws) {
|
||||
int no = 0;
|
||||
for (auto& n : m_lMasterNodesData) {
|
||||
if (n.workspaceID == ws)
|
||||
no++;
|
||||
}
|
||||
|
||||
return no;
|
||||
}
|
||||
|
||||
std::string CHyprMasterLayout::getLayoutName() {
|
||||
return "Master";
|
||||
}
|
||||
|
||||
SMasterNodeData* CHyprMasterLayout::getMasterNodeOnWorkspace(const int& ws) {
|
||||
for (auto& n : m_lMasterNodesData) {
|
||||
if (n.isMaster && n.workspaceID == ws)
|
||||
return &n;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||
if (pWindow->m_bIsFloating)
|
||||
return;
|
||||
|
||||
static auto *const PNEWTOP = &g_pConfigManager->getConfigValuePtr("master:new_on_top")->intValue;
|
||||
|
||||
const auto PNODE = *PNEWTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back();
|
||||
|
||||
PNODE->workspaceID = pWindow->m_iWorkspaceID;
|
||||
PNODE->pWindow = pWindow;
|
||||
|
||||
static auto *const PNEWISMASTER = &g_pConfigManager->getConfigValuePtr("master:new_is_master")->intValue;
|
||||
|
||||
const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID);
|
||||
float lastSplitPercent = 0.5f;
|
||||
|
||||
if (*PNEWISMASTER || WINDOWSONWORKSPACE == 1) {
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
|
||||
nd.isMaster = false;
|
||||
lastSplitPercent = nd.percMaster;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PNODE->isMaster = true;
|
||||
PNODE->percMaster = lastSplitPercent;
|
||||
} else {
|
||||
PNODE->isMaster = false;
|
||||
}
|
||||
|
||||
// recalc
|
||||
recalculateMonitor(pWindow->m_iMonitorID);
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
|
||||
if (!PNODE)
|
||||
return;
|
||||
|
||||
if (PNODE->isMaster) {
|
||||
// find new one
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
if (!nd.isMaster) {
|
||||
nd.isMaster = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_lMasterNodesData.remove(*PNODE);
|
||||
|
||||
recalculateMonitor(pWindow->m_iMonitorID);
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::recalculateMonitor(const int& monid) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
|
||||
if (!PWORKSPACE)
|
||||
return;
|
||||
|
||||
g_pHyprRenderer->damageMonitor(PMONITOR);
|
||||
|
||||
if (PMONITOR->specialWorkspaceOpen) {
|
||||
calculateWorkspace(SPECIAL_WORKSPACE_ID);
|
||||
}
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
||||
if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL)
|
||||
return;
|
||||
|
||||
// massive hack from the fullscreen func
|
||||
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
|
||||
SMasterNodeData fakeNode;
|
||||
fakeNode.pWindow = PFULLWINDOW;
|
||||
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
||||
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
||||
fakeNode.workspaceID = PWORKSPACE->m_iID;
|
||||
PFULLWINDOW->m_vPosition = fakeNode.position;
|
||||
PFULLWINDOW->m_vSize = fakeNode.size;
|
||||
|
||||
applyNodeDataToWindow(&fakeNode);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// calc the WS
|
||||
calculateWorkspace(PWORKSPACE->m_iID);
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(ws);
|
||||
|
||||
if (!PWORKSPACE)
|
||||
return;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
||||
|
||||
const auto PMASTERNODE = getMasterNodeOnWorkspace(PWORKSPACE->m_iID);
|
||||
|
||||
if (!PMASTERNODE)
|
||||
return;
|
||||
|
||||
if (getNodesOnWorkspace(PWORKSPACE->m_iID) < 2) {
|
||||
PMASTERNODE->position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition;
|
||||
PMASTERNODE->size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x, PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y);
|
||||
applyNodeDataToWindow(PMASTERNODE);
|
||||
return;
|
||||
} else {
|
||||
PMASTERNODE->position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition;
|
||||
PMASTERNODE->size = Vector2D((PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) * PMASTERNODE->percMaster, PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y);
|
||||
}
|
||||
|
||||
const auto SLAVESIZE = 1.f / (getNodesOnWorkspace(PWORKSPACE->m_iID) - 1) * (PMASTERNODE->size.y);
|
||||
int slavesDone = 0;
|
||||
|
||||
for (auto& nd : m_lMasterNodesData) {
|
||||
if (nd.workspaceID != PWORKSPACE->m_iID)
|
||||
continue;
|
||||
|
||||
if (nd == *PMASTERNODE) {
|
||||
applyNodeDataToWindow(PMASTERNODE);
|
||||
continue;
|
||||
}
|
||||
|
||||
nd.position = Vector2D(PMASTERNODE->size.x + PMASTERNODE->position.x, slavesDone * SLAVESIZE + PMASTERNODE->position.y);
|
||||
nd.size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x - PMASTERNODE->size.x, SLAVESIZE);
|
||||
|
||||
slavesDone++;
|
||||
|
||||
applyNodeDataToWindow(&nd);
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||
SMonitor* PMONITOR = nullptr;
|
||||
|
||||
if (pNode->workspaceID == SPECIAL_WORKSPACE_ID) {
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->specialWorkspaceOpen) {
|
||||
PMONITOR = m.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID);
|
||||
}
|
||||
|
||||
if (!PMONITOR) {
|
||||
Debug::log(ERR, "Orphaned Node %x (workspace ID: %i)!!", pNode, pNode->workspaceID);
|
||||
return;
|
||||
}
|
||||
|
||||
// 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 auto BORDERSIZE = g_pConfigManager->getInt("general:border_size");
|
||||
const auto GAPSIN = g_pConfigManager->getInt("general:gaps_in");
|
||||
const auto GAPSOUT = g_pConfigManager->getInt("general:gaps_out");
|
||||
|
||||
const auto PWINDOW = pNode->pWindow;
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW)) {
|
||||
Debug::log(ERR, "Node %x holding invalid window %x!!", pNode, PWINDOW);
|
||||
return;
|
||||
}
|
||||
|
||||
PWINDOW->m_vSize = pNode->size;
|
||||
PWINDOW->m_vPosition = pNode->position;
|
||||
|
||||
// TODO: special
|
||||
|
||||
auto calcPos = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE);
|
||||
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE);
|
||||
|
||||
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? GAPSOUT : GAPSIN,
|
||||
DISPLAYTOP ? GAPSOUT : GAPSIN);
|
||||
|
||||
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? GAPSOUT : GAPSIN,
|
||||
DISPLAYBOTTOM ? GAPSOUT : GAPSIN);
|
||||
|
||||
calcPos = calcPos + OFFSETTOPLEFT;
|
||||
calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
|
||||
|
||||
if (PWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) {
|
||||
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;
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * *PSCALEFACTOR);
|
||||
} else {
|
||||
PWINDOW->m_vRealSize = calcSize;
|
||||
PWINDOW->m_vRealPosition = calcPos;
|
||||
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
|
||||
}
|
||||
|
||||
PWINDOW->updateWindowDecos();
|
||||
}
|
||||
|
||||
bool CHyprMasterLayout::isWindowTiled(CWindow* pWindow) {
|
||||
return getNodeFromWindow(pWindow) != nullptr;
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* pWindow) {
|
||||
const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
||||
return;
|
||||
|
||||
const auto PNODE = getNodeFromWindow(PWINDOW);
|
||||
|
||||
if (!PNODE) {
|
||||
PWINDOW->m_vRealSize = Vector2D(std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).x, (double)20, (double)999999), std::clamp((PWINDOW->m_vRealSize.goalv() + pixResize).y, (double)20, (double)999999));
|
||||
PWINDOW->updateWindowDecos();
|
||||
return;
|
||||
}
|
||||
|
||||
// get master
|
||||
const auto PMASTER = getMasterNodeOnWorkspace(PWINDOW->m_iWorkspaceID);
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
|
||||
if (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) < 2)
|
||||
return;
|
||||
|
||||
float delta = pixResize.x / PMONITOR->vecSize.x;
|
||||
|
||||
PMASTER->percMaster += delta;
|
||||
|
||||
std::clamp(PMASTER->percMaster, 0.05f, 0.95f);
|
||||
|
||||
recalculateMonitor(PMONITOR->ID);
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode, bool on) {
|
||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
||||
return;
|
||||
|
||||
if (on == pWindow->m_bIsFullscreen)
|
||||
return; // ignore
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && on) {
|
||||
// if the window wants to be fullscreen but there already is one,
|
||||
// ignore the request.
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise, accept it.
|
||||
pWindow->m_bIsFullscreen = on;
|
||||
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)});
|
||||
|
||||
if (!pWindow->m_bIsFullscreen) {
|
||||
// if it got its fullscreen disabled, set back its node if it had one
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
if (PNODE)
|
||||
applyNodeDataToWindow(PNODE);
|
||||
else {
|
||||
// get back its' dimensions from position and size
|
||||
pWindow->m_vRealPosition = pWindow->m_vPosition;
|
||||
pWindow->m_vRealSize = pWindow->m_vSize;
|
||||
}
|
||||
} else {
|
||||
// if it now got fullscreen, make it fullscreen
|
||||
|
||||
PWORKSPACE->m_efFullscreenMode = fullscreenMode;
|
||||
|
||||
// save position and size if floating
|
||||
if (pWindow->m_bIsFloating) {
|
||||
pWindow->m_vPosition = pWindow->m_vRealPosition.vec();
|
||||
pWindow->m_vSize = pWindow->m_vRealSize.vec();
|
||||
}
|
||||
|
||||
// apply new pos and size being monitors' box
|
||||
if (fullscreenMode == FULLSCREEN_FULL) {
|
||||
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
||||
pWindow->m_vRealSize = PMONITOR->vecSize;
|
||||
} else {
|
||||
// This is a massive hack.
|
||||
// We make a fake "only" node and apply
|
||||
// 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;
|
||||
|
||||
applyNodeDataToWindow(&fakeNode);
|
||||
}
|
||||
}
|
||||
|
||||
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
|
||||
|
||||
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
|
||||
|
||||
g_pCompositor->moveWindowToTop(pWindow);
|
||||
|
||||
// we need to fix XWayland windows by sending them to NARNIA
|
||||
// because otherwise they'd still be recieving mouse events
|
||||
g_pCompositor->fixXWaylandWindowsOnWorkspace(PMONITOR->activeWorkspace);
|
||||
|
||||
recalculateMonitor(PMONITOR->ID);
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::recalculateWindow(CWindow* pWindow) {
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
|
||||
if (!PNODE)
|
||||
return;
|
||||
|
||||
recalculateMonitor(pWindow->m_iMonitorID);
|
||||
}
|
||||
|
||||
SWindowRenderLayoutHints CHyprMasterLayout::requestRenderHints(CWindow* pWindow) {
|
||||
// window should be valid, insallah
|
||||
|
||||
SWindowRenderLayoutHints hints;
|
||||
|
||||
return hints; // master doesnt have any hints
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
|
||||
// windows should be valid, insallah
|
||||
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
const auto PNODE2 = getNodeFromWindow(pWindow2);
|
||||
|
||||
if (!PNODE2 || !PNODE)
|
||||
return;
|
||||
|
||||
if (PNODE->workspaceID != PNODE2->workspaceID) {
|
||||
Debug::log(ERR, "Master: Rejecting a swap between workspaces");
|
||||
return;
|
||||
}
|
||||
|
||||
// massive hack: just swap window pointers, lol
|
||||
const auto PWINDOW1 = PNODE->pWindow;
|
||||
PNODE->pWindow = PNODE2->pWindow;
|
||||
PNODE2->pWindow = PWINDOW1;
|
||||
|
||||
recalculateMonitor(PWINDOW1->m_iMonitorID);
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
|
||||
// window should be valid, insallah
|
||||
|
||||
const auto PNODE = getNodeFromWindow(pWindow);
|
||||
|
||||
if (!PNODE)
|
||||
return;
|
||||
|
||||
const auto PMASTER = getMasterNodeOnWorkspace(pWindow->m_iWorkspaceID);
|
||||
|
||||
PMASTER->percMaster = std::clamp(PMASTER->percMaster + ratio, 0.05f, 0.95f);
|
||||
|
||||
recalculateMonitor(pWindow->m_iMonitorID);
|
||||
}
|
||||
|
||||
std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::string message) {
|
||||
return "";
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::onEnable() {
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_bIsFloating || !w->m_bMappedX11 || !w->m_bIsMapped || w->m_bHidden)
|
||||
continue;
|
||||
|
||||
onWindowCreatedTiling(w.get());
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprMasterLayout::onDisable() {
|
||||
m_lMasterNodesData.clear();
|
||||
}
|
54
src/layout/MasterLayout.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "IHyprLayout.hpp"
|
||||
#include <list>
|
||||
#include <deque>
|
||||
|
||||
enum eFullscreenMode : uint8_t;
|
||||
|
||||
struct SMasterNodeData {
|
||||
bool isMaster = false;
|
||||
float percMaster = 0.5f;
|
||||
|
||||
CWindow* pWindow = nullptr;
|
||||
|
||||
Vector2D position;
|
||||
Vector2D size;
|
||||
|
||||
int workspaceID = -1;
|
||||
|
||||
bool operator==(const SMasterNodeData& rhs) {
|
||||
return pWindow == rhs.pWindow;
|
||||
}
|
||||
};
|
||||
|
||||
class CHyprMasterLayout : public IHyprLayout {
|
||||
public:
|
||||
virtual void onWindowCreatedTiling(CWindow*);
|
||||
virtual void onWindowRemovedTiling(CWindow*);
|
||||
virtual bool isWindowTiled(CWindow*);
|
||||
virtual void recalculateMonitor(const int&);
|
||||
virtual void recalculateWindow(CWindow*);
|
||||
virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr);
|
||||
virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool);
|
||||
virtual std::any layoutMessage(SLayoutMessageHeader, std::string);
|
||||
virtual SWindowRenderLayoutHints requestRenderHints(CWindow*);
|
||||
virtual void switchWindows(CWindow*, CWindow*);
|
||||
virtual void alterSplitRatioBy(CWindow*, float);
|
||||
virtual std::string getLayoutName();
|
||||
|
||||
virtual void onEnable();
|
||||
virtual void onDisable();
|
||||
|
||||
private:
|
||||
|
||||
std::list<SMasterNodeData> m_lMasterNodesData;
|
||||
|
||||
int getNodesOnWorkspace(const int&);
|
||||
void applyNodeDataToWindow(SMasterNodeData*);
|
||||
SMasterNodeData* getNodeFromWindow(CWindow*);
|
||||
SMasterNodeData* getMasterNodeOnWorkspace(const int&);
|
||||
void calculateWorkspace(const int&);
|
||||
|
||||
friend struct SMasterNodeData;
|
||||
};
|
15
src/main.cpp
@@ -12,12 +12,22 @@ bool ignoreSudo = false;
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
if (!getenv("XDG_RUNTIME_DIR"))
|
||||
RIP("XDG_RUNTIME_DIR not set!");
|
||||
throw std::runtime_error("XDG_RUNTIME_DIR is not set!");
|
||||
|
||||
// parse some args
|
||||
std::string configPath;
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (!strcmp(argv[i], "--i-am-really-stupid"))
|
||||
ignoreSudo = true;
|
||||
else if ((!strcmp(argv[i], "-c") || !strcmp(argv[i], "--config")) && argc >= i + 2) {
|
||||
configPath = std::string(argv[++i]);
|
||||
Debug::log(LOG, "Using config location %s.", configPath.c_str());
|
||||
} else {
|
||||
std::cout << "Hyprland usage: Hyprland [arg [...]].\n\nArguments:\n" <<
|
||||
"--help -h | Show this help message\n" <<
|
||||
"--config -c | Specify config file to use\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
system("mkdir -p /tmp/hypr");
|
||||
@@ -37,6 +47,7 @@ int main(int argc, char** argv) {
|
||||
// let's init the compositor.
|
||||
// it initializes basic Wayland stuff in the constructor.
|
||||
g_pCompositor = std::make_unique<CCompositor>();
|
||||
g_pCompositor->explicitConfigPath = configPath;
|
||||
|
||||
Debug::log(LOG, "Hyprland init finished.");
|
||||
|
||||
@@ -46,7 +57,7 @@ int main(int argc, char** argv) {
|
||||
// If we are here it means we got yote.
|
||||
Debug::log(LOG, "Hyprland reached the end.");
|
||||
|
||||
g_pCompositor->cleanupExit();
|
||||
g_pCompositor->cleanup();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@@ -31,111 +31,113 @@ void CAnimationManager::tick() {
|
||||
static auto *const PANIMSPEED = &g_pConfigManager->getConfigValuePtr("animations:speed")->floatValue;
|
||||
static auto *const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
||||
static auto *const BEZIERSTR = &g_pConfigManager->getConfigValuePtr("animations:curve")->strValue;
|
||||
static auto *const PSHADOWSENABLED = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
|
||||
|
||||
auto DEFAULTBEZIER = m_mBezierCurves.find(*BEZIERSTR);
|
||||
if (DEFAULTBEZIER == m_mBezierCurves.end())
|
||||
DEFAULTBEZIER = m_mBezierCurves.find("default");
|
||||
|
||||
for (auto& av : m_lAnimatedVariables) {
|
||||
// get speed
|
||||
const auto SPEED = *av->m_pSpeed == 0 ? *PANIMSPEED : *av->m_pSpeed;
|
||||
|
||||
// window stuff
|
||||
const auto PWINDOW = (CWindow*)av->m_pWindow;
|
||||
const auto PWORKSPACE = (CWorkspace*)av->m_pWorkspace;
|
||||
const auto PLAYER = (SLayerSurface*)av->m_pLayer;
|
||||
// first of all, check if we need to update it at all
|
||||
if (!av->isBeingAnimated())
|
||||
continue;
|
||||
|
||||
wlr_box WLRBOXPREV = {0,0,0,0};
|
||||
if (PWINDOW) {
|
||||
WLRBOXPREV = PWINDOW->getFullWindowBoundingBox();
|
||||
} else if (PWORKSPACE) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
||||
WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y};
|
||||
} else if (PLAYER) {
|
||||
WLRBOXPREV = PLAYER->geometry;
|
||||
if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW && !*PSHADOWSENABLED) {
|
||||
av->warp();
|
||||
continue;
|
||||
}
|
||||
|
||||
// beziers are with a switch unforto
|
||||
// TODO: maybe do something cleaner
|
||||
// get speed
|
||||
const auto SPEED = *av->m_pSpeed == 0 ? *PANIMSPEED : *av->m_pSpeed;
|
||||
|
||||
// get the spent % (0 - 1)
|
||||
const auto DURATIONPASSED = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - av->animationBegin).count();
|
||||
const float SPENT = std::clamp((DURATIONPASSED / 100.f) / SPEED, 0.f, 1.f);
|
||||
|
||||
// window stuff
|
||||
const auto PWINDOW = (CWindow*)av->m_pWindow;
|
||||
const auto PWORKSPACE = (CWorkspace*)av->m_pWorkspace;
|
||||
const auto PLAYER = (SLayerSurface*)av->m_pLayer;
|
||||
SMonitor* PMONITOR = nullptr;
|
||||
|
||||
wlr_box WLRBOXPREV = {0,0,0,0};
|
||||
if (PWINDOW) {
|
||||
WLRBOXPREV = PWINDOW->getFullWindowBoundingBox();
|
||||
PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
||||
} else if (PWORKSPACE) {
|
||||
PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
||||
WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y};
|
||||
} 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);
|
||||
}
|
||||
|
||||
// beziers are with a switch unforto
|
||||
// TODO: maybe do something cleaner
|
||||
|
||||
switch (av->m_eVarType) {
|
||||
case AVARTYPE_FLOAT: {
|
||||
if (!deltazero(av->m_fValue, av->m_fGoal)) {
|
||||
|
||||
// for disabled anims just warp
|
||||
if (av->m_pEnabled == 0 || animationsDisabled) {
|
||||
av->warp();
|
||||
break;
|
||||
}
|
||||
|
||||
const auto DELTA = av->m_fGoal - av->m_fBegun;
|
||||
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
|
||||
|
||||
if (BEZIER != m_mBezierCurves.end())
|
||||
av->m_fValue = av->m_fBegun + BEZIER->second.getYForPoint(SPENT) * DELTA;
|
||||
else
|
||||
av->m_fValue = av->m_fBegun + DEFAULTBEZIER->second.getYForPoint(SPENT) * DELTA;
|
||||
|
||||
if (SPENT >= 1.f) {
|
||||
av->warp();
|
||||
}
|
||||
} else {
|
||||
continue; // dont process
|
||||
// for disabled anims just warp
|
||||
if (*av->m_pEnabled == 0 || animationsDisabled) {
|
||||
av->warp();
|
||||
break;
|
||||
}
|
||||
|
||||
if (SPENT >= 1.f) {
|
||||
av->warp();
|
||||
break;
|
||||
}
|
||||
|
||||
const auto DELTA = av->m_fGoal - av->m_fBegun;
|
||||
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
|
||||
|
||||
if (BEZIER != m_mBezierCurves.end())
|
||||
av->m_fValue = av->m_fBegun + BEZIER->second.getYForPoint(SPENT) * DELTA;
|
||||
else
|
||||
av->m_fValue = av->m_fBegun + DEFAULTBEZIER->second.getYForPoint(SPENT) * DELTA;
|
||||
break;
|
||||
}
|
||||
case AVARTYPE_VECTOR: {
|
||||
if (!deltazero(av->m_vValue, av->m_vGoal)) {
|
||||
|
||||
// for disabled anims just warp
|
||||
if (av->m_pEnabled == 0 || animationsDisabled) {
|
||||
av->warp();
|
||||
break;
|
||||
}
|
||||
|
||||
const auto DELTA = av->m_vGoal - av->m_vBegun;
|
||||
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
|
||||
|
||||
if (BEZIER != m_mBezierCurves.end())
|
||||
av->m_vValue = av->m_vBegun + DELTA * BEZIER->second.getYForPoint(SPENT);
|
||||
else
|
||||
av->m_vValue = av->m_vBegun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT);
|
||||
|
||||
if (SPENT >= 1.f) {
|
||||
av->warp();
|
||||
}
|
||||
} else {
|
||||
continue; // dont process
|
||||
// for disabled anims just warp
|
||||
if (*av->m_pEnabled == 0 || animationsDisabled) {
|
||||
av->warp();
|
||||
break;
|
||||
}
|
||||
|
||||
if (SPENT >= 1.f) {
|
||||
av->warp();
|
||||
break;
|
||||
}
|
||||
|
||||
const auto DELTA = av->m_vGoal - av->m_vBegun;
|
||||
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
|
||||
|
||||
if (BEZIER != m_mBezierCurves.end())
|
||||
av->m_vValue = av->m_vBegun + DELTA * BEZIER->second.getYForPoint(SPENT);
|
||||
else
|
||||
av->m_vValue = av->m_vBegun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT);
|
||||
break;
|
||||
}
|
||||
case AVARTYPE_COLOR: {
|
||||
if (!deltazero(av->m_cValue, av->m_cGoal)) {
|
||||
|
||||
// for disabled anims just warp
|
||||
if (av->m_pEnabled == 0 || animationsDisabled) {
|
||||
av->warp();
|
||||
break;
|
||||
}
|
||||
|
||||
const auto DELTA = av->m_cGoal - av->m_cBegun;
|
||||
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
|
||||
|
||||
if (BEZIER != m_mBezierCurves.end())
|
||||
av->m_cValue = av->m_cBegun + DELTA * BEZIER->second.getYForPoint(SPENT);
|
||||
else
|
||||
av->m_cValue = av->m_cBegun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT);
|
||||
|
||||
if (SPENT >= 1.f) {
|
||||
av->warp();
|
||||
}
|
||||
} else {
|
||||
continue; // dont process
|
||||
// for disabled anims just warp
|
||||
if (*av->m_pEnabled == 0 || animationsDisabled) {
|
||||
av->warp();
|
||||
break;
|
||||
}
|
||||
|
||||
if (SPENT >= 1.f) {
|
||||
av->warp();
|
||||
break;
|
||||
}
|
||||
|
||||
const auto DELTA = av->m_cGoal - av->m_cBegun;
|
||||
const auto BEZIER = m_mBezierCurves.find(*av->m_pBezier);
|
||||
|
||||
if (BEZIER != m_mBezierCurves.end())
|
||||
av->m_cValue = av->m_cBegun + DELTA * BEZIER->second.getYForPoint(SPENT);
|
||||
else
|
||||
av->m_cValue = av->m_cBegun + DELTA * DEFAULTBEZIER->second.getYForPoint(SPENT);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -152,14 +154,14 @@ void CAnimationManager::tick() {
|
||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||
PWINDOW->updateWindowDecos();
|
||||
} else if (PWORKSPACE) {
|
||||
for (auto& w : g_pCompositor->m_lWindows) {
|
||||
if (!w.m_bIsMapped || w.m_bHidden)
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (!w->m_bIsMapped || w->m_bHidden)
|
||||
continue;
|
||||
|
||||
if (w.m_iWorkspaceID != PWORKSPACE->m_iID)
|
||||
if (w->m_iWorkspaceID != PWORKSPACE->m_iID)
|
||||
continue;
|
||||
|
||||
w.updateWindowDecos();
|
||||
w->updateWindowDecos();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -185,6 +187,35 @@ void CAnimationManager::tick() {
|
||||
g_pHyprRenderer->damageBox(WLRBOXNEW.x + WLRBOXNEW.width - ROUNDINGSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXNEW.height + 2 * BORDERSIZE); // right
|
||||
g_pHyprRenderer->damageBox(WLRBOXNEW.x, WLRBOXNEW.y + WLRBOXNEW.height - ROUNDINGSIZE, WLRBOXNEW.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // bottom
|
||||
|
||||
break;
|
||||
} 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);
|
||||
|
||||
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 {
|
||||
pixman_region32_t rg;
|
||||
pixman_region32_init_rect(&rg, dmg.x, dmg.y, dmg.width, dmg.height);
|
||||
pixman_region32_t wb;
|
||||
pixman_region32_init_rect(&wb, PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealSize.vec().y);
|
||||
pixman_region32_subtract(&rg, &rg, &wb);
|
||||
g_pHyprRenderer->damageRegion(&rg);
|
||||
pixman_region32_fini(&rg);
|
||||
pixman_region32_fini(&wb);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -195,8 +226,11 @@ void CAnimationManager::tick() {
|
||||
|
||||
|
||||
// set size and pos if valid, but only if damage policy entire (dont if border for example)
|
||||
if (g_pCompositor->windowValidMapped(PWINDOW) && av->m_eDamagePolicy == AVARDAMAGE_ENTIRE)
|
||||
if (g_pCompositor->windowValidMapped(PWINDOW) && av->m_eDamagePolicy == AVARDAMAGE_ENTIRE && PWINDOW->m_iX11Type != 2)
|
||||
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv());
|
||||
|
||||
// manually schedule a frame
|
||||
g_pCompositor->scheduleFrameForMonitor(PMONITOR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,7 +344,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.find(' ') != std::string::npos) {
|
||||
if (pWindow->m_sAdditionalConfigData.animationStyle.contains(' ')) {
|
||||
// has a direction
|
||||
animationSlide(pWindow, pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find(' ') + 1), close);
|
||||
} else {
|
||||
|
@@ -87,7 +87,7 @@ void CEventManager::startThread() {
|
||||
|
||||
// write all queued events
|
||||
for (auto& ev : m_dQueuedEvents) {
|
||||
std::string eventString = ev.event + ">>" + ev.data + "\n";
|
||||
std::string eventString = (ev.event + ">>" + ev.data).substr(0, 1022) + "\n";
|
||||
for (auto& fd : m_dAcceptedSocketFDs) {
|
||||
write(fd, eventString.c_str(), eventString.length());
|
||||
}
|
||||
@@ -104,9 +104,9 @@ void CEventManager::startThread() {
|
||||
}).detach();
|
||||
}
|
||||
|
||||
void CEventManager::postEvent(const SHyprIPCEvent event) {
|
||||
void CEventManager::postEvent(const SHyprIPCEvent event, bool force) {
|
||||
|
||||
if (m_bIgnoreEvents) {
|
||||
if (m_bIgnoreEvents && !force) {
|
||||
Debug::log(WARN, "Suppressed (ignoreevents true) event of type %s, content: %s",event.event.c_str(), event.data.c_str());
|
||||
return;
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@ class CEventManager {
|
||||
public:
|
||||
CEventManager();
|
||||
|
||||
void postEvent(const SHyprIPCEvent event);
|
||||
void postEvent(const SHyprIPCEvent event, bool force = false);
|
||||
|
||||
void startThread();
|
||||
|
||||
|
@@ -30,66 +30,209 @@ CKeybindManager::CKeybindManager() {
|
||||
m_mDispatchers["resizeactive"] = resizeActive;
|
||||
m_mDispatchers["moveactive"] = moveActive;
|
||||
m_mDispatchers["cyclenext"] = circleNext;
|
||||
m_mDispatchers["focuswindowbyclass"] = focusWindowByClass;
|
||||
m_mDispatchers["focuswindowbyclass"] = focusWindow;
|
||||
m_mDispatchers["focuswindow"] = focusWindow;
|
||||
m_mDispatchers["submap"] = setSubmap;
|
||||
m_mDispatchers["pass"] = pass;
|
||||
}
|
||||
|
||||
void CKeybindManager::addKeybind(SKeybind kb) {
|
||||
m_lKeybinds.push_back(kb);
|
||||
|
||||
m_pActiveKeybind = nullptr;
|
||||
}
|
||||
|
||||
void CKeybindManager::removeKeybind(uint32_t mod, const std::string& key) {
|
||||
for (auto it = m_lKeybinds.begin(); it != m_lKeybinds.end(); ++it) {
|
||||
if (it->modmask == mod && it->key == key) {
|
||||
if (isNumber(key) && std::stoi(key) > 9) {
|
||||
const auto KEYNUM = std::stoi(key);
|
||||
|
||||
if (it->modmask == mod && it->keycode == KEYNUM) {
|
||||
it = m_lKeybinds.erase(it);
|
||||
|
||||
if (it == m_lKeybinds.end())
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (it->modmask == mod && it->key == key) {
|
||||
it = m_lKeybinds.erase(it);
|
||||
|
||||
if (it == m_lKeybinds.end())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_pActiveKeybind = nullptr;
|
||||
}
|
||||
|
||||
uint32_t CKeybindManager::stringToModMask(std::string mods) {
|
||||
uint32_t modMask = 0;
|
||||
if (mods.find("SHIFT") != std::string::npos)
|
||||
if (mods.contains("SHIFT"))
|
||||
modMask |= WLR_MODIFIER_SHIFT;
|
||||
if (mods.find("CAPS") != std::string::npos)
|
||||
if (mods.contains("CAPS"))
|
||||
modMask |= WLR_MODIFIER_CAPS;
|
||||
if (mods.find("CTRL") != std::string::npos || mods.find("CONTROL") != std::string::npos)
|
||||
if (mods.contains("CTRL") || mods.contains("CONTROL"))
|
||||
modMask |= WLR_MODIFIER_CTRL;
|
||||
if (mods.find("ALT") != std::string::npos)
|
||||
if (mods.contains("ALT"))
|
||||
modMask |= WLR_MODIFIER_ALT;
|
||||
if (mods.find("MOD2") != std::string::npos)
|
||||
if (mods.contains("MOD2"))
|
||||
modMask |= WLR_MODIFIER_MOD2;
|
||||
if (mods.find("MOD3") != std::string::npos)
|
||||
if (mods.contains("MOD3"))
|
||||
modMask |= WLR_MODIFIER_MOD3;
|
||||
if (mods.find("SUPER") != std::string::npos || mods.find("WIN") != std::string::npos || mods.find("LOGO") != std::string::npos || mods.find("MOD4") != std::string::npos)
|
||||
if (mods.contains("SUPER") || mods.contains("WIN") || mods.contains("LOGO") || mods.contains("MOD4"))
|
||||
modMask |= WLR_MODIFIER_LOGO;
|
||||
if (mods.find("MOD5") != std::string::npos)
|
||||
if (mods.contains("MOD5"))
|
||||
modMask |= WLR_MODIFIER_MOD5;
|
||||
|
||||
return modMask;
|
||||
}
|
||||
|
||||
bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t& key) {
|
||||
bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) {
|
||||
const auto KEYCODE = e->keycode + 8; // Because to xkbcommon it's +8 from libinput
|
||||
|
||||
const xkb_keysym_t keysym = xkb_state_key_get_one_sym(wlr_keyboard_from_input_device(pKeyboard->keyboard)->xkb_state, KEYCODE);
|
||||
|
||||
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
|
||||
|
||||
m_uTimeLastMs = e->time_msec;
|
||||
m_uLastCode = KEYCODE;
|
||||
|
||||
bool found = false;
|
||||
if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
// clean repeat
|
||||
if (m_pActiveKeybindEventSource) {
|
||||
wl_event_source_remove(m_pActiveKeybindEventSource);
|
||||
m_pActiveKeybindEventSource = nullptr;
|
||||
m_pActiveKeybind = nullptr;
|
||||
}
|
||||
|
||||
m_dPressedKeycodes.push_back(KEYCODE);
|
||||
m_dPressedKeysyms.push_back(keysym);
|
||||
|
||||
found = g_pKeybindManager->handleKeybinds(MODS, "", keysym, 0, true, e->time_msec) || found;
|
||||
|
||||
found = g_pKeybindManager->handleKeybinds(MODS, "", 0, KEYCODE, true, e->time_msec) || found;
|
||||
|
||||
if (found)
|
||||
shadowKeybinds(keysym, KEYCODE);
|
||||
} else if (e->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
|
||||
// clean repeat
|
||||
if (m_pActiveKeybindEventSource) {
|
||||
wl_event_source_remove(m_pActiveKeybindEventSource);
|
||||
m_pActiveKeybindEventSource = nullptr;
|
||||
m_pActiveKeybind = nullptr;
|
||||
}
|
||||
|
||||
m_dPressedKeycodes.erase(std::remove(m_dPressedKeycodes.begin(), m_dPressedKeycodes.end(), KEYCODE));
|
||||
m_dPressedKeysyms.erase(std::remove(m_dPressedKeysyms.begin(), m_dPressedKeysyms.end(), keysym));
|
||||
|
||||
found = g_pKeybindManager->handleKeybinds(MODS, "", keysym, 0, false, e->time_msec) || found;
|
||||
|
||||
found = g_pKeybindManager->handleKeybinds(MODS, "", 0, KEYCODE, false, e->time_msec) || found;
|
||||
|
||||
shadowKeybinds();
|
||||
}
|
||||
|
||||
return !found;
|
||||
}
|
||||
|
||||
bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) {
|
||||
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
|
||||
|
||||
bool found = false;
|
||||
if (e->source == WLR_AXIS_SOURCE_WHEEL && e->orientation == WLR_AXIS_ORIENTATION_VERTICAL) {
|
||||
if (e->delta < 0) {
|
||||
found = g_pKeybindManager->handleKeybinds(MODS, "mouse_down", 0, 0, true, 0);
|
||||
} else {
|
||||
found = g_pKeybindManager->handleKeybinds(MODS, "mouse_up", 0, 0, true, 0);
|
||||
}
|
||||
|
||||
if (found)
|
||||
shadowKeybinds();
|
||||
}
|
||||
|
||||
return !found;
|
||||
}
|
||||
|
||||
bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) {
|
||||
const auto MODS = g_pInputManager->accumulateModsFromAllKBs();
|
||||
|
||||
bool found = false;
|
||||
|
||||
if (handleInternalKeybinds(key))
|
||||
if (e->state == WLR_BUTTON_PRESSED) {
|
||||
found = g_pKeybindManager->handleKeybinds(MODS, "mouse:" + std::to_string(e->button), 0, 0, true, 0);
|
||||
|
||||
if (found)
|
||||
shadowKeybinds();
|
||||
} else {
|
||||
found = g_pKeybindManager->handleKeybinds(MODS, "mouse:" + std::to_string(e->button), 0, 0, false, 0);
|
||||
|
||||
shadowKeybinds();
|
||||
}
|
||||
|
||||
return !found;
|
||||
}
|
||||
|
||||
int repeatKeyHandler(void* data) {
|
||||
SKeybind** ppActiveKeybind = (SKeybind**)data;
|
||||
|
||||
if (!*ppActiveKeybind)
|
||||
return 0;
|
||||
|
||||
const auto DISPATCHER = g_pKeybindManager->m_mDispatchers.find((*ppActiveKeybind)->handler);
|
||||
|
||||
Debug::log(LOG, "Keybind repeat triggered, calling dispatcher.");
|
||||
DISPATCHER->second((*ppActiveKeybind)->arg);
|
||||
|
||||
wl_event_source_timer_update(g_pKeybindManager->m_pActiveKeybindEventSource, 1000 / g_pInputManager->m_pActiveKeyboard->repeatRate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string& key, const xkb_keysym_t& keysym, const int& keycode, bool pressed, uint32_t time) {
|
||||
bool found = false;
|
||||
|
||||
if (handleInternalKeybinds(keysym))
|
||||
return true;
|
||||
|
||||
if (g_pCompositor->m_sSeat.exclusiveClient)
|
||||
Debug::log(LOG, "Keybind handling only locked (inhibitor)");
|
||||
|
||||
if (pressed && m_kHeldBack) {
|
||||
// release the held back event
|
||||
wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, time, m_kHeldBack, WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||
m_kHeldBack = 0;
|
||||
}
|
||||
|
||||
for (auto& k : m_lKeybinds) {
|
||||
if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap)
|
||||
if (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || (!pressed && !k.release) || k.shadowed)
|
||||
continue;
|
||||
|
||||
// oMg such performance hit!!11!
|
||||
// this little maneouver is gonna cost us 4µs
|
||||
const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
|
||||
const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY);
|
||||
// small TODO: fix 0-9 keys and other modified ones with shift
|
||||
|
||||
if (key != KBKEY && key != KBKEYUPPER)
|
||||
continue;
|
||||
if (!key.empty()) {
|
||||
if (key != k.key)
|
||||
continue;
|
||||
} else if (k.keycode != -1) {
|
||||
if (keycode != k.keycode)
|
||||
continue;
|
||||
} else {
|
||||
if (keysym == 0)
|
||||
continue; // this is a keycode check run
|
||||
|
||||
// oMg such performance hit!!11!
|
||||
// this little maneouver is gonna cost us 4µs
|
||||
const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
|
||||
const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY);
|
||||
// small TODO: fix 0-9 keys and other modified ones with shift
|
||||
|
||||
if (keysym != KBKEY && keysym != KBKEYUPPER)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pressed && k.release) {
|
||||
// suppress down event
|
||||
m_kHeldBack = keysym;
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto DISPATCHER = m_mDispatchers.find(k.handler);
|
||||
|
||||
@@ -98,16 +241,61 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const xkb_keysym_t
|
||||
Debug::log(ERR, "Inavlid handler in a keybind! (handler %s does not exist)", k.handler.c_str());
|
||||
} else {
|
||||
// call the dispatcher
|
||||
Debug::log(LOG, "Keybind triggered, calling dispatcher (%d, %d)", modmask, KBKEYUPPER);
|
||||
Debug::log(LOG, "Keybind triggered, calling dispatcher (%d, %s, %d)", modmask, key, keysym);
|
||||
DISPATCHER->second(k.arg);
|
||||
}
|
||||
|
||||
if (k.repeat) {
|
||||
m_pActiveKeybind = &k;
|
||||
m_pActiveKeybindEventSource = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, repeatKeyHandler, &m_pActiveKeybind);
|
||||
|
||||
const auto PACTIVEKEEB = g_pInputManager->m_pActiveKeyboard;
|
||||
|
||||
wl_event_source_timer_update(m_pActiveKeybindEventSource, PACTIVEKEEB->repeatDelay);
|
||||
}
|
||||
|
||||
found = true;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const int& doesntHaveCode) {
|
||||
// shadow disables keybinds after one has been triggered
|
||||
|
||||
for (auto& k : m_lKeybinds) {
|
||||
|
||||
bool shadow = false;
|
||||
|
||||
const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE);
|
||||
const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY);
|
||||
|
||||
for (auto& pk : m_dPressedKeysyms) {
|
||||
if ((pk == KBKEY || pk == KBKEYUPPER)) {
|
||||
shadow = true;
|
||||
|
||||
if (pk == doesntHave && doesntHave != 0) {
|
||||
shadow = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& pk : m_dPressedKeycodes) {
|
||||
if (pk == k.keycode) {
|
||||
shadow = true;
|
||||
|
||||
if (pk == doesntHaveCode && doesntHaveCode != 0 && doesntHaveCode != -1) {
|
||||
shadow = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
k.shadowed = shadow;
|
||||
}
|
||||
}
|
||||
|
||||
bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
|
||||
// Handles the CTRL+ALT+FX TTY keybinds
|
||||
if (!(keysym >= XKB_KEY_XF86Switch_VT_1 && keysym <= XKB_KEY_XF86Switch_VT_12))
|
||||
@@ -117,11 +305,11 @@ bool CKeybindManager::handleVT(xkb_keysym_t keysym) {
|
||||
if (PSESSION) {
|
||||
const int TTY = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
|
||||
wlr_session_change_vt(PSESSION, TTY);
|
||||
g_pCompositor->m_bSessionActive = false;
|
||||
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
g_pHyprOpenGL->destroyMonitorResources(&m); // mark resources as unusable anymore
|
||||
m.noFrameSchedule = true;
|
||||
m.framesToSkip = 2;
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
m->noFrameSchedule = true;
|
||||
m->framesToSkip = 1;
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Switched to VT %i, destroyed all render data, frames to skip for each: 2", TTY);
|
||||
@@ -207,7 +395,7 @@ void CKeybindManager::killActive(std::string args) {
|
||||
g_pXWaylandManager->sendCloseWindow(g_pCompositor->m_pLastWindow);
|
||||
g_pCompositor->m_pLastFocus = nullptr;
|
||||
g_pCompositor->m_pLastWindow = nullptr;
|
||||
g_pEventManager->postEvent(SHyprIPCEvent("activewindow", ",")); // post an activewindow event to empty, as we are currently unfocused
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); // post an activewindow event to empty, as we are currently unfocused
|
||||
}
|
||||
|
||||
g_pCompositor->focusWindow(g_pCompositor->windowFromCursor());
|
||||
@@ -221,15 +409,15 @@ void CKeybindManager::toggleActiveFloating(std::string args) {
|
||||
const auto ACTIVEWINDOW = g_pCompositor->m_pLastWindow;
|
||||
|
||||
if (g_pCompositor->windowValidMapped(ACTIVEWINDOW)) {
|
||||
// remove drag status
|
||||
g_pInputManager->currentlyDraggedWindow = nullptr;
|
||||
|
||||
ACTIVEWINDOW->m_bIsFloating = !ACTIVEWINDOW->m_bIsFloating;
|
||||
|
||||
if (ACTIVEWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) {
|
||||
moveActiveToWorkspace(std::to_string(g_pCompositor->getMonitorFromID(ACTIVEWINDOW->m_iMonitorID)->activeWorkspace));
|
||||
}
|
||||
|
||||
ACTIVEWINDOW->m_vRealPosition.setValue(ACTIVEWINDOW->m_vRealPosition.vec() + Vector2D(5, 5));
|
||||
ACTIVEWINDOW->m_vSize = ACTIVEWINDOW->m_vRealPosition.vec() - Vector2D(10, 10);
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(ACTIVEWINDOW);
|
||||
}
|
||||
}
|
||||
@@ -249,7 +437,14 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
int workspaceToChangeTo = 0;
|
||||
std::string workspaceName = "";
|
||||
|
||||
workspaceToChangeTo = getWorkspaceIDFromString(args, workspaceName);
|
||||
if (args.find("[internal]") == 0) {
|
||||
workspaceToChangeTo = std::stoi(args.substr(10));
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceToChangeTo);
|
||||
if (PWORKSPACE)
|
||||
workspaceName = PWORKSPACE->m_szName;
|
||||
} else {
|
||||
workspaceToChangeTo = getWorkspaceIDFromString(args, workspaceName);
|
||||
}
|
||||
|
||||
if (workspaceToChangeTo == INT_MAX) {
|
||||
Debug::log(ERR, "Error in changeworkspace, invalid value");
|
||||
@@ -273,8 +468,6 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
const auto OLDWORKSPACEID = PMONITOR->activeWorkspace;
|
||||
|
||||
// change it
|
||||
PMONITOR->specialWorkspaceOpen = false;
|
||||
|
||||
if (workspaceToChangeTo != SPECIAL_WORKSPACE_ID)
|
||||
PMONITOR->activeWorkspace = workspaceToChangeTo;
|
||||
else
|
||||
@@ -297,7 +490,7 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
// start anim on new workspace
|
||||
PWORKSPACETOCHANGETO->startAnim(true, ANIMTOLEFT);
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent("workspace", PWORKSPACETOCHANGETO->m_szName));
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"workspace", PWORKSPACETOCHANGETO->m_szName});
|
||||
}
|
||||
|
||||
// If the monitor is not the one our cursor's at, warp to it.
|
||||
@@ -336,8 +529,7 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
if (const auto POLDWORKSPACE = g_pCompositor->getWorkspaceByID(OLDWORKSPACE); POLDWORKSPACE)
|
||||
POLDWORKSPACE->startAnim(false, ANIMTOLEFT);
|
||||
|
||||
g_pCompositor->m_lWorkspaces.emplace_back(PMONITOR->ID, workspaceName, workspaceToChangeTo == SPECIAL_WORKSPACE_ID);
|
||||
const auto PWORKSPACE = &g_pCompositor->m_lWorkspaces.back();
|
||||
const auto PWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(PMONITOR->ID, workspaceName, workspaceToChangeTo == SPECIAL_WORKSPACE_ID)).get();
|
||||
|
||||
// start anim on new workspace
|
||||
PWORKSPACE->startAnim(true, ANIMTOLEFT);
|
||||
@@ -371,7 +563,7 @@ void CKeybindManager::changeworkspace(std::string args) {
|
||||
g_pInputManager->refocus();
|
||||
|
||||
// Event
|
||||
g_pEventManager->postEvent(SHyprIPCEvent("workspace", PWORKSPACE->m_szName));
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"workspace", PWORKSPACE->m_szName});
|
||||
|
||||
Debug::log(LOG, "Changed to workspace %i", workspaceToChangeTo);
|
||||
}
|
||||
@@ -402,6 +594,9 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto PSAVEDSIZE = PWINDOW->m_vRealSize.vec();
|
||||
auto PSAVEDPOS = PWINDOW->m_vRealPosition.vec();
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
|
||||
|
||||
g_pKeybindManager->changeworkspace(args);
|
||||
@@ -429,32 +624,33 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) {
|
||||
PWORKSPACE->m_bHasFullscreenWindow = false;
|
||||
}
|
||||
|
||||
if (PWINDOW->m_bIsFullscreen) {
|
||||
PWINDOW->m_bIsFullscreen = false;
|
||||
PSAVEDPOS = PSAVEDPOS + Vector2D(10, 10);
|
||||
PSAVEDSIZE = PSAVEDSIZE - Vector2D(20, 20);
|
||||
}
|
||||
|
||||
// Hack: So that the layout doesnt find our window at the cursor
|
||||
PWINDOW->m_vPosition = Vector2D(-42069, -42069);
|
||||
|
||||
// Save the real position and size because the layout might set its own
|
||||
const auto PSAVEDSIZE = PWINDOW->m_vRealSize.vec();
|
||||
const auto PSAVEDPOS = PWINDOW->m_vRealPosition.vec();
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
|
||||
// and restore it
|
||||
PWINDOW->m_vRealPosition.setValue(PSAVEDPOS);
|
||||
PWINDOW->m_vRealSize.setValue(PSAVEDSIZE);
|
||||
|
||||
// and restore it
|
||||
if (PWINDOW->m_bIsFloating) {
|
||||
PWINDOW->m_vRealPosition.setValue(PWINDOW->m_vRealPosition.vec() - g_pCompositor->getMonitorFromID(OLDWORKSPACE->m_iMonitorID)->vecPosition);
|
||||
PWINDOW->m_vRealPosition.setValue(PWINDOW->m_vRealPosition.vec() + g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID)->vecPosition);
|
||||
PWINDOW->m_vRealSize.setValue(PSAVEDSIZE);
|
||||
PWINDOW->m_vRealPosition.setValueAndWarp(PSAVEDPOS - g_pCompositor->getMonitorFromID(OLDWORKSPACE->m_iMonitorID)->vecPosition + g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID)->vecPosition);
|
||||
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec();
|
||||
}
|
||||
|
||||
// undo the damage if we are moving to the special workspace
|
||||
if (WORKSPACEID == SPECIAL_WORKSPACE_ID) {
|
||||
changeworkspace(std::to_string(OLDWORKSPACE->m_iID));
|
||||
changeworkspace("[internal]" + std::to_string(OLDWORKSPACE->m_iID));
|
||||
OLDWORKSPACE->startAnim(true, true, true);
|
||||
toggleSpecialWorkspace("");
|
||||
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false, true);
|
||||
|
||||
for (auto& m : g_pCompositor->m_lMonitors)
|
||||
m.specialWorkspaceOpen = false;
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
m->specialWorkspaceOpen = false;
|
||||
}
|
||||
|
||||
g_pInputManager->refocus();
|
||||
@@ -500,8 +696,8 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) {
|
||||
|
||||
PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceToMoveTo);
|
||||
|
||||
changeworkspace(std::to_string(OLDWORKSPACEIDONMONITOR));
|
||||
changeworkspace(std::to_string(OLDWORKSPACEIDRETURN));
|
||||
changeworkspace("[internal]" + std::to_string(OLDWORKSPACEIDONMONITOR));
|
||||
changeworkspace("[internal]" + std::to_string(OLDWORKSPACEIDRETURN));
|
||||
|
||||
// revert animations
|
||||
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0,0));
|
||||
@@ -659,8 +855,8 @@ void CKeybindManager::focusMonitor(std::string arg) {
|
||||
Debug::log(ERR, "Error in focusMonitor: invalid num");
|
||||
}
|
||||
|
||||
if (monID > -1 && monID < (int)g_pCompositor->m_lMonitors.size()) {
|
||||
changeworkspace(std::to_string(g_pCompositor->getMonitorFromID(monID)->activeWorkspace));
|
||||
if (monID > -1 && monID < (int)g_pCompositor->m_vMonitors.size()) {
|
||||
changeworkspace("[internal]" + std::to_string(g_pCompositor->getMonitorFromID(monID)->activeWorkspace));
|
||||
} else {
|
||||
Debug::log(ERR, "Error in focusMonitor: invalid arg 1");
|
||||
}
|
||||
@@ -678,9 +874,9 @@ void CKeybindManager::focusMonitor(std::string arg) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
if (m.szName == arg) {
|
||||
changeworkspace(std::to_string(m.activeWorkspace));
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->szName == arg) {
|
||||
changeworkspace("[internal]" + std::to_string(m->activeWorkspace));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -740,11 +936,11 @@ void CKeybindManager::workspaceOpt(std::string args) {
|
||||
PWORKSPACE->m_bDefaultPseudo = !PWORKSPACE->m_bDefaultPseudo;
|
||||
|
||||
// apply
|
||||
for (auto& w : g_pCompositor->m_lWindows) {
|
||||
if (!w.m_bIsMapped || w.m_iWorkspaceID != PWORKSPACE->m_iID)
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (!w->m_bIsMapped || w->m_iWorkspaceID != PWORKSPACE->m_iID)
|
||||
continue;
|
||||
|
||||
w.m_bIsPseudotiled = PWORKSPACE->m_bDefaultPseudo;
|
||||
w->m_bIsPseudotiled = PWORKSPACE->m_bDefaultPseudo;
|
||||
}
|
||||
} else if (args == "allfloat") {
|
||||
PWORKSPACE->m_bDefaultFloating = !PWORKSPACE->m_bDefaultFloating;
|
||||
@@ -752,8 +948,8 @@ void CKeybindManager::workspaceOpt(std::string args) {
|
||||
|
||||
// we make a copy because changeWindowFloatingMode might invalidate the iterator
|
||||
std::deque<CWindow*> ptrs;
|
||||
for (auto& w : g_pCompositor->m_lWindows)
|
||||
ptrs.push_back(&w);
|
||||
for (auto& w : g_pCompositor->m_vWindows)
|
||||
ptrs.push_back(w.get());
|
||||
|
||||
for (auto& w : ptrs) {
|
||||
if (!w->m_bIsMapped || w->m_iWorkspaceID != PWORKSPACE->m_iID)
|
||||
@@ -785,20 +981,20 @@ void CKeybindManager::workspaceOpt(std::string args) {
|
||||
}
|
||||
|
||||
void CKeybindManager::exitHyprland(std::string argz) {
|
||||
g_pCompositor->cleanupExit();
|
||||
exit(0);
|
||||
g_pCompositor->cleanup();
|
||||
}
|
||||
|
||||
void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
|
||||
if (!isNumber(args) && !isDirection(args)) {
|
||||
Debug::log(ERR, "moveCurrentWorkspaceToMonitor arg not a number or direction!");
|
||||
return;
|
||||
}
|
||||
SMonitor* PMONITOR = nullptr;
|
||||
|
||||
const auto PMONITOR = isDirection(args) ? g_pCompositor->getMonitorInDirection(args[0]) : g_pCompositor->getMonitorFromID(std::stoi(args));
|
||||
|
||||
if (!PMONITOR) {
|
||||
Debug::log(ERR, "Ignoring moveCurrentWorkspaceToMonitor: monitor doesnt exist");
|
||||
try {
|
||||
if (!isNumber(args) && !isDirection(args)) {
|
||||
PMONITOR = g_pCompositor->getMonitorFromName(args);
|
||||
} else {
|
||||
PMONITOR = isDirection(args) ? g_pCompositor->getMonitorInDirection(args[0]) : g_pCompositor->getMonitorFromID(std::stoi(args));
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
Debug::log(LOG, "moveCurrentWorkspaceToMonitor: caught exception in monitor", e.what());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -812,18 +1008,25 @@ void CKeybindManager::moveCurrentWorkspaceToMonitor(std::string args) {
|
||||
}
|
||||
|
||||
void CKeybindManager::moveWorkspaceToMonitor(std::string args) {
|
||||
if (args.find_first_of(' ') == std::string::npos)
|
||||
if (!args.contains(' '))
|
||||
return;
|
||||
|
||||
std::string workspace = args.substr(0, args.find_first_of(' '));
|
||||
std::string monitor = args.substr(args.find_first_of(' ') + 1);
|
||||
|
||||
if (!isNumber(monitor) && !isDirection(monitor)) {
|
||||
Debug::log(ERR, "moveWorkspaceToMonitor monitor arg not a number or direction!");
|
||||
SMonitor* PMONITOR = nullptr;
|
||||
|
||||
try {
|
||||
if (!isNumber(monitor) && !isDirection(monitor)) {
|
||||
PMONITOR = g_pCompositor->getMonitorFromName(monitor);
|
||||
} else {
|
||||
PMONITOR = isDirection(monitor) ? g_pCompositor->getMonitorInDirection(monitor[0]) : g_pCompositor->getMonitorFromID(std::stoi(monitor));
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
Debug::log(LOG, "moveWorkspaceToMonitor: caught exception in monitor", e.what());
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PMONITOR = isDirection(monitor) ? g_pCompositor->getMonitorInDirection(monitor[0]) : g_pCompositor->getMonitorFromID(std::stoi(monitor));
|
||||
|
||||
|
||||
if (!PMONITOR){
|
||||
Debug::log(ERR, "Ignoring moveWorkspaceToMonitor: monitor doesnt exist");
|
||||
@@ -857,8 +1060,8 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
||||
|
||||
bool open = false;
|
||||
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
if (m.specialWorkspaceOpen) {
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->specialWorkspaceOpen) {
|
||||
open = true;
|
||||
break;
|
||||
}
|
||||
@@ -870,20 +1073,25 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
||||
Debug::log(LOG, "Toggling special workspace to open");
|
||||
|
||||
if (open) {
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
if (m.specialWorkspaceOpen != !open) {
|
||||
m.specialWorkspaceOpen = !open;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m.ID);
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (m->specialWorkspaceOpen != !open) {
|
||||
m->specialWorkspaceOpen = !open;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID);
|
||||
|
||||
g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID)->startAnim(false, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID);
|
||||
|
||||
if (!PSPECIALWORKSPACE) {
|
||||
// ??? happens sometimes...?
|
||||
PSPECIALWORKSPACE = g_pCompositor->m_vWorkspaces.emplace_back(std::make_unique<CWorkspace>(g_pCompositor->m_pLastMonitor->ID, "special", true)).get();
|
||||
}
|
||||
|
||||
g_pCompositor->m_pLastMonitor->specialWorkspaceOpen = true;
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(g_pCompositor->m_pLastMonitor->ID);
|
||||
|
||||
const auto PSPECIALWORKSPACE = g_pCompositor->getWorkspaceByID(SPECIAL_WORKSPACE_ID);
|
||||
|
||||
PSPECIALWORKSPACE->startAnim(true, true);
|
||||
PSPECIALWORKSPACE->m_iMonitorID = g_pCompositor->m_pLastMonitor->ID;
|
||||
}
|
||||
@@ -892,14 +1100,22 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) {
|
||||
}
|
||||
|
||||
void CKeybindManager::forceRendererReload(std::string args) {
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
auto rule = g_pConfigManager->getMonitorRuleFor(m.szName);
|
||||
g_pHyprRenderer->applyMonitorRule(&m, &rule, true);
|
||||
bool overAgain = false;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
auto rule = g_pConfigManager->getMonitorRuleFor(m->szName);
|
||||
if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule, true)) {
|
||||
overAgain = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (overAgain)
|
||||
forceRendererReload(args);
|
||||
}
|
||||
|
||||
void CKeybindManager::resizeActive(std::string args) {
|
||||
if (args.find_first_of(' ') == std::string::npos)
|
||||
if (!args.contains(' '))
|
||||
return;
|
||||
|
||||
std::string x = args.substr(0, args.find_first_of(' '));
|
||||
@@ -948,7 +1164,7 @@ void CKeybindManager::resizeActive(std::string args) {
|
||||
}
|
||||
|
||||
void CKeybindManager::moveActive(std::string args) {
|
||||
if (args.find_first_of(' ') == std::string::npos)
|
||||
if (!args.contains(' '))
|
||||
return;
|
||||
|
||||
std::string x = args.substr(0, args.find_first_of(' '));
|
||||
@@ -996,41 +1212,40 @@ void CKeybindManager::moveActive(std::string args) {
|
||||
g_pLayoutManager->getCurrentLayout()->moveActiveWindow(Vector2D(X, Y));
|
||||
}
|
||||
|
||||
void CKeybindManager::circleNext(std::string) {
|
||||
void CKeybindManager::circleNext(std::string arg) {
|
||||
if (!g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow))
|
||||
return;
|
||||
|
||||
g_pCompositor->focusWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow));
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastWindow->m_iWorkspaceID);
|
||||
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow)
|
||||
return;
|
||||
|
||||
if (arg == "last" || arg == "l" || arg == "prev" || arg == "p")
|
||||
g_pCompositor->focusWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow));
|
||||
else
|
||||
g_pCompositor->focusWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow));
|
||||
|
||||
const auto MIDPOINT = g_pCompositor->m_pLastWindow->m_vRealPosition.goalv() + g_pCompositor->m_pLastWindow->m_vRealSize.goalv() / 2.f;
|
||||
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, MIDPOINT.x, MIDPOINT.y);
|
||||
}
|
||||
|
||||
void CKeybindManager::focusWindowByClass(std::string clazz) {
|
||||
std::regex classCheck(clazz);
|
||||
void CKeybindManager::focusWindow(std::string regexp) {
|
||||
const auto PWINDOW = g_pCompositor->getWindowByRegex(regexp);
|
||||
|
||||
for (auto& w : g_pCompositor->m_lWindows) {
|
||||
if (!w.m_bIsMapped || w.m_bHidden)
|
||||
continue;
|
||||
if (!PWINDOW)
|
||||
return;
|
||||
|
||||
const auto windowClass = g_pXWaylandManager->getAppIDClass(&w);
|
||||
Debug::log(LOG, "Focusing to window name: %s", PWINDOW->m_szTitle.c_str());
|
||||
|
||||
if (!std::regex_search(windowClass, classCheck))
|
||||
continue;
|
||||
changeworkspace("[internal]" + std::to_string(PWINDOW->m_iWorkspaceID));
|
||||
|
||||
Debug::log(LOG, "Focusing to window name: %s", w.m_szTitle.c_str());
|
||||
g_pCompositor->focusWindow(PWINDOW);
|
||||
|
||||
changeworkspace(std::to_string(w.m_iWorkspaceID));
|
||||
const auto MIDPOINT = PWINDOW->m_vRealPosition.goalv() + PWINDOW->m_vRealSize.goalv() / 2.f;
|
||||
|
||||
g_pCompositor->focusWindow(&w);
|
||||
|
||||
const auto MIDPOINT = w.m_vRealPosition.goalv() + w.m_vRealSize.goalv() / 2.f;
|
||||
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, MIDPOINT.x, MIDPOINT.y);
|
||||
|
||||
break;
|
||||
}
|
||||
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, MIDPOINT.x, MIDPOINT.y);
|
||||
}
|
||||
|
||||
void CKeybindManager::setSubmap(std::string submap) {
|
||||
@@ -1050,3 +1265,31 @@ void CKeybindManager::setSubmap(std::string submap) {
|
||||
|
||||
Debug::log(ERR, "Cannot set submap %s, submap doesn't exist (wasn't registered!)", submap.c_str());
|
||||
}
|
||||
|
||||
void CKeybindManager::pass(std::string regexp) {
|
||||
|
||||
// find the first window passing the regex
|
||||
const auto PWINDOW = g_pCompositor->getWindowByRegex(regexp);
|
||||
|
||||
if (!PWINDOW) {
|
||||
Debug::log(ERR, "pass: window not found");
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PLASTSRF = g_pCompositor->m_pLastFocus;
|
||||
|
||||
const auto KEYBOARD = wlr_seat_get_keyboard(g_pCompositor->m_sSeat.seat);
|
||||
|
||||
if (!KEYBOARD){
|
||||
Debug::log(ERR, "No kb in pass?");
|
||||
return;
|
||||
}
|
||||
|
||||
// pass all mf shit
|
||||
wlr_seat_keyboard_notify_enter(g_pCompositor->m_sSeat.seat, g_pXWaylandManager->getWindowSurface(PWINDOW), KEYBOARD->keycodes, KEYBOARD->num_keycodes, &KEYBOARD->modifiers);
|
||||
|
||||
wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WLR_BUTTON_PRESSED);
|
||||
wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, g_pKeybindManager->m_uTimeLastMs, g_pKeybindManager->m_uLastCode - 8, WLR_BUTTON_RELEASED);
|
||||
|
||||
wlr_seat_keyboard_notify_enter(g_pCompositor->m_sSeat.seat, PLASTSRF, KEYBOARD->keycodes, KEYBOARD->num_keycodes, &KEYBOARD->modifiers);
|
||||
}
|
@@ -7,31 +7,61 @@
|
||||
#include <functional>
|
||||
|
||||
struct SKeybind {
|
||||
std::string key = 0;
|
||||
std::string key = "";
|
||||
int keycode = -1;
|
||||
uint32_t modmask = 0;
|
||||
std::string handler = "";
|
||||
std::string arg = "";
|
||||
bool locked = false;
|
||||
std::string submap = "";
|
||||
bool release = false;
|
||||
bool repeat = false;
|
||||
|
||||
// DO NOT INITIALIZE
|
||||
bool shadowed = false;
|
||||
};
|
||||
|
||||
enum eFocusWindowMode {
|
||||
MODE_CLASS_REGEX = 0,
|
||||
MODE_TITLE_REGEX,
|
||||
MODE_ADDRESS,
|
||||
MODE_PID
|
||||
};
|
||||
|
||||
class CKeybindManager {
|
||||
public:
|
||||
CKeybindManager();
|
||||
|
||||
bool handleKeybinds(const uint32_t&, const xkb_keysym_t&);
|
||||
bool onKeyEvent(wlr_keyboard_key_event*, SKeyboard*);
|
||||
bool onAxisEvent(wlr_pointer_axis_event*);
|
||||
bool onMouseEvent(wlr_pointer_button_event*);
|
||||
|
||||
void addKeybind(SKeybind);
|
||||
void removeKeybind(uint32_t, const std::string&);
|
||||
uint32_t stringToModMask(std::string);
|
||||
void clearKeybinds();
|
||||
void shadowKeybinds(const xkb_keysym_t& doesntHave = 0, const int& doesntHaveCode = 0);
|
||||
|
||||
std::unordered_map<std::string, std::function<void(std::string)>> m_mDispatchers;
|
||||
|
||||
wl_event_source* m_pActiveKeybindEventSource = nullptr;
|
||||
|
||||
private:
|
||||
std::list<SKeybind> m_lKeybinds;
|
||||
std::deque<xkb_keysym_t> m_dPressedKeysyms;
|
||||
std::deque<int> m_dPressedKeycodes;
|
||||
|
||||
inline static std::string m_szCurrentSelectedSubmap = "";
|
||||
|
||||
xkb_keysym_t m_kHeldBack = 0;
|
||||
|
||||
SKeybind* m_pActiveKeybind = nullptr;
|
||||
|
||||
uint32_t m_uTimeLastMs = 0;
|
||||
uint32_t m_uLastCode = 0;
|
||||
|
||||
bool handleKeybinds(const uint32_t&, const std::string&, const xkb_keysym_t&, const int&, bool, uint32_t);
|
||||
|
||||
bool handleInternalKeybinds(xkb_keysym_t);
|
||||
bool handleVT(xkb_keysym_t);
|
||||
|
||||
@@ -61,10 +91,11 @@ private:
|
||||
static void resizeActive(std::string);
|
||||
static void moveActive(std::string);
|
||||
static void circleNext(std::string);
|
||||
static void focusWindowByClass(std::string);
|
||||
static void focusWindow(std::string);
|
||||
static void setSubmap(std::string);
|
||||
static void pass(std::string);
|
||||
|
||||
friend class CCompositor;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CKeybindManager> g_pKeybindManager;
|
||||
inline std::unique_ptr<CKeybindManager> g_pKeybindManager;
|
||||
|
@@ -4,8 +4,28 @@ IHyprLayout* CLayoutManager::getCurrentLayout() {
|
||||
switch (m_iCurrentLayoutID) {
|
||||
case DWINDLE:
|
||||
return &m_cDwindleLayout;
|
||||
case MASTER:
|
||||
return &m_cMasterLayout;
|
||||
}
|
||||
|
||||
// fallback
|
||||
return &m_cDwindleLayout;
|
||||
}
|
||||
|
||||
void CLayoutManager::switchToLayout(std::string layout) {
|
||||
if (layout == "dwindle") {
|
||||
if (m_iCurrentLayoutID != DWINDLE) {
|
||||
getCurrentLayout()->onDisable();
|
||||
m_iCurrentLayoutID = DWINDLE;
|
||||
getCurrentLayout()->onEnable();
|
||||
}
|
||||
} else if (layout == "master") {
|
||||
if (m_iCurrentLayoutID != MASTER) {
|
||||
getCurrentLayout()->onDisable();
|
||||
m_iCurrentLayoutID = MASTER;
|
||||
getCurrentLayout()->onEnable();
|
||||
}
|
||||
} else {
|
||||
Debug::log(ERR, "Unknown layout %s!", layout.c_str());
|
||||
}
|
||||
}
|
@@ -1,20 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "../layout/DwindleLayout.hpp"
|
||||
#include "../layout/MasterLayout.hpp"
|
||||
|
||||
class CLayoutManager {
|
||||
public:
|
||||
|
||||
IHyprLayout* getCurrentLayout();
|
||||
|
||||
void switchToLayout(std::string);
|
||||
|
||||
private:
|
||||
enum HYPRLAYOUTS {
|
||||
DWINDLE = 0,
|
||||
MASTER
|
||||
};
|
||||
|
||||
HYPRLAYOUTS m_iCurrentLayoutID = DWINDLE;
|
||||
|
||||
CHyprDwindleLayout m_cDwindleLayout;
|
||||
CHyprMasterLayout m_cMasterLayout;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CLayoutManager> g_pLayoutManager;
|
@@ -1,34 +1,29 @@
|
||||
#include "ThreadManager.hpp"
|
||||
#include "../debug/HyprCtl.hpp"
|
||||
|
||||
CThreadManager::CThreadManager() {
|
||||
m_tMainThread = new std::thread([&]() {
|
||||
// Call the handle method.
|
||||
this->handle();
|
||||
});
|
||||
|
||||
m_tMainThread->detach(); // detach and continue.
|
||||
}
|
||||
|
||||
CThreadManager::~CThreadManager() {
|
||||
//
|
||||
}
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
int slowUpdate = 0;
|
||||
|
||||
void CThreadManager::handle() {
|
||||
int handleTimer(void* data) {
|
||||
const auto PTM = (CThreadManager*)data;
|
||||
|
||||
g_pConfigManager->tick();
|
||||
|
||||
wl_event_source_timer_update(PTM->m_esConfigTimer, 1000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CThreadManager::CThreadManager() {
|
||||
g_pConfigManager->init();
|
||||
|
||||
HyprCtl::startHyprCtlSocket();
|
||||
|
||||
while (3.1415f) {
|
||||
slowUpdate++;
|
||||
if (slowUpdate >= g_pConfigManager->getInt("general:max_fps")){
|
||||
g_pConfigManager->tick();
|
||||
slowUpdate = 0;
|
||||
}
|
||||
m_esConfigTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, handleTimer, this);
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(1000000 / g_pConfigManager->getInt("general:max_fps")));
|
||||
}
|
||||
wl_event_source_timer_update(m_esConfigTimer, 1000);
|
||||
}
|
||||
|
||||
CThreadManager::~CThreadManager() {
|
||||
//
|
||||
}
|
@@ -9,11 +9,9 @@ public:
|
||||
CThreadManager();
|
||||
~CThreadManager();
|
||||
|
||||
private:
|
||||
wl_event_source* m_esConfigTimer;
|
||||
|
||||
void handle();
|
||||
|
||||
std::thread* m_tMainThread;
|
||||
private:
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CThreadManager> g_pThreadManager;
|
@@ -36,7 +36,9 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate)
|
||||
wlr_xdg_toplevel_set_activated(wlr_xdg_surface_from_wlr_surface(pSurface)->toplevel, activate);
|
||||
else if (wlr_surface_is_xwayland_surface(pSurface)) {
|
||||
wlr_xwayland_surface_activate(wlr_xwayland_surface_from_wlr_surface(pSurface), activate);
|
||||
wlr_xwayland_surface_restack(wlr_xwayland_surface_from_wlr_surface(pSurface), NULL, XCB_STACK_MODE_ABOVE);
|
||||
|
||||
if (activate)
|
||||
wlr_xwayland_surface_restack(wlr_xwayland_surface_from_wlr_surface(pSurface), NULL, XCB_STACK_MODE_ABOVE);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -153,7 +155,7 @@ bool CHyprXWaylandManager::shouldBeFloated(CWindow* pWindow) {
|
||||
if (pWindow->m_uSurface.xwayland->role) {
|
||||
try {
|
||||
std::string winrole = std::string(pWindow->m_uSurface.xwayland->role);
|
||||
if (winrole.find("pop-up") != std::string::npos || winrole.find("task_dialog") != std::string::npos) {
|
||||
if (winrole.contains("pop-up") || winrole.contains("task_dialog")) {
|
||||
return true;
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
@@ -221,6 +223,4 @@ void CHyprXWaylandManager::setWindowFullscreen(CWindow* pWindow, bool fullscreen
|
||||
|
||||
if (pWindow->m_phForeignToplevel)
|
||||
wlr_foreign_toplevel_handle_v1_set_fullscreen(pWindow->m_phForeignToplevel, fullscreen);
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent("fullscreen", std::to_string((int)fullscreen)));
|
||||
}
|
54
src/managers/input/IdleInhibitor.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "InputManager.hpp"
|
||||
#include "../../Compositor.hpp"
|
||||
|
||||
void Events::listener_newIdleInhibitor(wl_listener* listener, void* data) {
|
||||
const auto WLRIDLEINHIBITOR = (wlr_idle_inhibitor_v1*)data;
|
||||
|
||||
if (!WLRIDLEINHIBITOR)
|
||||
return;
|
||||
|
||||
g_pInputManager->newIdleInhibitor(WLRIDLEINHIBITOR);
|
||||
}
|
||||
|
||||
void CInputManager::newIdleInhibitor(wlr_idle_inhibitor_v1* pInhibitor) {
|
||||
const auto PINHIBIT = &m_lIdleInhibitors.emplace_back();
|
||||
|
||||
Debug::log(LOG, "New idle inhibitor registered");
|
||||
|
||||
PINHIBIT->pWlrInhibitor = pInhibitor;
|
||||
|
||||
PINHIBIT->hyprListener_Destroy.initCallback(&pInhibitor->events.destroy, [](void* owner, void* data){
|
||||
|
||||
const auto PINH = (SIdleInhibitor*)owner;
|
||||
|
||||
g_pInputManager->m_lIdleInhibitors.remove(*PINH);
|
||||
|
||||
Debug::log(LOG, "Destroyed an idleinhibitor");
|
||||
|
||||
g_pInputManager->recheckIdleInhibitorStatus();
|
||||
|
||||
}, PINHIBIT, "IdleInhibitor");
|
||||
|
||||
PINHIBIT->pWindow = g_pCompositor->getWindowFromSurface(pInhibitor->surface);
|
||||
|
||||
if (PINHIBIT->pWindow)
|
||||
Debug::log(LOG, "IdleInhibitor got window %x (%s)", PINHIBIT->pWindow, PINHIBIT->pWindow->m_szTitle.c_str());
|
||||
|
||||
recheckIdleInhibitorStatus();
|
||||
}
|
||||
|
||||
void CInputManager::recheckIdleInhibitorStatus() {
|
||||
|
||||
for (auto& ii : m_lIdleInhibitors) {
|
||||
if (!ii.pWindow) {
|
||||
wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, false);
|
||||
return;
|
||||
} else if (g_pHyprRenderer->shouldRenderWindow(ii.pWindow)) {
|
||||
wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, true);
|
||||
return;
|
||||
}
|
@@ -28,6 +28,8 @@ void CInputManager::onMouseWarp(wlr_pointer_motion_absolute_event* e) {
|
||||
|
||||
void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
|
||||
static auto *const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||
|
||||
if (!g_pCompositor->m_bReadyToProcess)
|
||||
return;
|
||||
|
||||
@@ -36,7 +38,17 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_pCompositor->m_sSeat.mouse->virt)
|
||||
return; // don't refocus on virt
|
||||
|
||||
Vector2D mouseCoords = getMouseCoordsInternal();
|
||||
const auto MOUSECOORDSFLOORED = mouseCoords.floor();
|
||||
|
||||
if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored && !refocus)
|
||||
return;
|
||||
|
||||
m_vLastCursorPosFloored = MOUSECOORDSFLOORED;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromCursor();
|
||||
|
||||
bool didConstraintOnCursor = false;
|
||||
@@ -79,6 +91,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
} else {
|
||||
if ((!CONSTRAINTWINDOW->m_bIsX11 && PMONITOR && CONSTRAINTWINDOW->m_iWorkspaceID == PMONITOR->activeWorkspace) || (CONSTRAINTWINDOW->m_bIsX11)) {
|
||||
g_pCompositor->m_sSeat.mouse->constraintActive = true;
|
||||
didConstraintOnCursor = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,16 +117,17 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
ACTIVEWORKSPACE->setActive(true);
|
||||
|
||||
// event
|
||||
g_pEventManager->postEvent(SHyprIPCEvent("activemon", PMONITOR->szName + "," + ACTIVEWORKSPACE->m_szName));
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activemon", PMONITOR->szName + "," + ACTIVEWORKSPACE->m_szName});
|
||||
}
|
||||
|
||||
Vector2D surfaceCoords;
|
||||
Vector2D surfacePos = Vector2D(-1337, -1337);
|
||||
CWindow* pFoundWindow = nullptr;
|
||||
SLayerSurface* pFoundLayerSurface = nullptr;
|
||||
|
||||
// overlay is above fullscreen
|
||||
if (!foundSurface)
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &surfaceCoords);
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &surfaceCoords, &pFoundLayerSurface);
|
||||
|
||||
// then, we check if the workspace doesnt have a fullscreen window
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
||||
@@ -123,13 +137,14 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
surfacePos = pFoundWindow->m_vRealPosition.vec();
|
||||
|
||||
// only check floating because tiled cant be over fullscreen
|
||||
for (auto w = g_pCompositor->m_lWindows.rbegin(); w != g_pCompositor->m_lWindows.rend(); w++) {
|
||||
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_bIsMapped && w->m_bCreatedOverFullscreen) || (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bHidden) {
|
||||
pFoundWindow = &(*w);
|
||||
for (auto w = g_pCompositor->m_vWindows.rbegin(); w != g_pCompositor->m_vWindows.rend(); w++) {
|
||||
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_bIsMapped && (*w)->m_bCreatedOverFullscreen) || ((*w)->m_iWorkspaceID == SPECIAL_WORKSPACE_ID && PMONITOR->specialWorkspaceOpen)) && wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y) && g_pCompositor->isWorkspaceVisible((*w)->m_iWorkspaceID) && !(*w)->m_bHidden) {
|
||||
pFoundWindow = (*w).get();
|
||||
|
||||
if (!pFoundWindow->m_bIsX11) {
|
||||
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
|
||||
surfacePos = Vector2D(-1337, -1337);
|
||||
} else {
|
||||
foundSurface = g_pXWaylandManager->getWindowSurface(pFoundWindow);
|
||||
surfacePos = pFoundWindow->m_vRealPosition.vec();
|
||||
@@ -141,11 +156,27 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
}
|
||||
|
||||
if (!foundSurface)
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords);
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface);
|
||||
|
||||
// then windows
|
||||
if (!foundSurface) {
|
||||
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
|
||||
if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) {
|
||||
|
||||
if (PMONITOR->specialWorkspaceOpen) {
|
||||
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
|
||||
|
||||
if (pFoundWindow && pFoundWindow->m_iWorkspaceID != SPECIAL_WORKSPACE_ID) {
|
||||
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
}
|
||||
} else {
|
||||
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
|
||||
|
||||
if (!(pFoundWindow && pFoundWindow->m_bIsFloating && pFoundWindow->m_bCreatedOverFullscreen))
|
||||
pFoundWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
||||
}
|
||||
} else
|
||||
pFoundWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords);
|
||||
|
||||
if (pFoundWindow) {
|
||||
if (!pFoundWindow->m_bIsX11) {
|
||||
foundSurface = g_pCompositor->vectorWindowToSurface(mouseCoords, pFoundWindow, surfaceCoords);
|
||||
@@ -158,10 +189,10 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
|
||||
// then surfaces below
|
||||
if (!foundSurface)
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &surfaceCoords);
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &surfaceCoords, &pFoundLayerSurface);
|
||||
|
||||
if (!foundSurface)
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords);
|
||||
foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &surfaceCoords, &pFoundLayerSurface);
|
||||
|
||||
if (!foundSurface) {
|
||||
if (m_ecbClickBehavior == CLICKMODE_KILL)
|
||||
@@ -171,6 +202,12 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
|
||||
wlr_seat_pointer_clear_focus(g_pCompositor->m_sSeat.seat);
|
||||
|
||||
if (refocus) { // if we are forcing a refocus, and we don't find a surface, clear the kb focus too!
|
||||
g_pCompositor->focusSurface(nullptr);
|
||||
|
||||
g_pCompositor->m_pLastWindow = nullptr;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -188,7 +225,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
}
|
||||
|
||||
if (pFoundWindow) {
|
||||
static auto *const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue;
|
||||
if (*PFOLLOWMOUSE != 1 && !refocus) {
|
||||
if (pFoundWindow != g_pCompositor->m_pLastWindow && g_pCompositor->windowValidMapped(g_pCompositor->m_pLastWindow) && (g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating)) {
|
||||
// enter if change floating style
|
||||
@@ -197,12 +233,18 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
||||
} else if (*PFOLLOWMOUSE == 2) {
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||
}
|
||||
|
||||
if (pFoundWindow == g_pCompositor->m_pLastWindow && foundSurface != g_pCompositor->m_pLastFocus) {
|
||||
// we changed the subsurface
|
||||
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);
|
||||
return; // don't enter any new surfaces
|
||||
} else {
|
||||
g_pCompositor->focusWindow(pFoundWindow, foundSurface);
|
||||
}
|
||||
} else
|
||||
} else if (pFoundLayerSurface && pFoundLayerSurface->layerSurface->current.keyboard_interactive)
|
||||
g_pCompositor->focusSurface(foundSurface);
|
||||
|
||||
wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y);
|
||||
@@ -281,6 +323,13 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) {
|
||||
return;
|
||||
}
|
||||
|
||||
// notify the keybind manager
|
||||
static auto *const PPASSMOUSE = &g_pConfigManager->getConfigValuePtr("binds:pass_mouse_when_bound")->intValue;
|
||||
const auto PASS = g_pKeybindManager->onMouseEvent(e);
|
||||
|
||||
if (!PASS && !*PPASSMOUSE)
|
||||
return;
|
||||
|
||||
switch (e->state) {
|
||||
case WLR_BUTTON_PRESSED:
|
||||
if (!g_pCompositor->m_sSeat.mouse->currentConstraint)
|
||||
@@ -339,6 +388,16 @@ void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) {
|
||||
m_ecbClickBehavior = CLICKMODE_DEFAULT;
|
||||
}
|
||||
|
||||
void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) {
|
||||
bool passEvent = g_pKeybindManager->onAxisEvent(e);
|
||||
|
||||
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
|
||||
|
||||
if (passEvent) {
|
||||
wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, e->delta, e->delta_discrete, e->source);
|
||||
}
|
||||
}
|
||||
|
||||
Vector2D CInputManager::getMouseCoordsInternal() {
|
||||
return Vector2D(g_pCompositor->m_sWLRCursor->x, g_pCompositor->m_sWLRCursor->y);
|
||||
}
|
||||
@@ -348,13 +407,14 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
|
||||
|
||||
PNEWKEYBOARD->keyboard = keyboard;
|
||||
|
||||
const auto REPEATRATE = g_pConfigManager->getInt("input:repeat_rate");
|
||||
const auto REPEATDELAY = g_pConfigManager->getInt("input:repeat_delay");
|
||||
try {
|
||||
PNEWKEYBOARD->name = std::string(keyboard->name);
|
||||
} catch (std::exception& e) {
|
||||
Debug::log(ERR, "Keyboard had no name???"); // logic error
|
||||
}
|
||||
|
||||
wlr_keyboard_set_repeat_info(keyboard->keyboard, std::max(0, REPEATRATE), std::max(0, REPEATDELAY));
|
||||
|
||||
PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&keyboard->keyboard->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard");
|
||||
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&keyboard->keyboard->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard");
|
||||
PNEWKEYBOARD->hyprListener_keyboardMod.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.modifiers, &Events::listener_keyboardMod, PNEWKEYBOARD, "Keyboard");
|
||||
PNEWKEYBOARD->hyprListener_keyboardKey.initCallback(&wlr_keyboard_from_input_device(keyboard)->events.key, &Events::listener_keyboardKey, PNEWKEYBOARD, "Keyboard");
|
||||
PNEWKEYBOARD->hyprListener_keyboardDestroy.initCallback(&keyboard->events.destroy, &Events::listener_keyboardDestroy, PNEWKEYBOARD, "Keyboard");
|
||||
|
||||
if (m_pActiveKeyboard)
|
||||
@@ -363,7 +423,7 @@ void CInputManager::newKeyboard(wlr_input_device* keyboard) {
|
||||
|
||||
applyConfigToKeyboard(PNEWKEYBOARD);
|
||||
|
||||
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, keyboard->keyboard);
|
||||
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(keyboard));
|
||||
|
||||
Debug::log(LOG, "New keyboard created, pointers Hypr: %x and WLR: %x", PNEWKEYBOARD, keyboard);
|
||||
}
|
||||
@@ -374,17 +434,26 @@ void CInputManager::setKeyboardLayout() {
|
||||
}
|
||||
|
||||
void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(pKeyboard->name);
|
||||
|
||||
ASSERT(pKeyboard);
|
||||
|
||||
const auto RULES = g_pConfigManager->getString("input:kb_rules");
|
||||
const auto MODEL = g_pConfigManager->getString("input:kb_model");
|
||||
const auto LAYOUT = g_pConfigManager->getString("input:kb_layout");
|
||||
const auto VARIANT = g_pConfigManager->getString("input:kb_variant");
|
||||
const auto OPTIONS = g_pConfigManager->getString("input:kb_options");
|
||||
if (!wlr_keyboard_from_input_device(pKeyboard->keyboard))
|
||||
return;
|
||||
|
||||
const auto REPEATRATE = HASCONFIG ? g_pConfigManager->getDeviceInt(pKeyboard->name, "repeat_rate") : g_pConfigManager->getInt("input:repeat_rate");
|
||||
const auto REPEATDELAY = HASCONFIG ? g_pConfigManager->getDeviceInt(pKeyboard->name, "repeat_delay") : g_pConfigManager->getInt("input:repeat_delay");
|
||||
|
||||
const auto NUMLOCKON = HASCONFIG ? g_pConfigManager->getDeviceInt(pKeyboard->name, "numlock_by_default") : g_pConfigManager->getInt("input:numlock_by_default");
|
||||
|
||||
const auto RULES = HASCONFIG ? g_pConfigManager->getDeviceString(pKeyboard->name, "kb_rules") : g_pConfigManager->getString("input:kb_rules");
|
||||
const auto MODEL = HASCONFIG ? g_pConfigManager->getDeviceString(pKeyboard->name, "kb_model") : g_pConfigManager->getString("input:kb_model");
|
||||
const auto LAYOUT = HASCONFIG ? g_pConfigManager->getDeviceString(pKeyboard->name, "kb_layout") : g_pConfigManager->getString("input:kb_layout");
|
||||
const auto VARIANT = HASCONFIG ? g_pConfigManager->getDeviceString(pKeyboard->name, "kb_variant") : g_pConfigManager->getString("input:kb_variant");
|
||||
const auto OPTIONS = HASCONFIG ? g_pConfigManager->getDeviceString(pKeyboard->name, "kb_options") : g_pConfigManager->getString("input:kb_options");
|
||||
|
||||
try {
|
||||
if (RULES != "" && RULES == std::string(pKeyboard->currentRules.rules) && MODEL == std::string(pKeyboard->currentRules.model) && LAYOUT == std::string(pKeyboard->currentRules.layout) && VARIANT == std::string(pKeyboard->currentRules.variant) && OPTIONS == std::string(pKeyboard->currentRules.options)) {
|
||||
if (NUMLOCKON == pKeyboard->numlockOn && REPEATDELAY == pKeyboard->repeatDelay && REPEATRATE == pKeyboard->repeatRate && RULES != "" && RULES == pKeyboard->currentRules.rules && MODEL == pKeyboard->currentRules.model && LAYOUT == pKeyboard->currentRules.layout && VARIANT == pKeyboard->currentRules.variant && OPTIONS == pKeyboard->currentRules.options) {
|
||||
Debug::log(LOG, "Not applying config to keyboard, it did not change.");
|
||||
return;
|
||||
}
|
||||
@@ -393,6 +462,12 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
// we can ignore those and just apply
|
||||
}
|
||||
|
||||
wlr_keyboard_set_repeat_info(wlr_keyboard_from_input_device(pKeyboard->keyboard), std::max(0, REPEATRATE), std::max(0, REPEATDELAY));
|
||||
|
||||
pKeyboard->repeatDelay = REPEATDELAY;
|
||||
pKeyboard->repeatRate = REPEATRATE;
|
||||
pKeyboard->numlockOn = NUMLOCKON;
|
||||
|
||||
xkb_rule_names rules = {
|
||||
.rules = RULES.c_str(),
|
||||
.model = MODEL.c_str(),
|
||||
@@ -400,7 +475,11 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
.variant = VARIANT.c_str(),
|
||||
.options = OPTIONS.c_str()};
|
||||
|
||||
pKeyboard->currentRules = rules;
|
||||
pKeyboard->currentRules.rules = RULES;
|
||||
pKeyboard->currentRules.model = MODEL;
|
||||
pKeyboard->currentRules.variant = VARIANT;
|
||||
pKeyboard->currentRules.options = OPTIONS;
|
||||
pKeyboard->currentRules.layout = LAYOUT;
|
||||
|
||||
const auto CONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
|
||||
@@ -417,16 +496,20 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
Debug::log(ERR, "Keyboard layout %s with variant %s (rules: %s, model: %s, options: %s) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, rules.options);
|
||||
memset(&rules, 0, sizeof(rules));
|
||||
|
||||
pKeyboard->currentRules = rules;
|
||||
pKeyboard->currentRules.rules = "";
|
||||
pKeyboard->currentRules.model = "";
|
||||
pKeyboard->currentRules.variant = "";
|
||||
pKeyboard->currentRules.options = "";
|
||||
pKeyboard->currentRules.layout = "";
|
||||
|
||||
KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
}
|
||||
|
||||
wlr_keyboard_set_keymap(pKeyboard->keyboard->keyboard, KEYMAP);
|
||||
wlr_keyboard_set_keymap(wlr_keyboard_from_input_device(pKeyboard->keyboard), KEYMAP);
|
||||
|
||||
wlr_keyboard_modifiers wlrMods = {0};
|
||||
|
||||
if (g_pConfigManager->getInt("input:numlock_by_default") == 1) {
|
||||
if (NUMLOCKON == 1) {
|
||||
// lock numlock
|
||||
const auto IDX = xkb_map_mod_get_index(KEYMAP, XKB_MOD_NAME_NUM);
|
||||
|
||||
@@ -435,7 +518,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
}
|
||||
|
||||
if (wlrMods.locked != 0) {
|
||||
wlr_keyboard_notify_modifiers(pKeyboard->keyboard->keyboard, 0, 0, wlrMods.locked, 0);
|
||||
wlr_keyboard_notify_modifiers(wlr_keyboard_from_input_device(pKeyboard->keyboard), 0, 0, wlrMods.locked, 0);
|
||||
}
|
||||
|
||||
xkb_keymap_unref(KEYMAP);
|
||||
@@ -444,46 +527,26 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) {
|
||||
Debug::log(LOG, "Set the keyboard layout to %s and variant to %s for keyboard \"%s\"", rules.layout, rules.variant, pKeyboard->keyboard->name);
|
||||
}
|
||||
|
||||
void CInputManager::newMouse(wlr_input_device* mouse) {
|
||||
void CInputManager::newMouse(wlr_input_device* mouse, bool virt) {
|
||||
m_lMice.emplace_back();
|
||||
const auto PMOUSE = &m_lMice.back();
|
||||
|
||||
PMOUSE->mouse = mouse;
|
||||
PMOUSE->virt = virt;
|
||||
try {
|
||||
PMOUSE->name = std::string(mouse->name);
|
||||
} catch(std::exception& e) {
|
||||
Debug::log(ERR, "Mouse had no name???"); // logic error
|
||||
}
|
||||
|
||||
if (wlr_input_device_is_libinput(mouse)) {
|
||||
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(mouse);
|
||||
|
||||
if (g_pConfigManager->getInt("input:touchpad:clickfinger_behavior") == 0) // toggle software buttons or clickfinger
|
||||
libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
|
||||
else
|
||||
libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||
|
||||
if (libinput_device_config_middle_emulation_is_available(LIBINPUTDEV)) { // middleclick on r+l mouse button pressed
|
||||
if (g_pConfigManager->getInt("input:touchpad:middle_button_emulation") == 1)
|
||||
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);
|
||||
else
|
||||
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
|
||||
}
|
||||
|
||||
if (libinput_device_config_tap_get_finger_count(LIBINPUTDEV)) // this is for tapping (like on a laptop)
|
||||
if (g_pConfigManager->getInt("input:touchpad:tap-to-click") == 1)
|
||||
libinput_device_config_tap_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_TAP_ENABLED);
|
||||
|
||||
if (libinput_device_config_scroll_has_natural_scroll(LIBINPUTDEV)) {
|
||||
double w = 0, h = 0;
|
||||
|
||||
if (libinput_device_has_capability(LIBINPUTDEV, LIBINPUT_DEVICE_CAP_POINTER) && libinput_device_get_size(LIBINPUTDEV, &w, &h) == 0) // pointer with size is a touchpad
|
||||
libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, g_pConfigManager->getInt("input:touchpad:natural_scroll"));
|
||||
else
|
||||
libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, g_pConfigManager->getInt("input:natural_scroll"));
|
||||
}
|
||||
|
||||
if (libinput_device_config_dwt_is_available(LIBINPUTDEV)) {
|
||||
const auto DWT = static_cast<enum libinput_config_dwt_state>(g_pConfigManager->getInt("input:touchpad:disable_while_typing") != 0);
|
||||
libinput_device_config_dwt_set_enabled(LIBINPUTDEV, DWT);
|
||||
}
|
||||
Debug::log(LOG, "New mouse has libinput sens %.2f (%.2f) with accel profile %i (%i)", libinput_device_config_accel_get_speed(LIBINPUTDEV), libinput_device_config_accel_get_default_speed(LIBINPUTDEV), libinput_device_config_accel_get_profile(LIBINPUTDEV), libinput_device_config_accel_get_default_profile(LIBINPUTDEV));
|
||||
}
|
||||
|
||||
setMouseConfigs();
|
||||
|
||||
PMOUSE->hyprListener_destroyMouse.initCallback(&mouse->events.destroy, &Events::listener_destroyMouse, PMOUSE, "Mouse");
|
||||
|
||||
wlr_cursor_attach_input_device(g_pCompositor->m_sWLRCursor, mouse);
|
||||
@@ -495,6 +558,60 @@ void CInputManager::newMouse(wlr_input_device* mouse) {
|
||||
Debug::log(LOG, "New mouse created, pointer WLR: %x", mouse);
|
||||
}
|
||||
|
||||
void CInputManager::setMouseConfigs() {
|
||||
for (auto& m : m_lMice) {
|
||||
const auto PMOUSE = &m;
|
||||
|
||||
const auto HASCONFIG = g_pConfigManager->deviceConfigExists(PMOUSE->name);
|
||||
|
||||
if (wlr_input_device_is_libinput(m.mouse)) {
|
||||
const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(m.mouse);
|
||||
|
||||
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "clickfinger_behavior") : g_pConfigManager->getInt("input:touchpad:clickfinger_behavior")) == 0) // toggle software buttons or clickfinger
|
||||
libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
|
||||
else
|
||||
libinput_device_config_click_set_method(LIBINPUTDEV, LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
|
||||
|
||||
if (libinput_device_config_middle_emulation_is_available(LIBINPUTDEV)) { // middleclick on r+l mouse button pressed
|
||||
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "middle_button_emulation") : g_pConfigManager->getInt("input:touchpad:middle_button_emulation")) == 1)
|
||||
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED);
|
||||
else
|
||||
libinput_device_config_middle_emulation_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED);
|
||||
}
|
||||
|
||||
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "drag_lock") : g_pConfigManager->getInt("input:touchpad:drag_lock")) == 0)
|
||||
libinput_device_config_tap_set_drag_lock_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_DRAG_LOCK_DISABLED);
|
||||
else
|
||||
libinput_device_config_tap_set_drag_lock_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_DRAG_LOCK_ENABLED);
|
||||
|
||||
if (libinput_device_config_tap_get_finger_count(LIBINPUTDEV)) // this is for tapping (like on a laptop)
|
||||
if ((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "tap-to-click") : g_pConfigManager->getInt("input:touchpad:tap-to-click")) == 1)
|
||||
libinput_device_config_tap_set_enabled(LIBINPUTDEV, LIBINPUT_CONFIG_TAP_ENABLED);
|
||||
|
||||
if (libinput_device_config_scroll_has_natural_scroll(LIBINPUTDEV)) {
|
||||
double w = 0, h = 0;
|
||||
|
||||
if (libinput_device_has_capability(LIBINPUTDEV, LIBINPUT_DEVICE_CAP_POINTER) && libinput_device_get_size(LIBINPUTDEV, &w, &h) == 0) // pointer with size is a touchpad
|
||||
libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, (HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "natural_scroll") : g_pConfigManager->getInt("input:touchpad:natural_scroll")));
|
||||
else
|
||||
libinput_device_config_scroll_set_natural_scroll_enabled(LIBINPUTDEV, (HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "natural_scroll") : g_pConfigManager->getInt("input:natural_scroll")));
|
||||
}
|
||||
|
||||
if (libinput_device_config_dwt_is_available(LIBINPUTDEV)) {
|
||||
const auto DWT = static_cast<enum libinput_config_dwt_state>((HASCONFIG ? g_pConfigManager->getDeviceInt(PMOUSE->name, "disable_while_typing") : g_pConfigManager->getInt("input:touchpad:disable_while_typing")) != 0);
|
||||
libinput_device_config_dwt_set_enabled(LIBINPUTDEV, DWT);
|
||||
}
|
||||
|
||||
const auto LIBINPUTSENS = std::clamp((HASCONFIG ? g_pConfigManager->getDeviceFloat(PMOUSE->name, "sensitivity") : g_pConfigManager->getFloat("input:sensitivity")), -1.f, 1.f);
|
||||
|
||||
libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
|
||||
libinput_device_config_accel_set_speed(LIBINPUTDEV, LIBINPUTSENS);
|
||||
|
||||
Debug::log(LOG, "Applied config to mouse %s, sens %.2f", m.name.c_str(), LIBINPUTSENS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::destroyKeyboard(SKeyboard* pKeyboard) {
|
||||
pKeyboard->hyprListener_keyboardDestroy.removeCallback();
|
||||
pKeyboard->hyprListener_keyboardMod.removeCallback();
|
||||
@@ -529,32 +646,19 @@ void CInputManager::destroyMouse(wlr_input_device* mouse) {
|
||||
}
|
||||
|
||||
void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) {
|
||||
const auto KEYCODE = e->keycode + 8; // Because to xkbcommon it's +8 from libinput
|
||||
|
||||
const xkb_keysym_t* keysyms;
|
||||
int syms = xkb_state_key_get_syms(pKeyboard->keyboard->keyboard->xkb_state, KEYCODE, &keysyms);
|
||||
|
||||
const auto MODS = wlr_keyboard_get_modifiers(pKeyboard->keyboard->keyboard);
|
||||
bool passEvent = g_pKeybindManager->onKeyEvent(e, pKeyboard);
|
||||
|
||||
wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat);
|
||||
|
||||
bool found = false;
|
||||
if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
for (int i = 0; i < syms; ++i)
|
||||
found = g_pKeybindManager->handleKeybinds(MODS, keysyms[i]) || found;
|
||||
} else if (e->state == WL_KEYBOARD_KEY_STATE_RELEASED) {
|
||||
// hee hee
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, pKeyboard->keyboard->keyboard);
|
||||
if (passEvent) {
|
||||
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(pKeyboard->keyboard));
|
||||
wlr_seat_keyboard_notify_key(g_pCompositor->m_sSeat.seat, e->time_msec, e->keycode, e->state);
|
||||
}
|
||||
}
|
||||
|
||||
void CInputManager::onKeyboardMod(void* data, SKeyboard* pKeyboard) {
|
||||
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, pKeyboard->keyboard->keyboard);
|
||||
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &pKeyboard->keyboard->keyboard->modifiers);
|
||||
wlr_seat_set_keyboard(g_pCompositor->m_sSeat.seat, wlr_keyboard_from_input_device(pKeyboard->keyboard));
|
||||
wlr_seat_keyboard_notify_modifiers(g_pCompositor->m_sSeat.seat, &wlr_keyboard_from_input_device(pKeyboard->keyboard)->modifiers);
|
||||
}
|
||||
|
||||
void CInputManager::refocus() {
|
||||
@@ -568,9 +672,12 @@ void CInputManager::updateDragIcon() {
|
||||
switch (g_pInputManager->m_sDrag.dragIcon->drag->grab_type) {
|
||||
case WLR_DRAG_GRAB_KEYBOARD:
|
||||
break;
|
||||
case WLR_DRAG_GRAB_KEYBOARD_POINTER:
|
||||
case WLR_DRAG_GRAB_KEYBOARD_POINTER: {
|
||||
wlr_box box = {g_pInputManager->m_sDrag.pos.x - 2, g_pInputManager->m_sDrag.pos.y - 2, g_pInputManager->m_sDrag.dragIcon->surface->current.width + 4, g_pInputManager->m_sDrag.dragIcon->surface->current.height + 4};
|
||||
g_pHyprRenderer->damageBox(&box);
|
||||
g_pInputManager->m_sDrag.pos = g_pInputManager->getMouseCoordsInternal();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -669,4 +776,15 @@ void CInputManager::updateCapabilities(wlr_input_device* pDev) {
|
||||
}
|
||||
|
||||
wlr_seat_set_capabilities(g_pCompositor->m_sSeat.seat, m_uiCapabilities);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t CInputManager::accumulateModsFromAllKBs() {
|
||||
|
||||
uint32_t finalMask = 0;
|
||||
|
||||
for (auto& kb : m_lKeyboards) {
|
||||
finalMask |= wlr_keyboard_get_modifiers(wlr_keyboard_from_input_device(kb.keyboard));
|
||||
}
|
||||
|
||||
return finalMask;
|
||||
}
|
||||
|
@@ -17,11 +17,12 @@ public:
|
||||
void onMouseMoved(wlr_pointer_motion_event*);
|
||||
void onMouseWarp(wlr_pointer_motion_absolute_event*);
|
||||
void onMouseButton(wlr_pointer_button_event*);
|
||||
void onMouseWheel(wlr_pointer_axis_event*);
|
||||
void onKeyboardKey(wlr_keyboard_key_event*, SKeyboard*);
|
||||
void onKeyboardMod(void*, SKeyboard*);
|
||||
|
||||
void newKeyboard(wlr_input_device*);
|
||||
void newMouse(wlr_input_device*);
|
||||
void newMouse(wlr_input_device*, bool virt = false);
|
||||
void destroyKeyboard(SKeyboard*);
|
||||
void destroyMouse(wlr_input_device*);
|
||||
|
||||
@@ -32,6 +33,7 @@ public:
|
||||
void refocus();
|
||||
|
||||
void setKeyboardLayout();
|
||||
void setMouseConfigs();
|
||||
|
||||
void updateDragIcon();
|
||||
void updateCapabilities(wlr_input_device*);
|
||||
@@ -56,18 +58,33 @@ public:
|
||||
std::list<STabletTool> m_lTabletTools;
|
||||
std::list<STabletPad> m_lTabletPads;
|
||||
|
||||
// idle inhibitors
|
||||
std::list<SIdleInhibitor> m_lIdleInhibitors;
|
||||
|
||||
void newTabletTool(wlr_input_device*);
|
||||
void newTabletPad(wlr_input_device*);
|
||||
void focusTablet(STablet*, wlr_tablet_tool*, bool motion = false);
|
||||
void newIdleInhibitor(wlr_idle_inhibitor_v1*);
|
||||
void recheckIdleInhibitorStatus();
|
||||
|
||||
void onSwipeBegin(wlr_pointer_swipe_begin_event*);
|
||||
void onSwipeEnd(wlr_pointer_swipe_end_event*);
|
||||
void onSwipeUpdate(wlr_pointer_swipe_update_event*);
|
||||
|
||||
SSwipeGesture m_sActiveSwipe;
|
||||
|
||||
SKeyboard* m_pActiveKeyboard = nullptr;
|
||||
|
||||
CTimer m_tmrLastCursorMovement;
|
||||
|
||||
// for shared mods
|
||||
uint32_t accumulateModsFromAllKBs();
|
||||
|
||||
private:
|
||||
|
||||
// for click behavior override
|
||||
eClickBehaviorMode m_ecbClickBehavior = CLICKMODE_DEFAULT;
|
||||
Vector2D m_vLastCursorPosFloored = Vector2D();
|
||||
|
||||
void processMouseDownNormal(wlr_pointer_button_event* e);
|
||||
void processMouseDownKill(wlr_pointer_button_event* e);
|
||||
|
180
src/managers/input/Swipe.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
#include "InputManager.hpp"
|
||||
#include "../../Compositor.hpp"
|
||||
|
||||
void CInputManager::onSwipeBegin(wlr_pointer_swipe_begin_event* e) {
|
||||
|
||||
static auto *const PSWIPE = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe")->intValue;
|
||||
static auto *const PSWIPEFINGERS = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_fingers")->intValue;
|
||||
|
||||
if (e->fingers != *PSWIPEFINGERS|| *PSWIPE == 0)
|
||||
return;
|
||||
|
||||
int onMonitor = 0;
|
||||
for (auto& w : g_pCompositor->m_vWorkspaces) {
|
||||
if (w->m_iMonitorID == g_pCompositor->m_pLastMonitor->ID) {
|
||||
onMonitor++;
|
||||
}
|
||||
}
|
||||
|
||||
if (onMonitor < 2)
|
||||
return; // disallow swiping when there's 1 workspace on a monitor
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace);
|
||||
|
||||
Debug::log(LOG, "Starting a swipe from %s", PWORKSPACE->m_szName.c_str());
|
||||
|
||||
m_sActiveSwipe.pWorkspaceBegin = PWORKSPACE;
|
||||
m_sActiveSwipe.delta = 0;
|
||||
m_sActiveSwipe.pMonitor = g_pCompositor->m_pLastMonitor;
|
||||
m_sActiveSwipe.avgSpeed = 0;
|
||||
m_sActiveSwipe.speedPoints = 0;
|
||||
}
|
||||
|
||||
void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) {
|
||||
|
||||
if (!m_sActiveSwipe.pWorkspaceBegin)
|
||||
return; // no valid swipe
|
||||
|
||||
static auto *const PSWIPEPERC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_cancel_ratio")->floatValue;
|
||||
static auto *const PSWIPEDIST = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance")->intValue;
|
||||
static auto *const PSWIPEFORC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_min_speed_to_force")->intValue;
|
||||
|
||||
// commit
|
||||
std::string wsname = "";
|
||||
auto workspaceIDLeft = getWorkspaceIDFromString("m-1", wsname);
|
||||
auto workspaceIDRight = getWorkspaceIDFromString("m+1", wsname);
|
||||
|
||||
const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight);
|
||||
const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
|
||||
|
||||
const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.vec();
|
||||
|
||||
if ((abs(m_sActiveSwipe.delta) < *PSWIPEDIST * *PSWIPEPERC && (*PSWIPEFORC == 0 || (*PSWIPEFORC != 0 && m_sActiveSwipe.avgSpeed < *PSWIPEFORC))) || abs(m_sActiveSwipe.delta) < 2) {
|
||||
// revert
|
||||
if (abs(m_sActiveSwipe.delta) < 2) {
|
||||
PWORKSPACEL->m_vRenderOffset.setValueAndWarp(Vector2D(0,0));
|
||||
PWORKSPACER->m_vRenderOffset.setValueAndWarp(Vector2D(0,0));
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0,0));
|
||||
} else {
|
||||
if (m_sActiveSwipe.delta < 0) {
|
||||
// to left
|
||||
PWORKSPACEL->m_vRenderOffset = Vector2D({-m_sActiveSwipe.pMonitor->vecSize.x, 0});
|
||||
} else {
|
||||
// to right
|
||||
PWORKSPACER->m_vRenderOffset = Vector2D({m_sActiveSwipe.pMonitor->vecSize.x, 0});
|
||||
}
|
||||
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D();
|
||||
}
|
||||
} else if (m_sActiveSwipe.delta < 0) {
|
||||
// switch to left
|
||||
const auto RENDEROFFSET = PWORKSPACEL->m_vRenderOffset.vec();
|
||||
|
||||
g_pKeybindManager->m_mDispatchers["workspace"]("[internal]" + std::to_string(workspaceIDLeft));
|
||||
|
||||
PWORKSPACEL->m_vRenderOffset.setValue(RENDEROFFSET);
|
||||
PWORKSPACEL->m_fAlpha.setValueAndWarp(255.f);
|
||||
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE);
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(m_sActiveSwipe.pMonitor->vecSize.x, 0);
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(255.f);
|
||||
|
||||
g_pCompositor->m_sSeat.mouse->currentConstraint = nullptr;
|
||||
|
||||
Debug::log(LOG, "Ended swipe to the left");
|
||||
} else {
|
||||
// switch to right
|
||||
const auto RENDEROFFSET = PWORKSPACER->m_vRenderOffset.vec();
|
||||
|
||||
g_pKeybindManager->m_mDispatchers["workspace"]("[internal]" + std::to_string(workspaceIDRight));
|
||||
|
||||
PWORKSPACER->m_vRenderOffset.setValue(RENDEROFFSET);
|
||||
PWORKSPACER->m_fAlpha.setValueAndWarp(255.f);
|
||||
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE);
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-m_sActiveSwipe.pMonitor->vecSize.x, 0);
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(255.f);
|
||||
|
||||
g_pCompositor->m_sSeat.mouse->currentConstraint = nullptr;
|
||||
|
||||
Debug::log(LOG, "Ended swipe to the right");
|
||||
}
|
||||
|
||||
PWORKSPACEL->m_bForceRendering = false;
|
||||
PWORKSPACER->m_bForceRendering = false;
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_bForceRendering = false;
|
||||
|
||||
m_sActiveSwipe.pWorkspaceBegin = nullptr;
|
||||
|
||||
g_pInputManager->refocus();
|
||||
}
|
||||
|
||||
void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) {
|
||||
if (!m_sActiveSwipe.pWorkspaceBegin)
|
||||
return;
|
||||
|
||||
static auto *const PSWIPEDIST = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance")->intValue;
|
||||
static auto *const PSWIPEINVR = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_invert")->intValue;
|
||||
|
||||
m_sActiveSwipe.delta += *PSWIPEINVR ? -e->dx : e->dx;
|
||||
|
||||
m_sActiveSwipe.avgSpeed = (m_sActiveSwipe.avgSpeed * m_sActiveSwipe.speedPoints + abs(e->dx)) / (m_sActiveSwipe.speedPoints + 1);
|
||||
m_sActiveSwipe.speedPoints++;
|
||||
|
||||
std::string wsname = "";
|
||||
auto workspaceIDLeft = getWorkspaceIDFromString("m-1", wsname);
|
||||
auto workspaceIDRight = getWorkspaceIDFromString("m+1", wsname);
|
||||
|
||||
if (workspaceIDLeft == INT_MAX || workspaceIDRight == INT_MAX || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID)
|
||||
return;
|
||||
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_bForceRendering = true;
|
||||
|
||||
m_sActiveSwipe.delta = std::clamp(m_sActiveSwipe.delta, (double)-*PSWIPEDIST, (double)*PSWIPEDIST);
|
||||
|
||||
if (m_sActiveSwipe.delta < 0) {
|
||||
if (workspaceIDLeft > m_sActiveSwipe.pWorkspaceBegin->m_iID){
|
||||
m_sActiveSwipe.delta = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
|
||||
|
||||
PWORKSPACE->m_bForceRendering = true;
|
||||
|
||||
if (workspaceIDLeft != workspaceIDRight) {
|
||||
const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight);
|
||||
|
||||
PWORKSPACER->m_bForceRendering = false;
|
||||
}
|
||||
|
||||
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x - m_sActiveSwipe.pMonitor->vecSize.x, 0));
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0));
|
||||
|
||||
g_pCompositor->updateWorkspaceWindowDecos(workspaceIDLeft);
|
||||
} else {
|
||||
if (workspaceIDRight < m_sActiveSwipe.pWorkspaceBegin->m_iID){
|
||||
m_sActiveSwipe.delta = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceIDRight);
|
||||
|
||||
PWORKSPACE->m_bForceRendering = true;
|
||||
|
||||
if (workspaceIDLeft != workspaceIDRight) {
|
||||
const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft);
|
||||
|
||||
PWORKSPACEL->m_bForceRendering = false;
|
||||
}
|
||||
|
||||
PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x + m_sActiveSwipe.pMonitor->vecSize.x, 0));
|
||||
m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((- m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0));
|
||||
|
||||
g_pCompositor->updateWorkspaceWindowDecos(workspaceIDRight);
|
||||
}
|
||||
|
||||
g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor);
|
||||
|
||||
g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID);
|
||||
}
|
@@ -4,7 +4,13 @@
|
||||
void CInputManager::newTabletTool(wlr_input_device* pDevice) {
|
||||
const auto PNEWTABLET = &m_lTablets.emplace_back();
|
||||
|
||||
PNEWTABLET->wlrTablet = pDevice->tablet;
|
||||
try {
|
||||
PNEWTABLET->name = std::string(pDevice->name);
|
||||
} catch (std::exception& e) {
|
||||
Debug::log(ERR, "Tablet had no name???"); // logic error
|
||||
}
|
||||
|
||||
PNEWTABLET->wlrTablet = wlr_tablet_from_input_device(pDevice);
|
||||
PNEWTABLET->wlrDevice = pDevice;
|
||||
PNEWTABLET->wlrTabletV2 = wlr_tablet_create(g_pCompositor->m_sWLRTabletManager, g_pCompositor->m_sSeat.seat, pDevice);
|
||||
PNEWTABLET->wlrTablet->data = PNEWTABLET;
|
||||
@@ -21,7 +27,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
|
||||
Debug::log(LOG, "Removed a tablet");
|
||||
}, PNEWTABLET, "Tablet");
|
||||
|
||||
PNEWTABLET->hyprListener_Axis.initCallback(&pDevice->tablet->events.axis, [](void* owner, void* data) {
|
||||
PNEWTABLET->hyprListener_Axis.initCallback(&wlr_tablet_from_input_device(pDevice)->events.axis, [](void* owner, void* data) {
|
||||
|
||||
const auto EVENT = (wlr_tablet_tool_axis_event*)data;
|
||||
const auto PTAB = (STablet*)owner;
|
||||
@@ -74,7 +80,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
|
||||
|
||||
}, PNEWTABLET, "Tablet");
|
||||
|
||||
PNEWTABLET->hyprListener_Tip.initCallback(&pDevice->tablet->events.tip, [](void* owner, void* data) {
|
||||
PNEWTABLET->hyprListener_Tip.initCallback(&wlr_tablet_from_input_device(pDevice)->events.tip, [](void* owner, void* data) {
|
||||
const auto EVENT = (wlr_tablet_tool_tip_event*)data;
|
||||
const auto PTAB = (STablet*)owner;
|
||||
|
||||
@@ -92,7 +98,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
|
||||
|
||||
}, PNEWTABLET, "Tablet");
|
||||
|
||||
PNEWTABLET->hyprListener_Button.initCallback(&pDevice->tablet->events.button, [](void* owner, void* data) {
|
||||
PNEWTABLET->hyprListener_Button.initCallback(&wlr_tablet_from_input_device(pDevice)->events.button, [](void* owner, void* data) {
|
||||
const auto EVENT = (wlr_tablet_tool_button_event*)data;
|
||||
|
||||
const auto PTOOL = g_pInputManager->ensureTabletToolPresent(EVENT->tool);
|
||||
@@ -101,7 +107,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) {
|
||||
|
||||
}, PNEWTABLET, "Tablet");
|
||||
|
||||
PNEWTABLET->hyprListener_Proximity.initCallback(&pDevice->tablet->events.proximity, [](void* owner, void* data) {
|
||||
PNEWTABLET->hyprListener_Proximity.initCallback(&wlr_tablet_from_input_device(pDevice)->events.proximity, [](void* owner, void* data) {
|
||||
const auto EVENT = (wlr_tablet_tool_proximity_event*)data;
|
||||
const auto PTAB = (STablet*)owner;
|
||||
|
||||
@@ -151,9 +157,15 @@ STabletTool* CInputManager::ensureTabletToolPresent(wlr_tablet_tool* pTool) {
|
||||
void CInputManager::newTabletPad(wlr_input_device* pDevice) {
|
||||
const auto PNEWPAD = &m_lTabletPads.emplace_back();
|
||||
|
||||
try {
|
||||
PNEWPAD->name = std::string(pDevice->name);
|
||||
} catch (std::exception& e) {
|
||||
Debug::log(ERR, "Pad had no name???"); // logic error
|
||||
}
|
||||
|
||||
PNEWPAD->wlrTabletPadV2 = wlr_tablet_pad_create(g_pCompositor->m_sWLRTabletManager, g_pCompositor->m_sSeat.seat, pDevice);
|
||||
|
||||
PNEWPAD->hyprListener_Button.initCallback(&pDevice->tablet_pad->events.button, [](void* owner, void* data) {
|
||||
PNEWPAD->hyprListener_Button.initCallback(&wlr_tablet_pad_from_input_device(pDevice)->events.button, [](void* owner, void* data) {
|
||||
|
||||
const auto EVENT = (wlr_tablet_pad_button_event*)data;
|
||||
const auto PPAD = (STabletPad*)owner;
|
||||
@@ -163,7 +175,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) {
|
||||
|
||||
}, PNEWPAD, "Tablet Pad");
|
||||
|
||||
PNEWPAD->hyprListener_Strip.initCallback(&pDevice->tablet_pad->events.strip, [](void* owner, void* data) {
|
||||
PNEWPAD->hyprListener_Strip.initCallback(&wlr_tablet_pad_from_input_device(pDevice)->events.strip, [](void* owner, void* data) {
|
||||
|
||||
const auto EVENT = (wlr_tablet_pad_strip_event*)data;
|
||||
const auto PPAD = (STabletPad*)owner;
|
||||
@@ -172,7 +184,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) {
|
||||
|
||||
}, PNEWPAD, "Tablet Pad");
|
||||
|
||||
PNEWPAD->hyprListener_Ring.initCallback(&pDevice->tablet_pad->events.strip, [](void* owner, void* data) {
|
||||
PNEWPAD->hyprListener_Ring.initCallback(&wlr_tablet_pad_from_input_device(pDevice)->events.strip, [](void* owner, void* data) {
|
||||
|
||||
const auto EVENT = (wlr_tablet_pad_ring_event*)data;
|
||||
const auto PPAD = (STabletPad*)owner;
|
||||
@@ -181,7 +193,7 @@ void CInputManager::newTabletPad(wlr_input_device* pDevice) {
|
||||
|
||||
}, PNEWPAD, "Tablet Pad");
|
||||
|
||||
PNEWPAD->hyprListener_Attach.initCallback(&pDevice->tablet_pad->events.strip, [](void* owner, void* data) {
|
||||
PNEWPAD->hyprListener_Attach.initCallback(&wlr_tablet_pad_from_input_device(pDevice)->events.strip, [](void* owner, void* data) {
|
||||
|
||||
const auto TABLET = (wlr_tablet_tool*)data;
|
||||
const auto PPAD = (STabletPad*)owner;
|
||||
|
@@ -2,15 +2,14 @@
|
||||
#include "OpenGL.hpp"
|
||||
|
||||
bool CFramebuffer::alloc(int w, int h) {
|
||||
bool firstAlloc = false;
|
||||
if (m_iFb == (uint32_t)-1)
|
||||
{
|
||||
bool firstAlloc = false;
|
||||
|
||||
if (m_iFb == (uint32_t)-1) {
|
||||
firstAlloc = true;
|
||||
glGenFramebuffers(1, &m_iFb);
|
||||
}
|
||||
|
||||
if (m_cTex.m_iTexID == 0)
|
||||
{
|
||||
if (m_cTex.m_iTexID == 0) {
|
||||
firstAlloc = true;
|
||||
glGenTextures(1, &m_cTex.m_iTexID);
|
||||
glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
|
||||
@@ -20,13 +19,11 @@ bool CFramebuffer::alloc(int w, int h) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
|
||||
if (firstAlloc || m_Size != Vector2D(w, h))
|
||||
{
|
||||
if (firstAlloc || m_Size != Vector2D(w, h)) {
|
||||
glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iFb);
|
||||
glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_cTex.m_iTexID, 0);
|
||||
|
||||
|
||||
@@ -37,7 +34,6 @@ bool CFramebuffer::alloc(int w, int h) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, w, h, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iFb);
|
||||
glBindTexture(GL_TEXTURE_2D, m_pStencilTex->m_iTexID);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_pStencilTex->m_iTexID, 0);
|
||||
}
|
||||
@@ -78,3 +74,7 @@ void CFramebuffer::release() {
|
||||
m_cTex.m_iTexID = 0;
|
||||
m_iFb = -1;
|
||||
}
|
||||
|
||||
CFramebuffer::~CFramebuffer() {
|
||||
release();
|
||||
}
|
@@ -6,6 +6,8 @@
|
||||
class CFramebuffer {
|
||||
public:
|
||||
|
||||
~CFramebuffer();
|
||||
|
||||
bool alloc(int w, int h);
|
||||
void bind();
|
||||
void release();
|
||||
|
@@ -146,28 +146,30 @@ void CHyprOpenGLImpl::begin(SMonitor* pMonitor, pixman_region32_t* pDamage, bool
|
||||
|
||||
matrixProjection(m_RenderData.projection, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
|
||||
m_RenderData.pCurrentMonData = &m_mMonitorRenderResources[pMonitor];
|
||||
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_iCurrentOutputFb);
|
||||
m_iWLROutputFb = m_iCurrentOutputFb;
|
||||
|
||||
// ensure a framebuffer for the monitor exists
|
||||
if (m_mMonitorRenderResources.find(pMonitor) == m_mMonitorRenderResources.end() || m_mMonitorRenderResources[pMonitor].primaryFB.m_Size != pMonitor->vecPixelSize) {
|
||||
m_mMonitorRenderResources[pMonitor].stencilTex.allocate();
|
||||
if (m_mMonitorRenderResources.find(pMonitor) == m_mMonitorRenderResources.end() || m_RenderData.pCurrentMonData->primaryFB.m_Size != pMonitor->vecPixelSize) {
|
||||
m_RenderData.pCurrentMonData->stencilTex.allocate();
|
||||
|
||||
m_mMonitorRenderResources[pMonitor].primaryFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex;
|
||||
m_mMonitorRenderResources[pMonitor].mirrorFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex;
|
||||
m_mMonitorRenderResources[pMonitor].mirrorSwapFB.m_pStencilTex = &m_mMonitorRenderResources[pMonitor].stencilTex;
|
||||
m_RenderData.pCurrentMonData->primaryFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
m_RenderData.pCurrentMonData->mirrorFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex;
|
||||
|
||||
m_mMonitorRenderResources[pMonitor].primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_mMonitorRenderResources[pMonitor].mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_mMonitorRenderResources[pMonitor].mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_RenderData.pCurrentMonData->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y);
|
||||
|
||||
createBGTextureForMonitor(pMonitor);
|
||||
}
|
||||
|
||||
// bind the primary Hypr Framebuffer
|
||||
m_mMonitorRenderResources[pMonitor].primaryFB.bind();
|
||||
m_RenderData.pCurrentMonData->primaryFB.bind();
|
||||
|
||||
m_RenderData.pDamage = pDamage;
|
||||
|
||||
@@ -186,7 +188,7 @@ void CHyprOpenGLImpl::end() {
|
||||
|
||||
m_bEndFrame = true;
|
||||
|
||||
renderTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex, &monbox, 255.f, 0);
|
||||
renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 255.f, 0);
|
||||
|
||||
m_bEndFrame = false;
|
||||
}
|
||||
@@ -283,11 +285,11 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
|
||||
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
|
||||
|
||||
// Rounded corners
|
||||
glUniform2f(glGetUniformLocation(m_shQUAD.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||
glUniform2f(glGetUniformLocation(m_shQUAD.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(glGetUniformLocation(m_shQUAD.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(glGetUniformLocation(m_shQUAD.program, "radius"), round);
|
||||
glUniform1i(glGetUniformLocation(m_shQUAD.program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0));
|
||||
glUniform2f(m_shQUAD.getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||
glUniform2f(m_shQUAD.getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(m_shQUAD.getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(m_shQUAD.getUniformLocation("radius"), round);
|
||||
glUniform1i(m_shQUAD.getUniformLocation("primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0));
|
||||
|
||||
glVertexAttribPointer(m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(m_shQUAD.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
@@ -309,21 +311,21 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, pixm
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha, int round) {
|
||||
void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha, int round, bool allowCustomUV) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
|
||||
renderTexture(CTexture(tex), pBox, alpha, round);
|
||||
renderTexture(CTexture(tex), pBox, alpha, round, false, allowCustomUV);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool allowPrimary) {
|
||||
void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool allowCustomUV) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
|
||||
renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, false, allowPrimary);
|
||||
renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, false, allowCustomUV);
|
||||
|
||||
scissor((wlr_box*)nullptr);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool noAA, bool allowPrimary) {
|
||||
void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool noAA, bool allowCustomUV) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!");
|
||||
RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!");
|
||||
|
||||
@@ -378,22 +380,22 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b
|
||||
static auto *const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue;
|
||||
|
||||
// Rounded corners
|
||||
glUniform2f(glGetUniformLocation(shader->program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||
glUniform2f(glGetUniformLocation(shader->program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(glGetUniformLocation(shader->program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(glGetUniformLocation(shader->program, "radius"), round);
|
||||
glUniform1i(glGetUniformLocation(shader->program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !noAA));
|
||||
glUniform2f(shader->getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||
glUniform2f(shader->getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(shader->getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(shader->getUniformLocation("radius"), round);
|
||||
glUniform1i(shader->getUniformLocation("primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !noAA));
|
||||
|
||||
glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
|
||||
if (allowPrimary && m_RenderData.renderingPrimarySurface && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) {
|
||||
const float verts[] = {
|
||||
m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVTopLeft.y, // top right
|
||||
m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVTopLeft.y, // top left
|
||||
m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom right
|
||||
m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom left
|
||||
};
|
||||
const float verts[] = {
|
||||
m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVTopLeft.y, // top right
|
||||
m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVTopLeft.y, // top left
|
||||
m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom right
|
||||
m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom left
|
||||
};
|
||||
|
||||
if (allowCustomUV && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) {
|
||||
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, verts);
|
||||
} else {
|
||||
glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
@@ -447,10 +449,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
|
||||
wlr_region_expand(&damage, &damage, pow(2, *PBLURPASSES) * *PBLURSIZE);
|
||||
|
||||
// helper
|
||||
const auto PMIRRORFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorFB;
|
||||
const auto PMIRRORSWAPFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].mirrorSwapFB;
|
||||
const auto PMIRRORFB = &m_RenderData.pCurrentMonData->mirrorFB;
|
||||
const auto PMIRRORSWAPFB = &m_RenderData.pCurrentMonData->mirrorSwapFB;
|
||||
|
||||
CFramebuffer* currentRenderToFB = &m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB;
|
||||
CFramebuffer* currentRenderToFB = &m_RenderData.pCurrentMonData->primaryFB;
|
||||
|
||||
// declare the draw func
|
||||
auto drawPass = [&](CShader* pShader, pixman_region32_t* pDamage) {
|
||||
@@ -469,11 +471,11 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
|
||||
|
||||
// prep two shaders
|
||||
glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix);
|
||||
glUniform1f(glGetUniformLocation(pShader->program, "radius"), *PBLURSIZE * (a / 255.f)); // this makes the blursize change with a
|
||||
glUniform1f(pShader->getUniformLocation("radius"), *PBLURSIZE * (a / 255.f)); // this makes the blursize change with a
|
||||
if (pShader == &m_shBLUR1)
|
||||
glUniform2f(glGetUniformLocation(m_shBLUR1.program, "halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
|
||||
glUniform2f(m_shBLUR1.getUniformLocation("halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f));
|
||||
else
|
||||
glUniform2f(glGetUniformLocation(m_shBLUR2.program, "halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x * 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y * 2.f));
|
||||
glUniform2f(m_shBLUR2.getUniformLocation("halfpixel"), 0.5f / (m_RenderData.pMonitor->vecPixelSize.x * 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y * 2.f));
|
||||
glUniform1i(pShader->tex, 0);
|
||||
|
||||
glVertexAttribPointer(pShader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
@@ -503,7 +505,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, wlr_box* p
|
||||
// draw the things.
|
||||
// first draw is prim -> mirr
|
||||
PMIRRORFB->bind();
|
||||
glBindTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex.m_iTarget, m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex.m_iTexID);
|
||||
glBindTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTarget, m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTexID);
|
||||
|
||||
// damage region will be scaled, make a temp
|
||||
pixman_region32_t tempDamage;
|
||||
@@ -565,7 +567,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||
}
|
||||
|
||||
if (!pixman_region32_not_empty(&inverseOpaque)) {
|
||||
renderTexture(tex, pBox, a, round, false); // reject blurring a fully opaque window
|
||||
renderTexture(tex, pBox, a, round, false, true); // reject blurring a fully opaque window
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -575,7 +577,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||
pixman_region32_fini(&inverseOpaque);
|
||||
|
||||
// bind primary
|
||||
m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.bind();
|
||||
m_RenderData.pCurrentMonData->primaryFB.bind();
|
||||
|
||||
// make a stencil for rounded corners to work with blur
|
||||
scissor((wlr_box*)nullptr); // allow the entire window and stencil to render
|
||||
@@ -588,7 +590,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
renderTexture(tex, pBox, a, round, true); // discard opaque
|
||||
renderTexture(tex, pBox, a, round, true, true); // discard opaque
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
|
||||
glStencilFunc(GL_EQUAL, 1, -1);
|
||||
@@ -599,7 +601,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox,
|
||||
if (pixman_region32_not_empty(&damage)) {
|
||||
// render our great blurred FB
|
||||
static auto *const PBLURIGNOREOPACITY = &g_pConfigManager->getConfigValuePtr("decoration:blur_ignore_opacity")->intValue;
|
||||
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 255.f : a, &damage, 0, false, false, true);
|
||||
renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 255.f : a, &damage, 0, false, false, false);
|
||||
|
||||
// render the window, but clear stencil
|
||||
glClearStencil(0);
|
||||
@@ -653,18 +655,18 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int round) {
|
||||
glUseProgram(m_shBORDER1.program);
|
||||
|
||||
glUniformMatrix3fv(m_shBORDER1.proj, 1, GL_FALSE, glMatrix);
|
||||
glUniform4f(glGetUniformLocation(m_shBORDER1.program, "color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
|
||||
glUniform4f(m_shBORDER1.getUniformLocation("color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f);
|
||||
|
||||
const auto TOPLEFT = Vector2D(round, round);
|
||||
const auto BOTTOMRIGHT = Vector2D(box->width - round, box->height - round);
|
||||
const auto FULLSIZE = Vector2D(box->width, box->height);
|
||||
|
||||
glUniform2f(glGetUniformLocation(m_shBORDER1.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||
glUniform2f(glGetUniformLocation(m_shBORDER1.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(glGetUniformLocation(m_shBORDER1.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(glGetUniformLocation(m_shBORDER1.program, "radius"), round);
|
||||
glUniform1f(glGetUniformLocation(m_shBORDER1.program, "thick"), *PBORDERSIZE);
|
||||
glUniform1i(glGetUniformLocation(m_shBORDER1.program, "primitiveMultisample"), *PMULTISAMPLE);
|
||||
glUniform2f(m_shBORDER1.getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||
glUniform2f(m_shBORDER1.getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(m_shBORDER1.getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(m_shBORDER1.getUniformLocation("radius"), round);
|
||||
glUniform1f(m_shBORDER1.getUniformLocation("thick"), *PBORDERSIZE);
|
||||
glUniform1i(m_shBORDER1.getUniformLocation("primitiveMultisample"), *PMULTISAMPLE);
|
||||
|
||||
glVertexAttribPointer(m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(m_shBORDER1.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
@@ -696,12 +698,10 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
|
||||
// this is temporary, doesnt mess with the actual wlr damage
|
||||
pixman_region32_t fakeDamage;
|
||||
pixman_region32_init(&fakeDamage);
|
||||
pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecPixelSize.x, (int)PMONITOR->vecPixelSize.y);
|
||||
pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y);
|
||||
|
||||
begin(PMONITOR, &fakeDamage, true);
|
||||
|
||||
pixman_region32_fini(&fakeDamage);
|
||||
|
||||
clear(CColor(0,0,0,0)); // JIC
|
||||
|
||||
timespec now;
|
||||
@@ -715,7 +715,9 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
|
||||
const auto BLURVAL = g_pConfigManager->getInt("decoration:blur");
|
||||
g_pConfigManager->setInt("decoration:blur", 0);
|
||||
|
||||
g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders);
|
||||
m_bEndFrame = true;
|
||||
|
||||
g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders, RENDER_PASS_ALL);
|
||||
|
||||
g_pConfigManager->setInt("decoration:blur", BLURVAL);
|
||||
|
||||
@@ -731,8 +733,10 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
|
||||
|
||||
clear(CColor(0, 0, 0, 0)); // JIC
|
||||
|
||||
wlr_box fullMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
renderTexture(m_mMonitorRenderResources[m_RenderData.pMonitor].primaryFB.m_cTex, &fullMonBox, 255.f, 0);
|
||||
wlr_box fullMonBox = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
|
||||
|
||||
renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &fullMonBox, 255.f, 0);
|
||||
m_bEndFrame = false;
|
||||
|
||||
// restore original fb
|
||||
#ifndef GLES2
|
||||
@@ -740,9 +744,10 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
|
||||
#else
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_iCurrentOutputFb);
|
||||
#endif
|
||||
|
||||
end();
|
||||
|
||||
pixman_region32_fini(&fakeDamage);
|
||||
|
||||
wlr_output_rollback(PMONITOR->output);
|
||||
}
|
||||
|
||||
@@ -756,12 +761,10 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
|
||||
// this is temporary, doesnt mess with the actual wlr damage
|
||||
pixman_region32_t fakeDamage;
|
||||
pixman_region32_init(&fakeDamage);
|
||||
pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecPixelSize.x, (int)PMONITOR->vecPixelSize.y);
|
||||
pixman_region32_union_rect(&fakeDamage, &fakeDamage, 0, 0, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y);
|
||||
|
||||
begin(PMONITOR, &fakeDamage, true);
|
||||
|
||||
pixman_region32_fini(&fakeDamage);
|
||||
|
||||
const auto PFRAMEBUFFER = &m_mLayerFramebuffers[pLayer];
|
||||
|
||||
glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y);
|
||||
@@ -775,9 +778,13 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
|
||||
timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
|
||||
m_bEndFrame = true;
|
||||
|
||||
// draw the layer
|
||||
g_pHyprRenderer->renderLayer(pLayer, PMONITOR, &now);
|
||||
|
||||
m_bEndFrame = false;
|
||||
|
||||
// TODO: WARN:
|
||||
// revise if any stencil-requiring rendering is done to the layers.
|
||||
|
||||
@@ -790,6 +797,8 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) {
|
||||
|
||||
end();
|
||||
|
||||
pixman_region32_fini(&fakeDamage);
|
||||
|
||||
wlr_output_rollback(PMONITOR->output);
|
||||
}
|
||||
|
||||
@@ -811,15 +820,18 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
|
||||
|
||||
wlr_box windowBox;
|
||||
// some mafs to figure out the correct box
|
||||
Vector2D scaleXY = Vector2D((PWINDOW->m_vRealSize.vec().x / PWINDOW->m_vOriginalClosedSize.x), (PWINDOW->m_vRealSize.vec().y / PWINDOW->m_vOriginalClosedSize.y));
|
||||
// the originalClosedPos is relative to the monitor's pos
|
||||
Vector2D scaleXY = Vector2D((PMONITOR->scale * PWINDOW->m_vRealSize.vec().x / (PWINDOW->m_vOriginalClosedSize.x * PMONITOR->scale)), (PMONITOR->scale * PWINDOW->m_vRealSize.vec().y / (PWINDOW->m_vOriginalClosedSize.y * PMONITOR->scale)));
|
||||
|
||||
windowBox.width = PMONITOR->vecPixelSize.x * scaleXY.x;
|
||||
windowBox.height = PMONITOR->vecPixelSize.y * scaleXY.y;
|
||||
windowBox.x = (PWINDOW->m_vRealPosition.vec().x - PMONITOR->vecPosition.x) - ((PWINDOW->m_vOriginalClosedPos.x - PMONITOR->vecPosition.x) * scaleXY.x);
|
||||
windowBox.y = (PWINDOW->m_vRealPosition.vec().y - PMONITOR->vecPosition.y) - ((PWINDOW->m_vOriginalClosedPos.y - PMONITOR->vecPosition.y) * scaleXY.y);
|
||||
// TODO: this is wrong on scaled.
|
||||
|
||||
windowBox.width = PMONITOR->vecTransformedSize.x * scaleXY.x;
|
||||
windowBox.height = PMONITOR->vecTransformedSize.y * scaleXY.y;
|
||||
windowBox.x = ((PWINDOW->m_vRealPosition.vec().x - PMONITOR->vecPosition.x) * PMONITOR->scale) - ((PWINDOW->m_vOriginalClosedPos.x * PMONITOR->scale) * scaleXY.x);
|
||||
windowBox.y = ((PWINDOW->m_vRealPosition.vec().y - PMONITOR->vecPosition.y) * PMONITOR->scale) - ((PWINDOW->m_vOriginalClosedPos.y * PMONITOR->scale) * scaleXY.y);
|
||||
|
||||
pixman_region32_t fakeDamage;
|
||||
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y);
|
||||
|
||||
renderTextureInternalWithDamage(it->second.m_cTex, &windowBox, PWINDOW->m_fAlpha.fl(), &fakeDamage, 0);
|
||||
|
||||
@@ -842,10 +854,10 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) {
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PLAYER->monitorID);
|
||||
|
||||
wlr_box windowBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
|
||||
wlr_box windowBox = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
|
||||
|
||||
pixman_region32_t fakeDamage;
|
||||
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
|
||||
pixman_region32_init_rect(&fakeDamage, 0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y);
|
||||
|
||||
renderTextureInternalWithDamage(it->second.m_cTex, &windowBox, PLAYER->alpha.fl(), &fakeDamage, 0);
|
||||
|
||||
@@ -855,13 +867,13 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) {
|
||||
void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, float a) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!");
|
||||
RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!");
|
||||
RASSERT(m_pCurrentWindow, "Tried to render shadow without a window!");
|
||||
|
||||
static auto *const PSHADOWCOL = &g_pConfigManager->getConfigValuePtr("decoration:col.shadow")->intValue;
|
||||
static auto *const PSHADOWPOWER = &g_pConfigManager->getConfigValuePtr("decoration:shadow_render_power")->intValue;
|
||||
|
||||
const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4);
|
||||
|
||||
const auto col = CColor(*PSHADOWCOL);
|
||||
const auto col = m_pCurrentWindow->m_cRealShadowColor.col();
|
||||
|
||||
float matrix[9];
|
||||
wlr_matrix_project_box(matrix, box, wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here
|
||||
@@ -878,19 +890,19 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
|
||||
glUseProgram(m_shSHADOW.program);
|
||||
|
||||
glUniformMatrix3fv(m_shSHADOW.proj, 1, GL_FALSE, glMatrix);
|
||||
glUniform4f(glGetUniformLocation(m_shSHADOW.program, "color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f * a);
|
||||
glUniform4f(m_shSHADOW.getUniformLocation("color"), col.r / 255.f, col.g / 255.f, col.b / 255.f, col.a / 255.f * a);
|
||||
|
||||
const auto TOPLEFT = Vector2D(range + round, range + round);
|
||||
const auto BOTTOMRIGHT = Vector2D(box->width - (range + round), box->height - (range + round));
|
||||
const auto FULLSIZE = Vector2D(box->width, box->height);
|
||||
|
||||
// Rounded corners
|
||||
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(glGetUniformLocation(m_shSHADOW.program, "fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "radius"), range + round);
|
||||
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "range"), range);
|
||||
glUniform1f(glGetUniformLocation(m_shSHADOW.program, "shadowPower"), SHADOWPOWER);
|
||||
glUniform2f(m_shSHADOW.getUniformLocation("topLeft"), (float)TOPLEFT.x, (float)TOPLEFT.y);
|
||||
glUniform2f(m_shSHADOW.getUniformLocation("bottomRight"), (float)BOTTOMRIGHT.x, (float)BOTTOMRIGHT.y);
|
||||
glUniform2f(m_shSHADOW.getUniformLocation("fullSize"), (float)FULLSIZE.x, (float)FULLSIZE.y);
|
||||
glUniform1f(m_shSHADOW.getUniformLocation("radius"), range + round);
|
||||
glUniform1f(m_shSHADOW.getUniformLocation("range"), range);
|
||||
glUniform1f(m_shSHADOW.getUniformLocation("shadowPower"), SHADOWPOWER);
|
||||
|
||||
glVertexAttribPointer(m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
glVertexAttribPointer(m_shSHADOW.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts);
|
||||
@@ -912,9 +924,28 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::renderSplash(cairo_t *const CAIRO, cairo_surface_t *const CAIROSURFACE) {
|
||||
cairo_select_font_face(CAIRO, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||
|
||||
const auto FONTSIZE = (int)(m_RenderData.pMonitor->vecPixelSize.y / 76);
|
||||
cairo_set_font_size(CAIRO, FONTSIZE);
|
||||
|
||||
cairo_set_source_rgba(CAIRO, 1.f, 1.f, 1.f, 0.32f);
|
||||
|
||||
cairo_text_extents_t textExtents;
|
||||
cairo_text_extents(CAIRO, g_pCompositor->m_szCurrentSplash.c_str(), &textExtents);
|
||||
|
||||
cairo_move_to(CAIRO, m_RenderData.pMonitor->vecPixelSize.x / 2.f - textExtents.width / 2.f, m_RenderData.pMonitor->vecPixelSize.y - textExtents.height - 1);
|
||||
cairo_show_text(CAIRO, g_pCompositor->m_szCurrentSplash.c_str());
|
||||
|
||||
cairo_surface_flush(CAIROSURFACE);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!");
|
||||
|
||||
static auto *const PNOSPLASH = &g_pConfigManager->getConfigValuePtr("misc:disable_splash_rendering")->intValue;
|
||||
|
||||
// release the last tex if exists
|
||||
const auto PTEX = &m_mMonitorBGTextures[pMonitor];
|
||||
PTEX->destroyTexture();
|
||||
@@ -923,6 +954,9 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
|
||||
|
||||
Debug::log(LOG, "Allocated texture for BGTex");
|
||||
|
||||
// TODO: use relative paths to the installation
|
||||
// or configure the paths at build time
|
||||
|
||||
// check if wallpapers exist
|
||||
if (!std::filesystem::exists("/usr/share/hyprland/wall_8K.png"))
|
||||
return; // the texture will be empty, oh well. We'll clear with a solid color anyways.
|
||||
@@ -946,6 +980,9 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
|
||||
|
||||
const auto CAIRO = cairo_create(CAIROSURFACE);
|
||||
|
||||
if (!*PNOSPLASH)
|
||||
renderSplash(CAIRO, CAIROSURFACE);
|
||||
|
||||
// copy the data to an OpenGL texture we have
|
||||
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
|
||||
glBindTexture(GL_TEXTURE_2D, PTEX->m_iTexID);
|
||||
@@ -966,9 +1003,12 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(SMonitor* pMonitor) {
|
||||
void CHyprOpenGLImpl::clearWithTex() {
|
||||
RASSERT(m_RenderData.pMonitor, "Tried to render BGtex without begin()!");
|
||||
|
||||
wlr_box box = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
static auto *const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue;
|
||||
|
||||
renderTexture(m_mMonitorBGTextures[m_RenderData.pMonitor], &box, 255, 0);
|
||||
if (!*PRENDERTEX) {
|
||||
wlr_box box = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y};
|
||||
renderTexture(m_mMonitorBGTextures[m_RenderData.pMonitor], &box, 255, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::destroyMonitorResources(SMonitor* pMonitor) {
|
||||
|
@@ -6,6 +6,8 @@
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <cairo/cairo.h>
|
||||
|
||||
#include "Shaders.hpp"
|
||||
#include "Shader.hpp"
|
||||
#include "Texture.hpp"
|
||||
@@ -29,17 +31,6 @@ inline const float fanVertsFull[] = {
|
||||
-1.0f, 1.0f
|
||||
};
|
||||
|
||||
struct SCurrentRenderData {
|
||||
SMonitor* pMonitor = nullptr;
|
||||
float projection[9];
|
||||
|
||||
pixman_region32_t* pDamage = nullptr;
|
||||
|
||||
bool renderingPrimarySurface = false;
|
||||
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
};
|
||||
|
||||
struct SMonitorRenderData {
|
||||
CFramebuffer primaryFB;
|
||||
CFramebuffer mirrorFB;
|
||||
@@ -48,6 +39,18 @@ struct SMonitorRenderData {
|
||||
CTexture stencilTex;
|
||||
};
|
||||
|
||||
struct SCurrentRenderData {
|
||||
SMonitor* pMonitor = nullptr;
|
||||
float projection[9];
|
||||
|
||||
SMonitorRenderData* pCurrentMonData = nullptr;
|
||||
|
||||
pixman_region32_t* pDamage = nullptr;
|
||||
|
||||
Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
};
|
||||
|
||||
class CHyprOpenGLImpl {
|
||||
public:
|
||||
|
||||
@@ -58,8 +61,8 @@ public:
|
||||
|
||||
void renderRect(wlr_box*, const CColor&, int round = 0);
|
||||
void renderRectWithDamage(wlr_box*, const CColor&, pixman_region32_t* damage, int round = 0);
|
||||
void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0);
|
||||
void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool allowPrimary = false);
|
||||
void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0, bool allowCustomUV = false);
|
||||
void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool allowCustomUV = false);
|
||||
void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0);
|
||||
void renderRoundedShadow(wlr_box*, int round, int range, float a = 1.0);
|
||||
void renderBorder(wlr_box*, const CColor&, int round);
|
||||
@@ -102,7 +105,7 @@ private:
|
||||
bool m_bEndFrame = false;
|
||||
|
||||
// Shaders
|
||||
SQuad m_shQUAD;
|
||||
CShader m_shQUAD;
|
||||
CShader m_shRGBA;
|
||||
CShader m_shRGBX;
|
||||
CShader m_shEXT;
|
||||
@@ -119,7 +122,9 @@ private:
|
||||
// returns the out FB, can be either Mirror or MirrorSwap
|
||||
CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage);
|
||||
|
||||
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowPrimary = false);
|
||||
void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowCustomUV = false);
|
||||
|
||||
void renderSplash(cairo_t *const, cairo_surface_t *const);
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CHyprOpenGLImpl> g_pHyprOpenGL;
|
@@ -12,31 +12,53 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) {
|
||||
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, RDATA->output, &outputX, &outputY);
|
||||
|
||||
wlr_box windowBox;
|
||||
if (RDATA->surface && surface == RDATA->surface) {
|
||||
if (RDATA->surface && surface == RDATA->surface)
|
||||
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, RDATA->w, RDATA->h};
|
||||
} else { // here we clamp to 2, these might be some tiny specks
|
||||
else // here we clamp to 2, these might be some tiny specks
|
||||
windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, std::clamp(surface->current.width, 2, 1337420), std::clamp(surface->current.height, 2, 1337420)};
|
||||
|
||||
// squish all oversized but dont in some cases, jesus christ this is a mess
|
||||
// TODO: this shouldn't be done this way. Custom UV here as well.
|
||||
// this is fucking horrible
|
||||
// Issue: will cause oversized apps with reserved area to overflow from the window box. (see chromium on ozone wayland)
|
||||
const auto PRESQUISHSIZE = Vector2D(windowBox.width, windowBox.height);
|
||||
if (RDATA->squishOversized) {
|
||||
if (x + windowBox.width > RDATA->w)
|
||||
windowBox.width = RDATA->w - x;
|
||||
if (y + windowBox.height > RDATA->h)
|
||||
windowBox.height = RDATA->h - y;
|
||||
}
|
||||
|
||||
scaleBox(&windowBox, RDATA->output->scale);
|
||||
|
||||
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
||||
|
||||
float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? *PROUNDING : RDATA->rounding;
|
||||
|
||||
g_pHyprOpenGL->m_RenderData.renderingPrimarySurface = false;
|
||||
|
||||
if (RDATA->surface && surface == RDATA->surface) {
|
||||
g_pHyprOpenGL->m_RenderData.renderingPrimarySurface = true;
|
||||
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding);
|
||||
|
||||
if (RDATA->decorate) {
|
||||
auto col = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor.col();
|
||||
col.a *= RDATA->fadeAlpha * RDATA->alpha / 255.f;
|
||||
g_pHyprOpenGL->renderBorder(&windowBox, col, rounding);
|
||||
}
|
||||
if (RDATA->blur)
|
||||
g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding);
|
||||
else
|
||||
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true);
|
||||
}
|
||||
else
|
||||
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false, false);
|
||||
else {
|
||||
if (RDATA->surface && wlr_surface_is_xdg_surface(RDATA->surface)) {
|
||||
wlr_box geo;
|
||||
wlr_xdg_surface_get_geometry(wlr_xdg_surface_from_wlr_surface(RDATA->surface), &geo);
|
||||
|
||||
// TODO: continuation of the above madness.
|
||||
if (geo.x != 0 || geo.y != 0) {
|
||||
windowBox.width = PRESQUISHSIZE.x;
|
||||
windowBox.height = PRESQUISHSIZE.y;
|
||||
}
|
||||
|
||||
windowBox.x -= geo.x;
|
||||
windowBox.y -= geo.y;
|
||||
}
|
||||
|
||||
g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false);
|
||||
}
|
||||
|
||||
|
||||
wlr_surface_send_frame_done(surface, RDATA->when);
|
||||
|
||||
@@ -54,8 +76,8 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) {
|
||||
return true;
|
||||
|
||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
||||
// if not, check if it maybe is active on a different monitor. vvv might be animation in progress
|
||||
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
|
||||
// if not, check if it maybe is active on a different monitor. vvv might be animation in progress
|
||||
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && PWORKSPACE->m_bForceRendering) || (PWORKSPACE && PWORKSPACE->m_iMonitorID == pMonitor->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated())))
|
||||
return true;
|
||||
|
||||
if (pMonitor->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||
@@ -74,11 +96,11 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
|
||||
if (g_pCompositor->isWorkspaceVisible(pWindow->m_iWorkspaceID))
|
||||
return true;
|
||||
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m.ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()))
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
if (PWORKSPACE && PWORKSPACE->m_iMonitorID == m->ID && (PWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWORKSPACE->m_fAlpha.isBeingAnimated()))
|
||||
return true;
|
||||
|
||||
if (m.specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||
if (m->specialWorkspaceOpen && pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -88,59 +110,59 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow) {
|
||||
void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, CWorkspace* pWorkspace, timespec* time) {
|
||||
CWindow* pWorkspaceWindow = nullptr;
|
||||
|
||||
for (auto& w : g_pCompositor->m_lWindows) {
|
||||
if (w.m_iWorkspaceID != pWorkspace->m_iID || !w.m_bIsFullscreen)
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID != pWorkspace->m_iID || !w->m_bIsFullscreen)
|
||||
continue;
|
||||
|
||||
// found it!
|
||||
renderWindow(&w, pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL);
|
||||
renderWindow(w.get(), pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL, RENDER_PASS_ALL);
|
||||
|
||||
pWorkspaceWindow = &w;
|
||||
pWorkspaceWindow = w.get();
|
||||
}
|
||||
|
||||
// then render windows over fullscreen
|
||||
for (auto& w : g_pCompositor->m_lWindows) {
|
||||
if (w.m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || !w.m_bCreatedOverFullscreen || !w.m_bIsMapped)
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || !w->m_bCreatedOverFullscreen || !w->m_bIsMapped)
|
||||
continue;
|
||||
|
||||
renderWindow(&w, pMonitor, time, true);
|
||||
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
|
||||
}
|
||||
|
||||
// and then special windows
|
||||
for (auto& w : g_pCompositor->m_lWindows) {
|
||||
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (!g_pCompositor->windowValidMapped(w.get()) && !w->m_bFadingOut)
|
||||
continue;
|
||||
|
||||
if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
|
||||
if (w->m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
|
||||
continue;
|
||||
|
||||
if (!shouldRenderWindow(&w, pMonitor))
|
||||
if (!shouldRenderWindow(w.get(), pMonitor))
|
||||
continue;
|
||||
|
||||
// render the bad boy
|
||||
renderWindow(&w, pMonitor, time, true);
|
||||
renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL);
|
||||
}
|
||||
|
||||
// and the overlay layers
|
||||
if (pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL) {
|
||||
// on non-full we draw the bar and shit
|
||||
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
renderLayer(ls, pMonitor, time);
|
||||
renderLayer(ls.get(), pMonitor, time);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& ls : pMonitor->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
|
||||
renderLayer(ls, pMonitor, time);
|
||||
renderLayer(ls.get(), pMonitor, time);
|
||||
}
|
||||
|
||||
renderDragIcon(pMonitor, time);
|
||||
|
||||
// if correct monitor draw hyprerror
|
||||
if (pMonitor == &g_pCompositor->m_lMonitors.front())
|
||||
if (pMonitor == g_pCompositor->m_vMonitors.front().get())
|
||||
g_pHyprError->draw();
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec* time, bool decorate) {
|
||||
void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec* time, bool decorate, eRenderPassMode mode) {
|
||||
if (pWindow->m_bHidden)
|
||||
return;
|
||||
|
||||
@@ -160,9 +182,10 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
|
||||
renderdata.h = std::clamp(pWindow->m_vRealSize.vec().y, (double)5, (double)1337420); // otherwise we'll have issues later with invalid boxes
|
||||
renderdata.dontRound = pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL;
|
||||
renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (PWORKSPACE->m_fAlpha.fl() / 255.f);
|
||||
renderdata.alpha = pWindow->m_bIsFullscreen ? g_pConfigManager->getFloat("decoration:fullscreen_opacity") : pWindow == g_pCompositor->m_pLastWindow ? g_pConfigManager->getFloat("decoration:active_opacity") : g_pConfigManager->getFloat("decoration:inactive_opacity");
|
||||
renderdata.alpha = pWindow->m_fActiveInactiveAlpha.fl();
|
||||
renderdata.decorate = decorate && !pWindow->m_bX11DoesntWantBorders && (pWindow->m_bIsFloating ? *PNOFLOATINGBORDERS == 0 : true) && (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL);
|
||||
renderdata.rounding = pWindow->m_sAdditionalConfigData.rounding;
|
||||
renderdata.blur = true; // if it shouldn't, it will be ignored later
|
||||
|
||||
// apply window special data
|
||||
if (pWindow->m_sSpecialRenderData.alphaInactive == -1)
|
||||
@@ -173,37 +196,71 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec*
|
||||
g_pHyprOpenGL->m_pCurrentWindow = pWindow;
|
||||
|
||||
// render window decorations first, if not fullscreen full
|
||||
if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) for (auto& wd : pWindow->m_dWindowDecorations)
|
||||
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha / 255.f);
|
||||
|
||||
if (!pWindow->m_bIsX11) {
|
||||
if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_MAIN) {
|
||||
if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) for (auto& wd : pWindow->m_dWindowDecorations)
|
||||
wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha / 255.f);
|
||||
|
||||
// To everyone who makes apps with improperly aligned surfaces,
|
||||
// For example chromium, or GTK devs who allow shadows on windows,
|
||||
// a sincere FUCK YOU.
|
||||
if (!pWindow->m_bIsX11) {
|
||||
wlr_box geom;
|
||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom);
|
||||
|
||||
wlr_box geom;
|
||||
wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom);
|
||||
// first, check for poorly sized windows.
|
||||
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D((double)geom.x / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)geom.y / (double)pWindow->m_uSurface.xdg->surface->current.height);
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D((double)(geom.width + geom.x) / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)(geom.y + geom.height) / (double)pWindow->m_uSurface.xdg->surface->current.height);
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D((double)geom.x / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)geom.y / (double)pWindow->m_uSurface.xdg->surface->current.height);
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D((double)(geom.width + geom.x) / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)(geom.y + geom.height) / (double)pWindow->m_uSurface.xdg->surface->current.height);
|
||||
|
||||
if (g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft == Vector2D() && g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight == Vector2D(1, 1)) {
|
||||
// No special UV mods needed
|
||||
if (g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft == Vector2D() && g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight == Vector2D(1, 1)) {
|
||||
// No special UV mods needed
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
}
|
||||
|
||||
// then, if the surface is too big, modify the pos UV
|
||||
if (geom.width > renderdata.w + 1 || geom.height > renderdata.h + 1) {
|
||||
const auto OFF = Vector2D(renderdata.w / (double)geom.width, renderdata.h / (double)geom.height);
|
||||
|
||||
if (g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft == Vector2D(-1, -1))
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(0, 0);
|
||||
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.x * ((double)renderdata.w / ((double)geom.width / g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.x)),
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.y * ((double)renderdata.h / ((double)geom.height / g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight.y))
|
||||
);
|
||||
}
|
||||
} else {
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
}
|
||||
|
||||
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata);
|
||||
|
||||
if (renderdata.decorate) {
|
||||
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
||||
|
||||
float rounding = renderdata.dontRound ? 0 : renderdata.rounding == -1 ? *PROUNDING : renderdata.rounding;
|
||||
|
||||
auto col = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor.col();
|
||||
col.a *= renderdata.fadeAlpha * renderdata.alpha / 255.f;
|
||||
|
||||
wlr_box windowBox = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h};
|
||||
|
||||
scaleBox(&windowBox, pMonitor->scale);
|
||||
|
||||
g_pHyprOpenGL->renderBorder(&windowBox, col, rounding);
|
||||
}
|
||||
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
}
|
||||
|
||||
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata);
|
||||
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1);
|
||||
g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1);
|
||||
|
||||
if (!pWindow->m_bIsX11) {
|
||||
renderdata.dontRound = false; // restore dontround
|
||||
renderdata.pMonitor = pMonitor;
|
||||
wlr_xdg_surface_for_each_popup_surface(pWindow->m_uSurface.xdg, renderSurface, &renderdata);
|
||||
if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_POPUP) {
|
||||
if (!pWindow->m_bIsX11) {
|
||||
renderdata.dontRound = false; // restore dontround
|
||||
renderdata.pMonitor = pMonitor;
|
||||
renderdata.squishOversized = false; // don't squish popups
|
||||
wlr_xdg_surface_for_each_popup_surface(pWindow->m_uSurface.xdg, renderSurface, &renderdata);
|
||||
}
|
||||
}
|
||||
|
||||
g_pHyprOpenGL->m_pCurrentWindow = nullptr;
|
||||
@@ -217,6 +274,11 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, SMonitor* pMonitor, times
|
||||
|
||||
SRenderData renderdata = {pMonitor->output, time, pLayer->geometry.x, pLayer->geometry.y};
|
||||
renderdata.fadeAlpha = pLayer->alpha.fl();
|
||||
renderdata.blur = pLayer->forceBlur;
|
||||
renderdata.surface = pLayer->layerSurface->surface;
|
||||
renderdata.decorate = false;
|
||||
renderdata.w = pLayer->layerSurface->surface->current.width;
|
||||
renderdata.h = pLayer->layerSurface->surface->current.height;
|
||||
wlr_surface_for_each_surface(pLayer->layerSurface->surface, renderSurface, &renderdata);
|
||||
}
|
||||
|
||||
@@ -228,10 +290,10 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
||||
|
||||
// Render layer surfaces below windows for monitor
|
||||
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) {
|
||||
renderLayer(ls, PMONITOR, time);
|
||||
renderLayer(ls.get(), PMONITOR, time);
|
||||
}
|
||||
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]) {
|
||||
renderLayer(ls, PMONITOR, time);
|
||||
renderLayer(ls.get(), PMONITOR, time);
|
||||
}
|
||||
|
||||
// if there is a fullscreen window, render it and then do not render anymore.
|
||||
@@ -243,63 +305,81 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Non-floating
|
||||
for (auto& w : g_pCompositor->m_lWindows) {
|
||||
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
|
||||
// Non-floating main
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
|
||||
continue;
|
||||
|
||||
if (w.m_bIsFloating)
|
||||
if (w->m_bIsFloating)
|
||||
continue; // floating are in the second pass
|
||||
|
||||
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||
continue; // special are in the third pass
|
||||
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||
continue; // special are in the third pass
|
||||
|
||||
if (!shouldRenderWindow(&w, PMONITOR))
|
||||
if (!shouldRenderWindow(w.get(), PMONITOR))
|
||||
continue;
|
||||
|
||||
// render the bad boy
|
||||
renderWindow(&w, PMONITOR, time, true);
|
||||
renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_MAIN);
|
||||
}
|
||||
|
||||
// Non-floating popup
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
|
||||
continue;
|
||||
|
||||
if (w->m_bIsFloating)
|
||||
continue; // floating are in the second pass
|
||||
|
||||
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||
continue; // special are in the third pass
|
||||
|
||||
if (!shouldRenderWindow(w.get(), PMONITOR))
|
||||
continue;
|
||||
|
||||
// render the bad boy
|
||||
renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_POPUP);
|
||||
}
|
||||
|
||||
// floating on top
|
||||
for (auto& w : g_pCompositor->m_lWindows) {
|
||||
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
|
||||
continue;
|
||||
|
||||
if (!w.m_bIsFloating)
|
||||
if (!w->m_bIsFloating)
|
||||
continue;
|
||||
|
||||
if (w.m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||
if (w->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
||||
continue;
|
||||
|
||||
if (!shouldRenderWindow(&w, PMONITOR))
|
||||
if (!shouldRenderWindow(w.get(), PMONITOR))
|
||||
continue;
|
||||
|
||||
// render the bad boy
|
||||
renderWindow(&w, PMONITOR, time, true);
|
||||
renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_ALL);
|
||||
}
|
||||
|
||||
// and then special
|
||||
for (auto& w : g_pCompositor->m_lWindows) {
|
||||
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
|
||||
for (auto& w : g_pCompositor->m_vWindows) {
|
||||
if (w->m_bHidden && !w->m_bIsMapped && !w->m_bFadingOut)
|
||||
continue;
|
||||
|
||||
if (w.m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
|
||||
if (w->m_iWorkspaceID != SPECIAL_WORKSPACE_ID)
|
||||
continue;
|
||||
|
||||
if (!shouldRenderWindow(&w, PMONITOR))
|
||||
if (!shouldRenderWindow(w.get(), PMONITOR))
|
||||
continue;
|
||||
|
||||
// render the bad boy
|
||||
renderWindow(&w, PMONITOR, time, true);
|
||||
renderWindow(w.get(), PMONITOR, time, true, RENDER_PASS_ALL);
|
||||
}
|
||||
|
||||
// Render surfaces above windows for monitor
|
||||
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
|
||||
renderLayer(ls, PMONITOR, time);
|
||||
renderLayer(ls.get(), PMONITOR, time);
|
||||
}
|
||||
for (auto& ls : PMONITOR->m_aLayerSurfaceLists[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) {
|
||||
renderLayer(ls, PMONITOR, time);
|
||||
renderLayer(ls.get(), PMONITOR, time);
|
||||
}
|
||||
|
||||
renderDragIcon(PMONITOR, time);
|
||||
@@ -424,11 +504,11 @@ void apply_exclusive(struct wlr_box* usable_area, uint32_t anchor, int32_t exclu
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprRenderer::arrangeLayerArray(SMonitor* pMonitor, const std::list<SLayerSurface*>& layerSurfaces, bool exclusiveZone, wlr_box* usableArea) {
|
||||
void CHyprRenderer::arrangeLayerArray(SMonitor* pMonitor, const std::vector<std::unique_ptr<SLayerSurface>>& layerSurfaces, bool exclusiveZone, wlr_box* usableArea) {
|
||||
wlr_box full_area = {pMonitor->vecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y};
|
||||
|
||||
for (auto& ls : layerSurfaces) {
|
||||
if (ls->fadingOut || ls->readyToDelete)
|
||||
if (ls->fadingOut || ls->readyToDelete || !ls->layerSurface || ls->noProcess)
|
||||
continue;
|
||||
|
||||
const auto PLAYER = ls->layerSurface;
|
||||
@@ -497,7 +577,7 @@ void CHyprRenderer::arrangeLayerArray(SMonitor* pMonitor, const std::list<SLayer
|
||||
box.y -= PSTATE->margin.bottom;
|
||||
}
|
||||
if (box.width <= 0 || box.height <= 0) {
|
||||
Debug::log(ERR, "LayerSurface %x has a negative/zero w/h???", ls);
|
||||
Debug::log(ERR, "LayerSurface %x has a negative/zero w/h???", ls.get());
|
||||
continue;
|
||||
}
|
||||
// Apply
|
||||
@@ -551,6 +631,11 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
|
||||
pixman_region32_init(&damageBox);
|
||||
wlr_surface_get_effective_damage(pSurface, &damageBox);
|
||||
|
||||
// schedule frame events
|
||||
if (!wl_list_empty(&pSurface->current.frame_callback_list)) {
|
||||
g_pCompositor->scheduleFrameForMonitor(g_pCompositor->getMonitorFromVector(Vector2D(x, y)));
|
||||
}
|
||||
|
||||
if (!pixman_region32_not_empty(&damageBox)) {
|
||||
pixman_region32_fini(&damageBox);
|
||||
return;
|
||||
@@ -558,57 +643,35 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y) {
|
||||
|
||||
pixman_region32_translate(&damageBox, x, y);
|
||||
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
double lx = 0, ly = 0;
|
||||
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, m.output, &lx, &ly);
|
||||
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, m->output, &lx, &ly);
|
||||
pixman_region32_translate(&damageBox, lx, ly);
|
||||
wlr_region_scale(&damageBox, &damageBox, m.scale);
|
||||
wlr_output_damage_add(m.damage, &damageBox);
|
||||
wlr_region_scale(&damageBox, &damageBox, m->scale);
|
||||
wlr_output_damage_add(m->damage, &damageBox);
|
||||
pixman_region32_translate(&damageBox, -lx, -ly);
|
||||
}
|
||||
|
||||
pixman_region32_fini(&damageBox);
|
||||
|
||||
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
||||
|
||||
if (*PLOGDAMAGE)
|
||||
Debug::log(LOG, "Damage: Surface (extents): xy: %d, %d wh: %d, %d", damageBox.extents.x1, damageBox.extents.y1, damageBox.extents.x2 - damageBox.extents.x1, damageBox.extents.y2 - damageBox.extents.y1);
|
||||
|
||||
pixman_region32_fini(&damageBox);
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageWindow(CWindow* pWindow) {
|
||||
if (!pWindow->m_bIsFloating) {
|
||||
// damage by size & pos
|
||||
// TODO TEMP: revise when added shadows/etc
|
||||
|
||||
wlr_box damageBox = pWindow->getFullWindowBoundingBox();
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
wlr_box fixedDamageBox = damageBox;
|
||||
fixedDamageBox.x -= m.vecPosition.x;
|
||||
fixedDamageBox.y -= m.vecPosition.y;
|
||||
scaleBox(&fixedDamageBox, m.scale);
|
||||
wlr_output_damage_add_box(m.damage, &fixedDamageBox);
|
||||
}
|
||||
|
||||
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
||||
|
||||
if (*PLOGDAMAGE)
|
||||
Debug::log(LOG, "Damage: Window floated (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
|
||||
} else {
|
||||
// damage by real size & pos + border size * 2 (JIC)
|
||||
wlr_box damageBox = pWindow->getFullWindowBoundingBox();
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
wlr_box fixedDamageBox = damageBox;
|
||||
fixedDamageBox.x -= m.vecPosition.x;
|
||||
fixedDamageBox.y -= m.vecPosition.y;
|
||||
scaleBox(&fixedDamageBox, m.scale);
|
||||
wlr_output_damage_add_box(m.damage, &fixedDamageBox);
|
||||
}
|
||||
|
||||
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
||||
|
||||
if (*PLOGDAMAGE)
|
||||
Debug::log(LOG, "Damage: Window tiled (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
|
||||
wlr_box damageBox = pWindow->getFullWindowBoundingBox();
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
wlr_box fixedDamageBox = {damageBox.x - m->vecPosition.x, damageBox.y - m->vecPosition.y, damageBox.width, damageBox.height};
|
||||
scaleBox(&fixedDamageBox, m->scale);
|
||||
wlr_output_damage_add_box(m->damage, &fixedDamageBox);
|
||||
}
|
||||
|
||||
static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
||||
|
||||
if (*PLOGDAMAGE)
|
||||
Debug::log(LOG, "Damage: Window (%s): xy: %d, %d wh: %d, %d", pWindow->m_szTitle.c_str(), damageBox.x, damageBox.y, damageBox.width, damageBox.height);
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageMonitor(SMonitor* pMonitor) {
|
||||
@@ -622,10 +685,10 @@ void CHyprRenderer::damageMonitor(SMonitor* pMonitor) {
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageBox(wlr_box* pBox) {
|
||||
for (auto& m : g_pCompositor->m_lMonitors) {
|
||||
wlr_box damageBox = {pBox->x - m.vecPosition.x, pBox->y - m.vecPosition.y, pBox->width, pBox->height};
|
||||
scaleBox(&damageBox, m.scale);
|
||||
wlr_output_damage_add_box(m.damage, &damageBox);
|
||||
for (auto& m : g_pCompositor->m_vMonitors) {
|
||||
wlr_box damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height};
|
||||
scaleBox(&damageBox, m->scale);
|
||||
wlr_output_damage_add_box(m->damage, &damageBox);
|
||||
}
|
||||
|
||||
static auto *const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue;
|
||||
@@ -639,6 +702,13 @@ void CHyprRenderer::damageBox(const int& x, const int& y, const int& w, const in
|
||||
damageBox(&box);
|
||||
}
|
||||
|
||||
void CHyprRenderer::damageRegion(pixman_region32_t* rg) {
|
||||
PIXMAN_DAMAGE_FOREACH(rg) {
|
||||
const auto RECT = RECTSARR[i];
|
||||
damageBox(RECT.x1, RECT.y1, RECT.x2 - RECT.x1, RECT.y2 - RECT.y1);
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderDragIcon(SMonitor* pMonitor, timespec* time) {
|
||||
if (!(g_pInputManager->m_sDrag.dragIcon && g_pInputManager->m_sDrag.iconMapped && g_pInputManager->m_sDrag.dragIcon->surface))
|
||||
return;
|
||||
@@ -649,6 +719,9 @@ void CHyprRenderer::renderDragIcon(SMonitor* pMonitor, timespec* time) {
|
||||
renderdata.h = g_pInputManager->m_sDrag.dragIcon->surface->current.height;
|
||||
|
||||
wlr_surface_for_each_surface(g_pInputManager->m_sDrag.dragIcon->surface, renderSurface, &renderdata);
|
||||
|
||||
wlr_box box = {g_pInputManager->m_sDrag.pos.x - 2, g_pInputManager->m_sDrag.pos.y - 2, g_pInputManager->m_sDrag.dragIcon->surface->current.width + 4, g_pInputManager->m_sDrag.dragIcon->surface->current.height + 4};
|
||||
g_pHyprRenderer->damageBox(&box);
|
||||
}
|
||||
|
||||
DAMAGETRACKINGMODES CHyprRenderer::damageTrackingModeFromStr(const std::string& mode) {
|
||||
@@ -662,14 +735,23 @@ DAMAGETRACKINGMODES CHyprRenderer::damageTrackingModeFromStr(const std::string&
|
||||
return DAMAGE_TRACKING_INVALID;
|
||||
}
|
||||
|
||||
void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorRule, bool force) {
|
||||
bool CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorRule, bool force) {
|
||||
|
||||
Debug::log(LOG, "Applying monitor rule for %s", pMonitor->szName.c_str());
|
||||
|
||||
// if it's disabled, disable and ignore
|
||||
if (pMonitorRule->disabled) {
|
||||
wlr_output_enable(pMonitor->output, 0);
|
||||
wlr_output_commit(pMonitor->output);
|
||||
|
||||
Events::listener_monitorDestroy(nullptr, pMonitor->output);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the rule isn't already applied
|
||||
if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, pMonitorRule->resolution.y, 1) && DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->scale == pMonitorRule->scale && DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1) && pMonitor->transform == pMonitorRule->transform) {
|
||||
Debug::log(LOG, "Not applying a new rule to %s because it's already applied!", pMonitor->szName.c_str());
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
wlr_output_set_scale(pMonitor->output, pMonitorRule->scale);
|
||||
@@ -719,7 +801,7 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
if (!PREFERREDMODE) {
|
||||
Debug::log(ERR, "Monitor %s has NO PREFERRED MODE, and an INVALID one was requested: %ix%i@%2f",
|
||||
(int)pMonitorRule->resolution.x, (int)pMonitorRule->resolution.y, (float)pMonitorRule->refreshRate);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Preferred is valid
|
||||
@@ -750,7 +832,7 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
|
||||
if (!wlr_output_commit(pMonitor->output)) {
|
||||
Debug::log(ERR, "Couldn't commit output named %s", pMonitor->output->name);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
int x, y;
|
||||
@@ -772,6 +854,8 @@ void CHyprRenderer::applyMonitorRule(SMonitor* pMonitor, SMonitorRule* pMonitorR
|
||||
|
||||
// frame skip
|
||||
pMonitor->framesToSkip = 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CHyprRenderer::ensureCursorRenderingMode() {
|
||||
@@ -787,8 +871,8 @@ void CHyprRenderer::ensureCursorRenderingMode() {
|
||||
|
||||
Debug::log(LOG, "Hiding the cursor (timeout)");
|
||||
|
||||
for (auto& m : g_pCompositor->m_lMonitors)
|
||||
g_pHyprRenderer->damageMonitor(&m); // TODO: maybe just damage the cursor area?
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
|
||||
} else if (*PCURSORTIMEOUT > PASSEDCURSORSECONDS && !m_bHasARenderedCursor) {
|
||||
m_bHasARenderedCursor = true;
|
||||
|
||||
@@ -797,8 +881,8 @@ void CHyprRenderer::ensureCursorRenderingMode() {
|
||||
|
||||
Debug::log(LOG, "Showing the cursor (timeout)");
|
||||
|
||||
for (auto& m : g_pCompositor->m_lMonitors)
|
||||
g_pHyprRenderer->damageMonitor(&m); // TODO: maybe just damage the cursor area?
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area?
|
||||
}
|
||||
} else {
|
||||
m_bHasARenderedCursor = true;
|
||||
@@ -807,4 +891,4 @@ void CHyprRenderer::ensureCursorRenderingMode() {
|
||||
|
||||
bool CHyprRenderer::shouldRenderCursor() {
|
||||
return m_bHasARenderedCursor;
|
||||
}
|
||||
}
|
||||
|
@@ -17,6 +17,12 @@ enum DAMAGETRACKINGMODES {
|
||||
DAMAGE_TRACKING_FULL
|
||||
};
|
||||
|
||||
enum eRenderPassMode {
|
||||
RENDER_PASS_ALL = 0,
|
||||
RENDER_PASS_MAIN,
|
||||
RENDER_PASS_POPUP
|
||||
};
|
||||
|
||||
class CHyprRenderer {
|
||||
public:
|
||||
|
||||
@@ -27,8 +33,9 @@ public:
|
||||
void damageWindow(CWindow*);
|
||||
void damageBox(wlr_box*);
|
||||
void damageBox(const int& x, const int& y, const int& w, const int& h);
|
||||
void damageRegion(pixman_region32_t*);
|
||||
void damageMonitor(SMonitor*);
|
||||
void applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false);
|
||||
bool applyMonitorRule(SMonitor*, SMonitorRule*, bool force = false);
|
||||
bool shouldRenderWindow(CWindow*, SMonitor*);
|
||||
bool shouldRenderWindow(CWindow*);
|
||||
void ensureCursorRenderingMode();
|
||||
@@ -39,9 +46,9 @@ public:
|
||||
DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&);
|
||||
|
||||
private:
|
||||
void arrangeLayerArray(SMonitor*, const std::list<SLayerSurface*>&, bool, wlr_box*);
|
||||
void arrangeLayerArray(SMonitor*, const std::vector<std::unique_ptr<SLayerSurface>>&, bool, wlr_box*);
|
||||
void renderWorkspaceWithFullscreenWindow(SMonitor*, CWorkspace*, timespec*);
|
||||
void renderWindow(CWindow*, SMonitor*, timespec*, bool);
|
||||
void renderWindow(CWindow*, SMonitor*, timespec*, bool, eRenderPassMode);
|
||||
void renderLayer(SLayerSurface*, SMonitor*, timespec*);
|
||||
void renderDragIcon(SMonitor*, timespec*);
|
||||
|
||||
|
@@ -0,0 +1,13 @@
|
||||
#include "Shader.hpp"
|
||||
|
||||
GLint CShader::getUniformLocation(const std::string& unif) {
|
||||
const auto itpos = m_muUniforms.find(unif);
|
||||
|
||||
if (itpos == m_muUniforms.end()) {
|
||||
const auto unifLoc = glGetUniformLocation(program, unif.c_str());
|
||||
m_muUniforms[unif] = unifLoc;
|
||||
return unifLoc;
|
||||
}
|
||||
|
||||
return itpos->second;
|
||||
}
|
@@ -1,22 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "../defines.hpp"
|
||||
|
||||
struct SQuad {
|
||||
GLuint program;
|
||||
GLint proj;
|
||||
GLint color;
|
||||
GLint posAttrib;
|
||||
GLint texAttrib;
|
||||
};
|
||||
#include <unordered_map>
|
||||
|
||||
class CShader {
|
||||
public:
|
||||
GLuint program;
|
||||
GLint proj;
|
||||
GLint color;
|
||||
GLint tex;
|
||||
GLint alpha;
|
||||
GLint posAttrib;
|
||||
GLint texAttrib;
|
||||
GLint discardOpaque;
|
||||
|
||||
GLint getUniformLocation(const std::string&);
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, GLint> m_muUniforms;
|
||||
};
|
@@ -53,6 +53,9 @@ void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) {
|
||||
if (!g_pCompositor->windowValidMapped(m_pWindow))
|
||||
return;
|
||||
|
||||
if (m_pWindow->m_cRealShadowColor.col() == CColor(0, 0, 0, 0))
|
||||
return; // don't draw invisible shadows
|
||||
|
||||
static auto *const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue;
|
||||
static auto *const PSHADOWSIZE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_range")->intValue;
|
||||
static auto *const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue;
|
||||
@@ -99,6 +102,8 @@ void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) {
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
|
||||
wlr_box windowBox = {m_vLastWindowPos.x - pMonitor->vecPosition.x, m_vLastWindowPos.y - pMonitor->vecPosition.y, m_vLastWindowSize.x, m_vLastWindowSize.y};
|
||||
|
||||
scaleBox(&windowBox, pMonitor->scale);
|
||||
|
||||
if (windowBox.width < 1 || windowBox.height < 1) {
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
@@ -110,7 +115,8 @@ void CHyprDropShadowDecoration::draw(SMonitor* pMonitor, float a) {
|
||||
glStencilFunc(GL_NOTEQUAL, 1, -1);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
}
|
||||
|
||||
|
||||
scaleBox(&fullBox, pMonitor->scale);
|
||||
g_pHyprOpenGL->renderRoundedShadow(&fullBox, *PROUNDING, *PSHADOWSIZE, a);
|
||||
|
||||
if (*PSHADOWIGNOREWINDOW) {
|
||||
|
@@ -40,12 +40,8 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
|
||||
|
||||
if (g_pLayoutManager->getCurrentLayout()->getLayoutName() != "dwindle") {
|
||||
// ????
|
||||
for (auto it = pWindow->m_dWindowDecorations.begin(); it != pWindow->m_dWindowDecorations.end(); it++) {
|
||||
if (it->get() == this) {
|
||||
pWindow->m_dWindowDecorations.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_pWindow->m_vDecosToRemove.push_back(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// get the group info
|
||||
@@ -58,12 +54,8 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
|
||||
|
||||
if (m_dwGroupMembers.size() == 0) {
|
||||
// remove
|
||||
for (auto it = pWindow->m_dWindowDecorations.begin(); it != pWindow->m_dWindowDecorations.end(); it++) {
|
||||
if (it->get() == this) {
|
||||
pWindow->m_dWindowDecorations.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_pWindow->m_vDecosToRemove.push_back(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -16,7 +16,7 @@ struct SWindowDecorationExtents {
|
||||
class CWindow;
|
||||
struct SMonitor;
|
||||
|
||||
class IHyprWindowDecoration {
|
||||
interface IHyprWindowDecoration {
|
||||
public:
|
||||
virtual ~IHyprWindowDecoration() = 0;
|
||||
|
||||
|
@@ -34,8 +34,7 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = )#" + colorVarName + R"#( * distances;
|
||||
return;
|
||||
)#" + colorVarName + R"#( = )#" + colorVarName + R"#( * distances;
|
||||
}
|
||||
}
|
||||
} else if (pixCoord[1] > bottomRight[1]) {
|
||||
@@ -66,8 +65,7 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = )#" + colorVarName + R"#( * distances;
|
||||
return;
|
||||
)#" + colorVarName + R"#( = )#" + colorVarName + R"#( * distances;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,8 +100,7 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = )#" + colorVarName + R"#( * distances;
|
||||
return;
|
||||
)#" + colorVarName + R"#( = )#" + colorVarName + R"#( * distances;
|
||||
}
|
||||
}
|
||||
} else if (pixCoord[1] > bottomRight[1]) {
|
||||
@@ -134,8 +131,7 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar
|
||||
|
||||
distances = distances / 4.0;
|
||||
|
||||
gl_FragColor = )#" + colorVarName + R"#( * distances;
|
||||
return;
|
||||
)#" + colorVarName + R"#( = )#" + colorVarName + R"#( * distances;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -176,11 +172,13 @@ void main() {
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 pixColor = v_color;
|
||||
|
||||
vec2 pixCoord = fullSize * v_texcoord;
|
||||
|
||||
)#" + ROUNDED_SHADER_FUNC("v_color") + R"#(
|
||||
)#" + ROUNDED_SHADER_FUNC("pixColor") + R"#(
|
||||
|
||||
gl_FragColor = v_color;
|
||||
gl_FragColor = pixColor;
|
||||
})#";
|
||||
|
||||
inline const std::string TEXVERTSRC = R"#(
|
||||
|