Compare commits

..

11 Commits

Author SHA1 Message Date
Vaxry
0bd541f2fd version: bump to 0.46.2 2024-12-19 19:26:47 +00:00
Aqa-Ib
23d00cdd0d layout: apply group rules after window creation (#8779)
* apply group rules after window creation

* clang-format
2024-12-19 19:26:40 +00:00
Vaxry
061241d3a2 core: fix possible crash on null active workspace
fixes #7822
2024-12-19 19:26:40 +00:00
Aaron Blasko
b9df70be22 hyprpm: fix hyrpm sometimes returning 0 despite errors occuring (#8761)
* hyprpm: fix hyrpm sometimes returning 0 despite errors occuring

* there u go
2024-12-19 19:26:40 +00:00
Jan Beich
9583429eae core: Unbreak build on FreeBSD (#8762)
* CrashReporter: restore explicit environ(7) after 8bbeee1173

BSD systems don't declare environ(7) in any header like POSIX suggests.

src/signal-safe.cpp:12:23: error: use of undeclared identifier 'environ'
   12 |     for (char** var = environ; *var != nullptr; var++) {
      |                       ^

* fix

---------

Co-authored-by: Vaxry <vaxry@vaxry.net>
2024-12-19 19:26:40 +00:00
Vaxry
747c38112b xwayland: fix compile with no xwayland 2024-12-19 19:26:40 +00:00
Vaxry
508e82341f xwm: fixup targets in selection requests
fixes #8719
2024-12-19 19:26:40 +00:00
Vaxry
ec0a38303b xwayland: fix dnd including xwayland
ref #8759
2024-12-19 19:26:40 +00:00
Vaxry
d0bffc4fa9 core: avoid activating toplevel-less surfaces
ref #8609
2024-12-19 19:26:40 +00:00
Khalid
07a19e2c95 hyprctl: Fix hyprctl batch JSON command (#8749) 2024-12-19 19:26:40 +00:00
Vaxry
46d5b363fa windowrules: fixup duplicate rule enum tags
fixes #8746
2024-12-19 19:26:40 +00:00
303 changed files with 5301 additions and 10568 deletions

View File

@@ -5,10 +5,10 @@ body:
- type: checkboxes - type: checkboxes
attributes: attributes:
label: Already reported ? * label: Already reported ? *
description: Before opening a new bug report, please take a moment to search through the current open issues. If the same bug is already reported, don't open new issue - instead go upvote/comment on an existing one. description: Before opening a new bug report, please take a moment to search through the current open and closed issues to check if it already exists.
options: options:
- label: I have searched the existing open and closed issues. - label: I have searched the existing open and closed issues.
required: true required: true
- type: dropdown - type: dropdown
id: type id: type
@@ -19,28 +19,27 @@ body:
**BEFORE CONTINUING**, please check if this bug is a regression or not, and if it is, we need you to bisect with the help of the wiki: https://wiki.hyprland.org/Crashes-and-Bugs/#bisecting-an-issue **BEFORE CONTINUING**, please check if this bug is a regression or not, and if it is, we need you to bisect with the help of the wiki: https://wiki.hyprland.org/Crashes-and-Bugs/#bisecting-an-issue
multiple: true multiple: true
options: options:
- "Definitely a regression - something broke after update (requires bisect)" - "Yes"
- "Probably not a regression / I don't remember it happening before" - "No"
- "Not a regression - it's bug regarding new feature"
- "Not a regression - it's an old bug"
- "I don't know, I started using Hyprland only recently"
validations: validations:
required: true required: true
- type: textarea - type: textarea
id: ver id: ver
attributes: attributes:
label: System Info and Hyprland Version label: System Info and Version
description: | description: |
Paste the output of `hyprctl systeminfo` here. If you can't Paste the output of `hyprctl systeminfo -c` here. If you can't
launch Hyprland, paste the output of `Hyprland --systeminfo`. launch Hyprland, paste the output of `Hyprland --systeminfo`.
If `Hyprland --systeminfo` errors out (added in 0.44.0), find
and paste the Hyprland version manually.
value: "<details> value: "<details>
<summary>System/Version info</summary> <summary>System/Version info</summary>
``` ```sh
<Paste the output of the command here, without removing any formatting around this> <Paste the output of the command here>
``` ```
@@ -62,56 +61,15 @@ body:
attributes: attributes:
label: How to reproduce label: How to reproduce
description: "How can someone else reproduce the issue?" description: "How can someone else reproduce the issue?"
placeholder: |
1. ...
2. ...
3. ...
validations: validations:
required: true required: true
- type: markdown
attributes:
value: |
## Additional info section
In the section below you will be asked to upload some files.
When including text files (such as logs or config), please **always ATTACH** them, and not paste them directly.
This is important to avoid clutter, spam, and make the issues more readable.
Thanks for your understanding.
# The main reason to disallow pasting directly or in a dropdown, is to not clutter
# the issue with unnecessary keywords, making the github issue search useless.
- type: checkboxes
attributes:
label: Attach not paste
options:
- label: I understand that all text files must be *attached*, and not pasted directly. If not respected, this issue will likely get closed as spam
required: true
- type: markdown
attributes:
value: >-
Please be sure to upload the following files below if they are relevant to the issue:
- Logs can be found in $XDG_RUNTIME_DIR/hypr (sort by date to grab the latest)
- Crash reports are stored in ~/.cache/hyprland or $XDG_CACHE_HOME/hyprland
- Hyprland config files - `hyprctl systeminfo -c > /tmp/hyprland_config_dump.txt` use this command to dump full configuration to a single file.
- type: checkboxes
attributes:
label: Checklist of files to include below
options:
- label: Hyprland config - `hyprctl systeminfo -c` (always include)
- label: Crash report (always include in case of crash)
- label: Video (always include in case of a visual bug)
- label: Logs (might contain useful info such as errors)
- type: textarea - type: textarea
id: logs id: logs
attributes: attributes:
label: Additional info & File uploads label: Crash reports, logs, images, videos
description: | description: |
Tip: You can attach files by clicking this area to highlight it and then dragging files in. Anything that can help. Please always ATTACH and not paste them.
Logs can be found in $XDG_RUNTIME_DIR/hypr
Crash reports are stored in ~/.cache/hyprland or $XDG_CACHE_HOME/hyprland

View File

@@ -63,15 +63,6 @@ runs:
librsvg \ librsvg \
re2 re2
- name: Get glaze
shell: bash
run: |
git clone https://github.com/stephenberry/glaze.git
cd glaze
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -S . -B ./build
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
cmake --install build
- name: Get hyprwayland-scanner-git - name: Get hyprwayland-scanner-git
shell: bash shell: bash
run: | run: |

View File

@@ -107,7 +107,6 @@ jobs:
run: make release run: make release
clang-format: clang-format:
permissions: read-all
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
name: "Code Style (Arch)" name: "Code Style (Arch)"
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -127,27 +126,3 @@ jobs:
- name: clang-format check - name: clang-format check
run: ninja -C build clang-format-check run: ninja -C build clang-format-check
- name: clang-format apply
if: ${{ failure() && github.event_name == 'pull_request' }}
run: ninja -C build clang-format
- name: Create patch
if: ${{ failure() && github.event_name == 'pull_request' }}
run: |
echo 'Please fix the formatting issues by running [`clang-format`](https://wiki.hyprland.org/Contributing-and-Debugging/PR-Guidelines/#code-style), or directly apply this patch:' > clang-format.patch
echo '<details>' >> clang-format.patch
echo '<summary>clang-format.patch</summary>' >> clang-format.patch
echo >> clang-format.patch
echo '```diff' >> clang-format.patch
git diff >> clang-format.patch
echo '```' >> clang-format.patch
echo >> clang-format.patch
echo '</details>' >> clang-format.patch
- name: Comment patch
if: ${{ failure() && github.event_name == 'pull_request' }}
uses: mshick/add-pr-comment@v2
with:
message-path: |
clang-format.patch

View File

@@ -104,7 +104,7 @@ find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5) pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5)
pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2) pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2)
pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7) pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7)
pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.4.0) pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.2.3)
pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.1) pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.1)
add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}") add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}")
@@ -197,12 +197,6 @@ if(NOT HAS_TIMERFD AND epoll_FOUND)
target_link_libraries(Hyprland PkgConfig::epoll) target_link_libraries(Hyprland PkgConfig::epoll)
endif() endif()
check_include_file("sys/inotify.h" HAS_INOTIFY)
pkg_check_modules(inotify IMPORTED_TARGET libinotify)
if(NOT HAS_INOTIFY AND inotify_FOUND)
target_link_libraries(Hyprland PkgConfig::inotify)
endif()
if(LEGACY_RENDERER) if(LEGACY_RENDERER)
message(STATUS "Using the legacy GLES2 renderer!") message(STATUS "Using the legacy GLES2 renderer!")
add_compile_definitions(LEGACY_RENDERER) add_compile_definitions(LEGACY_RENDERER)
@@ -254,15 +248,7 @@ target_precompile_headers(Hyprland PRIVATE
message(STATUS "Setting link libraries") message(STATUS "Setting link libraries")
target_link_libraries( target_link_libraries(Hyprland rt PkgConfig::aquamarine_dep PkgConfig::hyprlang_dep PkgConfig::hyprutils_dep PkgConfig::hyprcursor_dep PkgConfig::hyprgraphics_dep PkgConfig::deps)
Hyprland
rt
PkgConfig::aquamarine_dep
PkgConfig::hyprlang_dep
PkgConfig::hyprutils_dep
PkgConfig::hyprcursor_dep
PkgConfig::hyprgraphics_dep
PkgConfig::deps)
if(udis_dep_FOUND) if(udis_dep_FOUND)
target_link_libraries(Hyprland PkgConfig::udis_dep) target_link_libraries(Hyprland PkgConfig::udis_dep)
else() else()
@@ -304,7 +290,7 @@ endfunction()
target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads) target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads)
pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.6.0) pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.4.0)
if(hyprland_protocols_dep_FOUND) if(hyprland_protocols_dep_FOUND)
pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir) pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir)
message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}") message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}")
@@ -330,12 +316,8 @@ protocolnew("protocols" "kde-server-decoration" true)
protocolnew("protocols" "wlr-data-control-unstable-v1" true) protocolnew("protocols" "wlr-data-control-unstable-v1" true)
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-focus-grab-v1" true) protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-focus-grab-v1" true)
protocolnew("protocols" "wlr-layer-shell-unstable-v1" true) protocolnew("protocols" "wlr-layer-shell-unstable-v1" true)
protocolnew("protocols" "xx-color-management-v4" true)
protocolnew("protocols" "frog-color-management-v1" true)
protocolnew("protocols" "wayland-drm" true) protocolnew("protocols" "wayland-drm" true)
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-ctm-control-v1" true) protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-ctm-control-v1" true)
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-surface-v1" true)
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-lock-notify-v1" true)
protocolnew("staging/tearing-control" "tearing-control-v1" false) protocolnew("staging/tearing-control" "tearing-control-v1" false)
protocolnew("staging/fractional-scale" "fractional-scale-v1" false) protocolnew("staging/fractional-scale" "fractional-scale-v1" false)
@@ -373,13 +355,7 @@ protocolwayland()
# tools # tools
add_subdirectory(hyprctl) add_subdirectory(hyprctl)
add_subdirectory(hyprpm)
if(NO_HYPRPM)
message(STATUS "hyprpm is disabled")
else()
add_subdirectory(hyprpm)
message(STATUS "hyprpm is enabled (NO_HYPRPM not defined)")
endif()
# binary and symlink # binary and symlink
install(TARGETS Hyprland) install(TARGETS Hyprland)
@@ -390,6 +366,7 @@ install(
${CMAKE_INSTALL_FULL_BINDIR}/Hyprland \ ${CMAKE_INSTALL_FULL_BINDIR}/Hyprland \
\"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/hyprland\" \ \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_BINDIR}/hyprland\" \
)") )")
# session file # session file
install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.desktop
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions) DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions)

View File

@@ -1 +1 @@
0.47.1 0.46.2

View File

@@ -81,7 +81,6 @@ general {
# https://wiki.hyprland.org/Configuring/Variables/#decoration # https://wiki.hyprland.org/Configuring/Variables/#decoration
decoration { decoration {
rounding = 10 rounding = 10
rounding_power = 2
# Change transparency of focused and unfocused windows # Change transparency of focused and unfocused windows
active_opacity = 1.0 active_opacity = 1.0

View File

@@ -22,6 +22,5 @@
} }
] ]
}, },
] ]
} }

173
flake.lock generated
View File

@@ -16,11 +16,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1737636397, "lastModified": 1734364797,
"narHash": "sha256-F5MbBj3QVorycVSFE9qjuOTLtIQBqt2VWbXa0uwzm98=", "narHash": "sha256-2h1c+P0v3l0Z/ypUSsAPhU/yiSRgFwjVFODWp0S3d/w=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "aquamarine", "repo": "aquamarine",
"rev": "7fe006981fae53e931f513026fc754e322f13145", "rev": "8e77618b403a82fde2105a8e3cd7cabe7ef00952",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -79,11 +79,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1737634937, "lastModified": 1734364709,
"narHash": "sha256-Ffw4ujFpi++6pPHe+gCBOfDgAoNlzVPZN6MReC1beu8=", "narHash": "sha256-+2bZJL2u5hva7rSp65OfKJBK+k03T6GB/NCvpoS1OOo=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprcursor", "repo": "hyprcursor",
"rev": "9c5dd1f7c825ee47f72727ad0a4e16ca46a2688e", "rev": "f388aacd22be4a6e4d634fbaf6f75eb0713d239a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -105,11 +105,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1737634889, "lastModified": 1733684019,
"narHash": "sha256-9JZE3KxcXOqZH9zs3UeadngDiK/yIACTiAR8HSA/TNI=", "narHash": "sha256-2kYREgmSmbLsmDpLEq96hxVAU3qz8aCvVhF65yCFZHY=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprgraphics", "repo": "hyprgraphics",
"rev": "0d77b4895ad5f1bb3b0ee43103a5246c58b65591", "rev": "fb2c0268645a77403af3b8a4ce8fa7ba5917f15d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -128,11 +128,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1737556638, "lastModified": 1728345020,
"narHash": "sha256-laKgI3mr2qz6tas/q3tuGPxMdsGhBi/w+HO+hO2f1AY=", "narHash": "sha256-xGbkc7U/Roe0/Cv3iKlzijIaFBNguasI31ynL2IlEoM=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprland-protocols", "repo": "hyprland-protocols",
"rev": "4c75dd5c015c8a0e5a34c6d02a018a650f57feb5", "rev": "a7c183800e74f337753de186522b9017a07a8cee",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -141,35 +141,8 @@
"type": "github" "type": "github"
} }
}, },
"hyprland-qt-support": {
"inputs": {
"hyprlang": "hyprlang",
"nixpkgs": [
"hyprland-qtutils",
"nixpkgs"
],
"systems": [
"hyprland-qtutils",
"systems"
]
},
"locked": {
"lastModified": 1737634706,
"narHash": "sha256-nGCibkfsXz7ARx5R+SnisRtMq21IQIhazp6viBU8I/A=",
"owner": "hyprwm",
"repo": "hyprland-qt-support",
"rev": "8810df502cdee755993cb803eba7b23f189db795",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprland-qt-support",
"type": "github"
}
},
"hyprland-qtutils": { "hyprland-qtutils": {
"inputs": { "inputs": {
"hyprland-qt-support": "hyprland-qt-support",
"hyprutils": [ "hyprutils": [
"hyprutils" "hyprutils"
], ],
@@ -181,11 +154,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1737811848, "lastModified": 1733940128,
"narHash": "sha256-WZ7LeiKHk5Y94MU5gHIWn0r8asWxYOvie4LqfCjVIZU=", "narHash": "sha256-hmfXWj2GA9cj1QUkPFYtAAeohhs615zL4E3APy3FnvQ=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprland-qtutils", "repo": "hyprland-qtutils",
"rev": "9c0831ff98856c0f312fcb8b57553fbe3dd34d5b", "rev": "3833097e50473a152dd614d4b468886840b4ea78",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -195,34 +168,6 @@
} }
}, },
"hyprlang": { "hyprlang": {
"inputs": {
"hyprutils": "hyprutils",
"nixpkgs": [
"hyprland-qtutils",
"hyprland-qt-support",
"nixpkgs"
],
"systems": [
"hyprland-qtutils",
"hyprland-qt-support",
"systems"
]
},
"locked": {
"lastModified": 1737634606,
"narHash": "sha256-W7W87Cv6wqZ9PHegI6rH1+ve3zJPiyevMFf0/HwdbCQ=",
"owner": "hyprwm",
"repo": "hyprlang",
"rev": "f41271d35cc0f370d300413d756c2677f386af9d",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprlang",
"type": "github"
}
},
"hyprlang_2": {
"inputs": { "inputs": {
"hyprutils": [ "hyprutils": [
"hyprutils" "hyprutils"
@@ -235,11 +180,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1737634606, "lastModified": 1734364628,
"narHash": "sha256-W7W87Cv6wqZ9PHegI6rH1+ve3zJPiyevMFf0/HwdbCQ=", "narHash": "sha256-ii8fzJfI953n/EmIxVvq64ZAwhvwuuPHWfGd61/mJG8=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprlang", "repo": "hyprlang",
"rev": "f41271d35cc0f370d300413d756c2677f386af9d", "rev": "16e59c1eb13d9fb6de066f54e7555eb5e8a4aba5",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -249,35 +194,6 @@
} }
}, },
"hyprutils": { "hyprutils": {
"inputs": {
"nixpkgs": [
"hyprland-qtutils",
"hyprland-qt-support",
"hyprlang",
"nixpkgs"
],
"systems": [
"hyprland-qtutils",
"hyprland-qt-support",
"hyprlang",
"systems"
]
},
"locked": {
"lastModified": 1737632363,
"narHash": "sha256-X9I8POSlHxBVjD0fiX1O2j7U9Zi1+4rIkrsyHP0uHXY=",
"owner": "hyprwm",
"repo": "hyprutils",
"rev": "006620eb29d54ea9086538891404c78563d1bae1",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprutils",
"type": "github"
}
},
"hyprutils_2": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
@@ -287,11 +203,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1737725508, "lastModified": 1733502241,
"narHash": "sha256-jGmcPc6y/prg/4A8KGYqJ27nSPaProCMiFadaxNAKvA=", "narHash": "sha256-KAUNC4Dgq8WQjYov5auBw/usaHixhacvb7cRDd0AG/k=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprutils", "repo": "hyprutils",
"rev": "fb0c2d1de3d1ef7396d19c18ac09e12bd956929e", "rev": "104117aed6dd68561be38b50f218190aa47f2cd8",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -310,11 +226,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1735493474, "lastModified": 1726874836,
"narHash": "sha256-fktzv4NaqKm94VAkAoVqO/nqQlw+X0/tJJNAeCSfzK4=", "narHash": "sha256-VKR0sf0PSNCB0wPHVKSAn41mCNVCnegWmgkrneKDhHM=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprwayland-scanner", "repo": "hyprwayland-scanner",
"rev": "de913476b59ee88685fdc018e77b8f6637a2ae0b", "rev": "500c81a9e1a76760371049a8d99e008ea77aa59e",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -325,11 +241,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1737632463, "lastModified": 1734119587,
"narHash": "sha256-38J9QfeGSej341ouwzqf77WIHAScihAKCt8PQJ+NH28=", "narHash": "sha256-AKU6qqskl0yf2+JdRdD0cfxX4b9x3KKV5RqA6wijmPM=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "0aa475546ed21629c4f5bbf90e38c846a99ec9e9", "rev": "3566ab7246670a43abd2ffa913cc62dad9cdf7d5",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -339,20 +255,37 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-stable": {
"locked": {
"lastModified": 1730741070,
"narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d063c1dd113c91ab27959ba540c0d9753409edf3",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"pre-commit-hooks": { "pre-commit-hooks": {
"inputs": { "inputs": {
"flake-compat": "flake-compat", "flake-compat": "flake-compat",
"gitignore": "gitignore", "gitignore": "gitignore",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
] ],
"nixpkgs-stable": "nixpkgs-stable"
}, },
"locked": { "locked": {
"lastModified": 1737465171, "lastModified": 1734279981,
"narHash": "sha256-R10v2hoJRLq8jcL4syVFag7nIGE7m13qO48wRIukWNg=", "narHash": "sha256-NdaCraHPp8iYMWzdXAt5Nv6sA3MUzlCiGiR586TCwo0=",
"owner": "cachix", "owner": "cachix",
"repo": "git-hooks.nix", "repo": "git-hooks.nix",
"rev": "9364dc02281ce2d37a1f55b6e51f7c0f65a75f17", "rev": "aa9f40c906904ebd83da78e7f328cd8aeaeae785",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -368,8 +301,8 @@
"hyprgraphics": "hyprgraphics", "hyprgraphics": "hyprgraphics",
"hyprland-protocols": "hyprland-protocols", "hyprland-protocols": "hyprland-protocols",
"hyprland-qtutils": "hyprland-qtutils", "hyprland-qtutils": "hyprland-qtutils",
"hyprlang": "hyprlang_2", "hyprlang": "hyprlang",
"hyprutils": "hyprutils_2", "hyprutils": "hyprutils",
"hyprwayland-scanner": "hyprwayland-scanner", "hyprwayland-scanner": "hyprwayland-scanner",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"pre-commit-hooks": "pre-commit-hooks", "pre-commit-hooks": "pre-commit-hooks",
@@ -414,11 +347,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1737634991, "lastModified": 1734124279,
"narHash": "sha256-dBAnb7Kbnier30cA7AgxVSxxARmxKZ1vHZT33THSIr8=", "narHash": "sha256-YNpFfiQjYt2o6LGcMN9NkjVvprC8ELrIpLHlbZbclRM=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "xdg-desktop-portal-hyprland", "repo": "xdg-desktop-portal-hyprland",
"rev": "e09dfe2726c8008f983e45a0aa1a3b7416aaeb8a", "rev": "0c6861f819f6d31f6195c9864709b2556f00b5cf",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@@ -11,23 +11,9 @@ set(CMAKE_CXX_STANDARD 23)
pkg_check_modules(hyprpm_deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.2.4) pkg_check_modules(hyprpm_deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.2.4)
find_package(glaze QUIET)
if (NOT glaze_FOUND)
set(GLAZE_VERSION v4.2.3)
message(STATUS "glaze dependency not found, retrieving ${GLAZE_VERSION} with FetchContent")
include(FetchContent)
FetchContent_Declare(
glaze
GIT_REPOSITORY https://github.com/stephenberry/glaze.git
GIT_TAG ${GLAZE_VERSION}
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(glaze)
endif()
add_executable(hyprpm ${SRCFILES}) add_executable(hyprpm ${SRCFILES})
target_link_libraries(hyprpm PUBLIC PkgConfig::hyprpm_deps glaze::glaze) target_link_libraries(hyprpm PUBLIC PkgConfig::hyprpm_deps)
# binary # binary
install(TARGETS hyprpm) install(TARGETS hyprpm)

View File

@@ -14,7 +14,7 @@ hyprpm [<FLAGS>]... <ARGUMENT>
| (list) "List all installed plugins" | (list) "List all installed plugins"
| (enable <PLUGINS>) "Load a plugin" | (enable <PLUGINS>) "Load a plugin"
| (disable <PLUGINS>) "Unload a plugin" | (disable <PLUGINS>) "Unload a plugin"
| (reload) "Reload plugins to match the enabled/disabled state. Use -f to force reload." | (reload) "Reload all plugins"
; ;
<PLUGINS> ::= {{{ hyprpm list | awk '/Plugin/{print $4}' }}}; <PLUGINS> ::= {{{ hyprpm list | awk '/Plugin/{print $4}' }}};

View File

@@ -1,10 +1,11 @@
#include "DataState.hpp" #include "DataState.hpp"
#include <toml++/toml.hpp> #include <toml++/toml.hpp>
#include <print> #include <print>
#include <filesystem>
#include <fstream> #include <fstream>
#include "PluginManager.hpp" #include "PluginManager.hpp"
std::filesystem::path DataState::getDataStatePath() { std::string DataState::getDataStatePath() {
const auto HOME = getenv("HOME"); const auto HOME = getenv("HOME");
if (!HOME) { if (!HOME) {
std::println(stderr, "DataState: no $HOME"); std::println(stderr, "DataState: no $HOME");
@@ -15,29 +16,12 @@ std::filesystem::path DataState::getDataStatePath() {
const auto XDG_DATA_HOME = getenv("XDG_DATA_HOME"); const auto XDG_DATA_HOME = getenv("XDG_DATA_HOME");
if (XDG_DATA_HOME) if (XDG_DATA_HOME)
return std::filesystem::path{XDG_DATA_HOME} / "hyprpm"; return std::string{XDG_DATA_HOME} + "/hyprpm";
return std::filesystem::path{HOME} / ".local/share/hyprpm"; return std::string{HOME} + "/.local/share/hyprpm";
} }
std::string DataState::getHeadersPath() { std::string DataState::getHeadersPath() {
return getDataStatePath() / "headersRoot"; return getDataStatePath() + "/headersRoot";
}
std::vector<std::filesystem::path> DataState::getPluginStates() {
ensureStateStoreExists();
std::vector<std::filesystem::path> states;
for (const auto& entry : std::filesystem::directory_iterator(getDataStatePath())) {
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
continue;
const auto stateFile = entry.path() / "state.toml";
if (!std::filesystem::exists(stateFile))
continue;
states.emplace_back(stateFile);
}
return states;
} }
void DataState::ensureStateStoreExists() { void DataState::ensureStateStoreExists() {
@@ -53,7 +37,7 @@ void DataState::ensureStateStoreExists() {
void DataState::addNewPluginRepo(const SPluginRepository& repo) { void DataState::addNewPluginRepo(const SPluginRepository& repo) {
ensureStateStoreExists(); ensureStateStoreExists();
const auto PATH = getDataStatePath() / repo.name; const auto PATH = getDataStatePath() + "/" + repo.name;
std::filesystem::create_directories(PATH); std::filesystem::create_directories(PATH);
// clang-format off // clang-format off
@@ -66,21 +50,19 @@ void DataState::addNewPluginRepo(const SPluginRepository& repo) {
}} }}
}; };
for (auto const& p : repo.plugins) { for (auto const& p : repo.plugins) {
const auto filename = p.name + ".so";
// copy .so to the good place // copy .so to the good place
if (std::filesystem::exists(p.filename)) if (std::filesystem::exists(p.filename))
std::filesystem::copy_file(p.filename, PATH / filename); std::filesystem::copy_file(p.filename, PATH + "/" + p.name + ".so");
DATA.emplace(p.name, toml::table{ DATA.emplace(p.name, toml::table{
{"filename", filename}, {"filename", p.name + ".so"},
{"enabled", p.enabled}, {"enabled", p.enabled},
{"failed", p.failed} {"failed", p.failed}
}); });
} }
// clang-format on // clang-format on
std::ofstream ofs(PATH / "state.toml", std::ios::trunc); std::ofstream ofs(PATH + "/state.toml", std::ios::trunc);
ofs << DATA; ofs << DATA;
ofs.close(); ofs.close();
} }
@@ -90,10 +72,17 @@ bool DataState::pluginRepoExists(const std::string& urlOrName) {
const auto PATH = getDataStatePath(); const auto PATH = getDataStatePath();
for (const auto& stateFile : getPluginStates()) { for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
const auto STATE = toml::parse_file(stateFile.c_str()); if (!entry.is_directory() || entry.path().stem() == "headersRoot")
const auto NAME = STATE["repository"]["name"].value_or(""); continue;
const auto URL = STATE["repository"]["url"].value_or("");
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
continue;
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
const auto NAME = STATE["repository"]["name"].value_or("");
const auto URL = STATE["repository"]["url"].value_or("");
if (URL == urlOrName || NAME == urlOrName) if (URL == urlOrName || NAME == urlOrName)
return true; return true;
@@ -107,22 +96,29 @@ void DataState::removePluginRepo(const std::string& urlOrName) {
const auto PATH = getDataStatePath(); const auto PATH = getDataStatePath();
for (const auto& stateFile : getPluginStates()) { for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
const auto STATE = toml::parse_file(stateFile.c_str()); if (!entry.is_directory() || entry.path().stem() == "headersRoot")
const auto NAME = STATE["repository"]["name"].value_or(""); continue;
const auto URL = STATE["repository"]["url"].value_or("");
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
continue;
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
const auto NAME = STATE["repository"]["name"].value_or("");
const auto URL = STATE["repository"]["url"].value_or("");
if (URL == urlOrName || NAME == urlOrName) { if (URL == urlOrName || NAME == urlOrName) {
// unload the plugins!! // unload the plugins!!
for (const auto& file : std::filesystem::directory_iterator(stateFile.parent_path())) { for (const auto& file : std::filesystem::directory_iterator(entry.path())) {
if (!file.path().string().ends_with(".so")) if (!file.path().string().ends_with(".so"))
continue; continue;
g_pPluginManager->loadUnloadPlugin(std::filesystem::absolute(file.path()), false); g_pPluginManager->loadUnloadPlugin(std::filesystem::absolute(file.path()), false);
} }
std::filesystem::remove_all(stateFile.parent_path()); std::filesystem::remove_all(entry.path());
return; return;
} }
} }
@@ -143,7 +139,7 @@ void DataState::updateGlobalState(const SGlobalState& state) {
}; };
// clang-format on // clang-format on
std::ofstream ofs(PATH / "state.toml", std::ios::trunc); std::ofstream ofs(PATH + "/state.toml", std::ios::trunc);
ofs << DATA; ofs << DATA;
ofs.close(); ofs.close();
} }
@@ -151,12 +147,12 @@ void DataState::updateGlobalState(const SGlobalState& state) {
SGlobalState DataState::getGlobalState() { SGlobalState DataState::getGlobalState() {
ensureStateStoreExists(); ensureStateStoreExists();
const auto stateFile = getDataStatePath() / "state.toml"; const auto PATH = getDataStatePath();
if (!std::filesystem::exists(stateFile)) if (!std::filesystem::exists(PATH + "/state.toml"))
return SGlobalState{}; return SGlobalState{};
auto DATA = toml::parse_file(stateFile.c_str()); auto DATA = toml::parse_file(PATH + "/state.toml");
SGlobalState state; SGlobalState state;
state.headersHashCompiled = DATA["state"]["hash"].value_or(""); state.headersHashCompiled = DATA["state"]["hash"].value_or("");
@@ -171,8 +167,15 @@ std::vector<SPluginRepository> DataState::getAllRepositories() {
const auto PATH = getDataStatePath(); const auto PATH = getDataStatePath();
std::vector<SPluginRepository> repos; std::vector<SPluginRepository> repos;
for (const auto& stateFile : getPluginStates()) {
const auto STATE = toml::parse_file(stateFile.c_str()); for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
if (!entry.is_directory() || entry.path().stem() == "headersRoot")
continue;
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
continue;
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
const auto NAME = STATE["repository"]["name"].value_or(""); const auto NAME = STATE["repository"]["name"].value_or("");
const auto URL = STATE["repository"]["url"].value_or(""); const auto URL = STATE["repository"]["url"].value_or("");
@@ -207,8 +210,15 @@ bool DataState::setPluginEnabled(const std::string& name, bool enabled) {
const auto PATH = getDataStatePath(); const auto PATH = getDataStatePath();
for (const auto& stateFile : getPluginStates()) { for (const auto& entry : std::filesystem::directory_iterator(PATH)) {
const auto STATE = toml::parse_file(stateFile.c_str()); if (!entry.is_directory() || entry.path().stem() == "headersRoot")
continue;
if (!std::filesystem::exists(entry.path().string() + "/state.toml"))
continue;
auto STATE = toml::parse_file(entry.path().string() + "/state.toml");
for (const auto& [key, val] : STATE) { for (const auto& [key, val] : STATE) {
if (key == "repository") if (key == "repository")
continue; continue;
@@ -221,11 +231,10 @@ bool DataState::setPluginEnabled(const std::string& name, bool enabled) {
if (FAILED) if (FAILED)
return false; return false;
auto modifiedState = STATE; (*STATE[key].as_table()).insert_or_assign("enabled", enabled);
(*modifiedState[key].as_table()).insert_or_assign("enabled", enabled);
std::ofstream state(stateFile, std::ios::trunc); std::ofstream state(entry.path().string() + "/state.toml", std::ios::trunc);
state << modifiedState; state << STATE;
state.close(); state.close();
return true; return true;

View File

@@ -1,5 +1,4 @@
#pragma once #pragma once
#include <filesystem>
#include <string> #include <string>
#include <vector> #include <vector>
#include "Plugin.hpp" #include "Plugin.hpp"
@@ -10,15 +9,14 @@ struct SGlobalState {
}; };
namespace DataState { namespace DataState {
std::filesystem::path getDataStatePath(); std::string getDataStatePath();
std::string getHeadersPath(); std::string getHeadersPath();
std::vector<std::filesystem::path> getPluginStates(); void ensureStateStoreExists();
void ensureStateStoreExists(); void addNewPluginRepo(const SPluginRepository& repo);
void addNewPluginRepo(const SPluginRepository& repo); void removePluginRepo(const std::string& urlOrName);
void removePluginRepo(const std::string& urlOrName); bool pluginRepoExists(const std::string& urlOrName);
bool pluginRepoExists(const std::string& urlOrName); void updateGlobalState(const SGlobalState& state);
void updateGlobalState(const SGlobalState& state); SGlobalState getGlobalState();
SGlobalState getGlobalState(); bool setPluginEnabled(const std::string& name, bool enabled);
bool setPluginEnabled(const std::string& name, bool enabled); std::vector<SPluginRepository> getAllRepositories();
std::vector<SPluginRepository> getAllRepositories();
}; };

View File

@@ -7,8 +7,10 @@
#include <cstdio> #include <cstdio>
#include <iostream> #include <iostream>
#include <array>
#include <filesystem> #include <filesystem>
#include <print> #include <print>
#include <thread>
#include <fstream> #include <fstream>
#include <algorithm> #include <algorithm>
#include <format> #include <format>
@@ -19,7 +21,6 @@
#include <unistd.h> #include <unistd.h>
#include <toml++/toml.hpp> #include <toml++/toml.hpp>
#include <glaze/glaze.hpp>
#include <hyprutils/string/String.hpp> #include <hyprutils/string/String.hpp>
#include <hyprutils/os/Process.hpp> #include <hyprutils/os/Process.hpp>
@@ -82,13 +83,13 @@ SHyprlandVersion CPluginManager::getHyprlandVersion(bool running) {
hlbranch = hlbranch.substr(0, hlbranch.find(" at commit ")); hlbranch = hlbranch.substr(0, hlbranch.find(" at commit "));
std::string hldate = HLVERCALL.substr(HLVERCALL.find("Date: ") + 6); std::string hldate = HLVERCALL.substr(HLVERCALL.find("Date: ") + 6);
hldate = hldate.substr(0, hldate.find('\n')); hldate = hldate.substr(0, hldate.find("\n"));
std::string hlcommits; std::string hlcommits;
if (HLVERCALL.contains("commits:")) { if (HLVERCALL.contains("commits:")) {
hlcommits = HLVERCALL.substr(HLVERCALL.find("commits:") + 9); hlcommits = HLVERCALL.substr(HLVERCALL.find("commits:") + 9);
hlcommits = hlcommits.substr(0, hlcommits.find(' ')); hlcommits = hlcommits.substr(0, hlcommits.find(" "));
} }
int commits = 0; int commits = 0;
@@ -377,7 +378,7 @@ eHeadersErrors CPluginManager::headersValid() {
// find headers commit // find headers commit
const std::string& cmd = std::format("PKG_CONFIG_PATH=\"{}/share/pkgconfig\" pkgconf --cflags --keep-system-cflags hyprland", DataState::getHeadersPath()); const std::string& cmd = std::format("PKG_CONFIG_PATH=\"{}/share/pkgconfig\" pkgconf --cflags --keep-system-cflags hyprland", DataState::getHeadersPath());
auto headers = execAndGet(cmd); auto headers = execAndGet(cmd.c_str());
if (!headers.contains("-I/")) if (!headers.contains("-I/"))
return HEADERS_MISSING; return HEADERS_MISSING;
@@ -780,7 +781,7 @@ bool CPluginManager::disablePlugin(const std::string& name) {
return ret; return ret;
} }
ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState(bool forceReload) { ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() {
if (headersValid() != HEADERS_OK) { if (headersValid() != HEADERS_OK) {
std::println(stderr, "\n{}", failureString("headers are not up-to-date, please run hyprpm update.")); std::println(stderr, "\n{}", failureString("headers are not up-to-date, please run hyprpm update."));
return LOADSTATE_HEADERS_OUTDATED; return LOADSTATE_HEADERS_OUTDATED;
@@ -789,28 +790,35 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState(bool forceReload)
const auto HOME = getenv("HOME"); const auto HOME = getenv("HOME");
const auto HIS = getenv("HYPRLAND_INSTANCE_SIGNATURE"); const auto HIS = getenv("HYPRLAND_INSTANCE_SIGNATURE");
if (!HOME || !HIS) { if (!HOME || !HIS) {
std::println(stderr, "PluginManager: no $HOME or $HYPRLAND_INSTANCE_SIGNATURE"); std::println(stderr, "PluginManager: no $HOME or HIS");
return LOADSTATE_FAIL; return LOADSTATE_FAIL;
} }
const auto HYPRPMPATH = DataState::getDataStatePath(); const auto HYPRPMPATH = DataState::getDataStatePath() + "/";
const auto json = glz::read_json<glz::json_t::array_t>(execAndGet("hyprctl plugins list -j")); auto pluginLines = execAndGet("hyprctl plugins list | grep Plugin");
if (!json) {
std::println(stderr, "PluginManager: couldn't parse hyprctl output");
return LOADSTATE_FAIL;
}
std::vector<std::string> loadedPlugins; std::vector<std::string> loadedPlugins;
for (const auto& plugin : json.value()) {
if (!plugin.is_object() || !plugin.contains("name")) {
std::println(stderr, "PluginManager: couldn't parse plugin object");
return LOADSTATE_FAIL;
}
loadedPlugins.emplace_back(plugin["name"].get<std::string>());
}
std::println("{}", successString("Ensuring plugin load state")); std::println("{}", successString("Ensuring plugin load state"));
// iterate line by line
while (!pluginLines.empty()) {
auto plLine = pluginLines.substr(0, pluginLines.find('\n'));
if (pluginLines.find('\n') != std::string::npos)
pluginLines = pluginLines.substr(pluginLines.find('\n') + 1);
else
pluginLines = "";
if (plLine.back() != ':')
continue;
plLine = plLine.substr(7);
plLine = plLine.substr(0, plLine.find(" by "));
loadedPlugins.push_back(plLine);
}
// get state // get state
const auto REPOS = DataState::getAllRepositories(); const auto REPOS = DataState::getAllRepositories();
@@ -841,11 +849,11 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState(bool forceReload)
// (and Hyprland needs to restart) // (and Hyprland needs to restart)
bool hyprlandVersionMismatch = false; bool hyprlandVersionMismatch = false;
// unload disabled plugins (or all if forceReload is true) // unload disabled plugins
for (auto const& p : loadedPlugins) { for (auto const& p : loadedPlugins) {
if (forceReload || !enabled(p)) { if (!enabled(p)) {
// unload // unload
if (!loadUnloadPlugin(HYPRPMPATH / repoForName(p) / (p + ".so"), false)) { if (!loadUnloadPlugin(HYPRPMPATH + repoForName(p) + "/" + p + ".so", false)) {
std::println("{}", infoString("{} will be unloaded after restarting Hyprland", p)); std::println("{}", infoString("{} will be unloaded after restarting Hyprland", p));
hyprlandVersionMismatch = true; hyprlandVersionMismatch = true;
} else } else
@@ -859,10 +867,10 @@ ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState(bool forceReload)
if (!p.enabled) if (!p.enabled)
continue; continue;
if (!forceReload && std::find_if(loadedPlugins.begin(), loadedPlugins.end(), [&](const auto& other) { return other == p.name; }) != loadedPlugins.end()) if (std::find_if(loadedPlugins.begin(), loadedPlugins.end(), [&](const auto& other) { return other == p.name; }) != loadedPlugins.end())
continue; continue;
if (!loadUnloadPlugin(HYPRPMPATH / repoForName(p.name) / p.filename, true)) { if (!loadUnloadPlugin(HYPRPMPATH + repoForName(p.name) + "/" + p.filename, true)) {
std::println("{}", infoString("{} will be loaded after restarting Hyprland", p.name)); std::println("{}", infoString("{} will be loaded after restarting Hyprland", p.name));
hyprlandVersionMismatch = true; hyprlandVersionMismatch = true;
} else } else

View File

@@ -51,7 +51,7 @@ class CPluginManager {
bool enablePlugin(const std::string& name); bool enablePlugin(const std::string& name);
bool disablePlugin(const std::string& name); bool disablePlugin(const std::string& name);
ePluginLoadStateReturn ensurePluginsLoadState(bool forceReload = false); ePluginLoadStateReturn ensurePluginsLoadState();
bool loadUnloadPlugin(const std::string& path, bool load); bool loadUnloadPlugin(const std::string& path, bool load);
SHyprlandVersion getHyprlandVersion(bool running = true); SHyprlandVersion getHyprlandVersion(bool running = true);

View File

@@ -154,7 +154,7 @@ int main(int argc, char** argv, char** envp) {
if (ret != LOADSTATE_OK) if (ret != LOADSTATE_OK)
return 1; return 1;
} else if (command[0] == "reload") { } else if (command[0] == "reload") {
auto ret = g_pPluginManager->ensurePluginsLoadState(force); auto ret = g_pPluginManager->ensurePluginsLoadState();
if (ret != LOADSTATE_OK && notify) { if (ret != LOADSTATE_OK && notify) {
switch (ret) { switch (ret) {

View File

@@ -8,7 +8,6 @@ executable(
dependency('hyprutils', version: '>= 0.1.1'), dependency('hyprutils', version: '>= 0.1.1'),
dependency('threads'), dependency('threads'),
dependency('tomlplusplus'), dependency('tomlplusplus'),
dependency('glaze', method: 'cmake'),
], ],
install: true, install: true,
) )

View File

@@ -58,7 +58,6 @@ endif
backtrace_dep = cpp_compiler.find_library('execinfo', required: false) backtrace_dep = cpp_compiler.find_library('execinfo', required: false)
epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs epoll_dep = dependency('epoll-shim', required: false) # timerfd on BSDs
inotify_dep = dependency('libinotify', required: false) # inotify on BSDs
re2 = dependency('re2', required: true) re2 = dependency('re2', required: true)
@@ -102,14 +101,11 @@ endif
subdir('protocols') subdir('protocols')
subdir('src') subdir('src')
subdir('hyprctl') subdir('hyprctl')
subdir('hyprpm/src')
subdir('assets') subdir('assets')
subdir('example') subdir('example')
subdir('docs') subdir('docs')
if get_option('hyprpm').enabled()
subdir('hyprpm/src')
endif
# Generate hyprland.pc # Generate hyprland.pc
pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig') pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig')

View File

@@ -2,5 +2,4 @@ option('xwayland', type: 'feature', value: 'auto', description: 'Enable support
option('systemd', type: 'feature', value: 'auto', description: 'Enable systemd integration') option('systemd', type: 'feature', value: 'auto', description: 'Enable systemd integration')
option('uwsm', type: 'feature', value: 'enabled', description: 'Enable uwsm integration (only if systemd is enabled)') option('uwsm', type: 'feature', value: 'enabled', description: 'Enable uwsm integration (only if systemd is enabled)')
option('legacy_renderer', type: 'feature', value: 'disabled', description: 'Enable legacy renderer') option('legacy_renderer', type: 'feature', value: 'disabled', description: 'Enable legacy renderer')
option('hyprpm', type: 'feature', value: 'enabled', description: 'Enable hyprpm')
option('tracy_enable', type: 'boolean', value: false , description: 'Enable profiling') option('tracy_enable', type: 'boolean', value: false , description: 'Enable profiling')

View File

@@ -5,14 +5,12 @@
pkg-config, pkg-config,
pkgconf, pkgconf,
makeWrapper, makeWrapper,
cmake,
meson, meson,
ninja, ninja,
aquamarine, aquamarine,
binutils, binutils,
cairo, cairo,
git, git,
glaze,
hyprcursor, hyprcursor,
hyprgraphics, hyprgraphics,
hyprland-protocols, hyprland-protocols,
@@ -52,12 +50,12 @@
nvidiaPatches ? false, nvidiaPatches ? false,
hidpiXWayland ? false, hidpiXWayland ? false,
}: let }: let
inherit (builtins) baseNameOf foldl' readFile; inherit (builtins) baseNameOf foldl';
inherit (lib.asserts) assertMsg; inherit (lib.asserts) assertMsg;
inherit (lib.attrsets) mapAttrsToList; inherit (lib.attrsets) mapAttrsToList;
inherit (lib.lists) flatten concatLists optional optionals; inherit (lib.lists) flatten concatLists optional optionals;
inherit (lib.sources) cleanSourceWith cleanSource; inherit (lib.sources) cleanSourceWith cleanSource;
inherit (lib.strings) hasSuffix makeBinPath optionalString mesonBool mesonEnable trim; inherit (lib.strings) hasSuffix makeBinPath optionalString mesonBool mesonEnable;
adapters = flatten [ adapters = flatten [
stdenvAdapters.useMoldLinker stdenvAdapters.useMoldLinker
@@ -93,7 +91,7 @@ in
DATE = date; DATE = date;
DIRTY = optionalString (commit == "") "dirty"; DIRTY = optionalString (commit == "") "dirty";
HASH = commit; HASH = commit;
TAG = "v${trim (readFile "${finalAttrs.src}/VERSION")}"; TAG = "v${builtins.readFile "${finalAttrs.src}/VERSION"}";
depsBuildBuild = [ depsBuildBuild = [
pkg-config pkg-config
@@ -104,7 +102,6 @@ in
makeWrapper makeWrapper
meson meson
ninja ninja
cmake # needed for glaze
pkg-config pkg-config
]; ];
@@ -119,7 +116,6 @@ in
aquamarine aquamarine
cairo cairo
git git
glaze
hyprcursor hyprcursor
hyprgraphics hyprgraphics
hyprland-protocols hyprland-protocols
@@ -163,7 +159,6 @@ in
"xwayland" = enableXWayland; "xwayland" = enableXWayland;
"legacy_renderer" = legacyRenderer; "legacy_renderer" = legacyRenderer;
"uwsm" = false; "uwsm" = false;
"hyprpm" = false;
}) })
(mapAttrsToList mesonBool { (mapAttrsToList mesonBool {
"b_pch" = false; "b_pch" = false;

View File

@@ -7,206 +7,15 @@ inputs: {
inherit (pkgs.stdenv.hostPlatform) system; inherit (pkgs.stdenv.hostPlatform) system;
cfg = config.programs.hyprland; cfg = config.programs.hyprland;
# basically 1:1 taken from https://github.com/nix-community/home-manager/blob/master/modules/services/window-managers/hyprland.nix package = inputs.self.packages.${system}.hyprland;
toHyprconf = { portalPackage = inputs.self.packages.${system}.xdg-desktop-portal-hyprland.override {
attrs, hyprland = cfg.finalPackage;
indentLevel ? 0, };
importantPrefixes ? ["$"],
}: let
inherit
(lib)
all
concatMapStringsSep
concatStrings
concatStringsSep
filterAttrs
foldl
generators
hasPrefix
isAttrs
isList
mapAttrsToList
replicate
;
initialIndent = concatStrings (replicate indentLevel " ");
toHyprconf' = indent: attrs: let
sections =
filterAttrs (n: v: isAttrs v || (isList v && all isAttrs v)) attrs;
mkSection = n: attrs:
if lib.isList attrs
then (concatMapStringsSep "\n" (a: mkSection n a) attrs)
else ''
${indent}${n} {
${toHyprconf' " ${indent}" attrs}${indent}}
'';
mkFields = generators.toKeyValue {
listsAsDuplicateKeys = true;
inherit indent;
};
allFields =
filterAttrs (n: v: !(isAttrs v || (isList v && all isAttrs v)))
attrs;
isImportantField = n: _:
foldl (acc: prev:
if hasPrefix prev n
then true
else acc)
false
importantPrefixes;
importantFields = filterAttrs isImportantField allFields;
fields =
builtins.removeAttrs allFields
(mapAttrsToList (n: _: n) importantFields);
in
mkFields importantFields
+ concatStringsSep "\n" (mapAttrsToList mkSection sections)
+ mkFields fields;
in
toHyprconf' initialIndent attrs;
in { in {
options = { config = {
programs.hyprland = { programs.hyprland = {
plugins = lib.mkOption { package = lib.mkDefault package;
type = with lib.types; listOf (either package path); portalPackage = lib.mkDefault portalPackage;
default = [];
description = ''
List of Hyprland plugins to use. Can either be packages or
absolute plugin paths.
'';
};
settings = lib.mkOption {
type = with lib.types; let
valueType =
nullOr (oneOf [
bool
int
float
str
path
(attrsOf valueType)
(listOf valueType)
])
// {
description = "Hyprland configuration value";
};
in
valueType;
default = {};
description = ''
Hyprland configuration written in Nix. Entries with the same key
should be written as lists. Variables' and colors' names should be
quoted. See <https://wiki.hyprland.org> for more examples.
::: {.note}
Use the [](#programs.hyprland.plugins) option to
declare plugins.
:::
'';
example = lib.literalExpression ''
{
decoration = {
shadow_offset = "0 5";
"col.shadow" = "rgba(00000099)";
};
"$mod" = "SUPER";
bindm = [
# mouse movements
"$mod, mouse:272, movewindow"
"$mod, mouse:273, resizewindow"
"$mod ALT, mouse:272, resizewindow"
];
}
'';
};
extraConfig = lib.mkOption {
type = lib.types.lines;
default = "";
example = ''
# window resize
bind = $mod, S, submap, resize
submap = resize
binde = , right, resizeactive, 10 0
binde = , left, resizeactive, -10 0
binde = , up, resizeactive, 0 -10
binde = , down, resizeactive, 0 10
bind = , escape, submap, reset
submap = reset
'';
description = ''
Extra configuration lines to add to `/etc/xdg/hypr/hyprland.conf`.
'';
};
sourceFirst =
lib.mkEnableOption ''
putting source entries at the top of the configuration
''
// {
default = true;
};
importantPrefixes = lib.mkOption {
type = with lib.types; listOf str;
default = ["$" "bezier" "name"] ++ lib.optionals cfg.sourceFirst ["source"];
example = ["$" "bezier"];
description = ''
List of prefix of attributes to source at the top of the config.
'';
};
}; };
}; };
config = lib.mkMerge [
{
programs.hyprland = {
package = lib.mkDefault inputs.self.packages.${system}.hyprland;
portalPackage = lib.mkDefault (inputs.self.packages.${system}.xdg-desktop-portal-hyprland.override {
hyprland = cfg.finalPackage;
});
};
}
(lib.mkIf cfg.enable {
environment.etc."xdg/hypr/hyprland.conf" = let
shouldGenerate = cfg.extraConfig != "" || cfg.settings != {} || cfg.plugins != [];
pluginsToHyprconf = plugins:
toHyprconf {
attrs = {
plugin = let
mkEntry = entry:
if lib.types.package.check entry
then "${entry}/lib/lib${entry.pname}.so"
else entry;
in
map mkEntry cfg.plugins;
};
inherit (cfg) importantPrefixes;
};
in
lib.mkIf shouldGenerate {
text =
lib.optionalString (cfg.plugins != [])
(pluginsToHyprconf cfg.plugins)
+ lib.optionalString (cfg.settings != {})
(toHyprconf {
attrs = cfg.settings;
inherit (cfg) importantPrefixes;
})
+ lib.optionalString (cfg.extraConfig != "") cfg.extraConfig;
};
})
];
} }

View File

@@ -1,366 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="frog_color_management_v1">
<copyright>
Copyright © 2023 Joshua Ashton for Valve Software
Copyright © 2023 Xaver Hugl
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
</copyright>
<description summary="experimental color management protocol">
The aim of this color management extension is to get HDR games working quickly,
and have an easy way to test implementations in the wild before the upstream
protocol is ready to be merged.
For that purpose it's intentionally limited and cut down and does not serve
all uses cases.
</description>
<interface name="frog_color_management_factory_v1" version="1">
<description summary="color management factory">
The color management factory singleton creates color managed surface objects.
</description>
<request name="destroy" type="destructor"></request>
<request name="get_color_managed_surface">
<description summary="create color management interface for surface">
</description>
<arg name="surface" type="object" interface="wl_surface"
summary="target surface" />
<arg name="callback" type="new_id" interface="frog_color_managed_surface"
summary="new color managed surface object" />
</request>
</interface>
<interface name="frog_color_managed_surface" version="1">
<description summary="color managed surface">
Interface for changing surface color management and HDR state.
An implementation must: support every part of the version
of the frog_color_managed_surface interface it exposes.
Including all known enums associated with a given version.
</description>
<request name="destroy" type="destructor">
<description summary="destroy color managed surface">
Destroying the color managed surface resets all known color
state for the surface back to 'undefined' implementation-specific
values.
</description>
</request>
<enum name="transfer_function">
<description summary="known transfer functions">
Extended information on the transfer functions described
here can be found in the Khronos Data Format specification:
https://registry.khronos.org/DataFormat/specs/1.3/dataformat.1.3.html
</description>
<entry name="undefined" value="0"
summary="specifies undefined, implementation-specific handling of the surface's transfer function." />
<entry name="srgb" value="1"
summary="specifies the sRGB non-linear EOTF. An implementation may: display this as Gamma 2.2 for the purposes of being consistent with content rendering across displays, rendering_intent and user expectations." />
<entry name="gamma_22" value="2" summary="specifies gamma 2.2 power curve as the EOTF" />
<entry name="st2084_pq" value="3"
summary="specifies the SMPTE ST2084 Perceptual Quantizer (PQ) EOTF" />
<entry name="scrgb_linear" value="4"
summary="specifies the scRGB (extended sRGB) linear EOTF. Note: Primaries outside the gamut triangle specified can be expressed with negative values for this transfer function." />
</enum>
<request name="set_known_transfer_function">
<description summary="sets a known transfer function for a surface" />
<arg name="transfer_function" type="uint" enum="transfer_function"
summary="transfer function for the surface" />
</request>
<enum name="primaries">
<description summary="known primaries" />
<entry name="undefined" value="0"
summary="specifies undefined, implementation-specific handling" />
<entry name="rec709" value="1" summary="specifies Rec.709/sRGB primaries with D65 white point" />
<entry name="rec2020" value="2"
summary="specifies Rec.2020/HDR10 primaries with D65 white point" />
</enum>
<request name="set_known_container_color_volume">
<description summary="sets the container color volume (primaries) for a surface" />
<arg name="primaries" type="uint" enum="primaries" summary="primaries for the surface" />
</request>
<enum name="render_intent">
<description summary="known render intents">
Extended information on render intents described
here can be found in ICC.1:2022:
https://www.color.org/specification/ICC.1-2022-05.pdf
</description>
<entry name="perceptual" value="0" summary="perceptual" />
</enum>
<request name="set_render_intent">
<description summary="sets the render intent for a surface">
NOTE: On a surface with "perceptual" (default) render intent, handling of the container's
color volume
is implementation-specific, and may differ between different transfer functions it is paired
with:
ie. sRGB + 709 rendering may have it's primaries widened to more of the available display's
gamut
to be be more pleasing for the viewer.
Compared to scRGB Linear + 709 being treated faithfully as 709
(including utilizing negatives out of the 709 gamut triangle)
</description>
<arg name="render_intent" type="uint" enum="render_intent"
summary="render intent for the surface" />
</request>
<request name="set_hdr_metadata">
<description summary="set HDR metadata for a surface">
Forwards HDR metadata from the client to the compositor.
HDR Metadata Infoframe as per CTA 861.G spec.
Usage of this HDR metadata is implementation specific and
outside of the scope of this protocol.
</description>
<arg name="mastering_display_primary_red_x" type="uint">
<description summary="red primary x coordinate">
Mastering Red Color Primary X Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="mastering_display_primary_red_y" type="uint">
<description summary="red primary y coordinate">
Mastering Red Color Primary Y Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="mastering_display_primary_green_x" type="uint">
<description summary="green primary x coordinate">
Mastering Green Color Primary X Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="mastering_display_primary_green_y" type="uint">
<description summary="green primary y coordinate">
Mastering Green Color Primary Y Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="mastering_display_primary_blue_x" type="uint">
<description summary="blue primary x coordinate">
Mastering Blue Color Primary X Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="mastering_display_primary_blue_y" type="uint">
<description summary="blue primary y coordinate">
Mastering Blue Color Primary Y Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="mastering_white_point_x" type="uint">
<description summary="white point x coordinate">
Mastering White Point X Coordinate of the Data.
These are coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="mastering_white_point_y" type="uint">
<description summary="white point y coordinate">
Mastering White Point Y Coordinate of the Data.
These are coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="max_display_mastering_luminance" type="uint">
<description summary="max display mastering luminance">
Max Mastering Display Luminance.
This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
</description>
</arg>
<arg name="min_display_mastering_luminance" type="uint">
<description summary="min display mastering luminance">
Min Mastering Display Luminance.
This value is coded as an unsigned 16-bit value in units of
0.0001 cd/m2, where 0x0001 represents 0.0001 cd/m2 and 0xFFFF
represents 6.5535 cd/m2.
</description>
</arg>
<arg name="max_cll" type="uint">
<description summary="max content light level">
Max Content Light Level.
This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
</description>
</arg>
<arg name="max_fall" type="uint">
<description summary="max frame average light level">
Max Frame Average Light Level.
This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
</description>
</arg>
</request>
<event name="preferred_metadata">
<description summary="preferred metadata for a surface">
Current preferred metadata for a surface.
The application should use this information to tone-map its buffers
to this target before committing.
This metadata does not necessarily correspond to any physical output, but
rather what the compositor thinks would be best for a given surface.
</description>
<arg name="transfer_function" type="uint" enum="transfer_function">
<description summary="output's current transfer function">
Specifies a known transfer function that corresponds to the
output the surface is targeting.
</description>
</arg>
<arg name="output_display_primary_red_x" type="uint">
<description summary="red primary x coordinate">
Output Red Color Primary X Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="output_display_primary_red_y" type="uint">
<description summary="red primary y coordinate">
Output Red Color Primary Y Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="output_display_primary_green_x" type="uint">
<description summary="green primary x coordinate">
Output Green Color Primary X Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="output_display_primary_green_y" type="uint">
<description summary="green primary y coordinate">
Output Green Color Primary Y Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="output_display_primary_blue_x" type="uint">
<description summary="blue primary x coordinate">
Output Blue Color Primary X Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="output_display_primary_blue_y" type="uint">
<description summary="blue primary y coordinate">
Output Blue Color Primary Y Coordinate of the Data.
Coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="output_white_point_x" type="uint">
<description summary="white point x coordinate">
Output White Point X Coordinate of the Data.
These are coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="output_white_point_y" type="uint">
<description summary="white point y coordinate">
Output White Point Y Coordinate of the Data.
These are coded as unsigned 16-bit values in units of
0.00002, where 0x0000 represents zero and 0xC350
represents 1.0000.
</description>
</arg>
<arg name="max_luminance" type="uint">
<description summary="maximum luminance">
Max Output Luminance
The max luminance in nits that the output is capable of rendering in small areas.
Content should: not exceed this value to avoid clipping.
This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
</description>
</arg>
<arg name="min_luminance" type="uint">
<description summary="minimum luminance">
Min Output Luminance
The min luminance that the output is capable of rendering.
Content should: not exceed this value to avoid clipping.
This value is coded as an unsigned 16-bit value in units of
0.0001 cd/m2, where 0x0001 represents 0.0001 cd/m2 and 0xFFFF
represents 6.5535 cd/m2.
</description>
</arg>
<arg name="max_full_frame_luminance" type="uint">
<description summary="maximum full frame luminance">
Max Full Frame Luminance
The max luminance in nits that the output is capable of rendering for the
full frame sustained.
This value is coded as an unsigned 16-bit value in units of 1 cd/m2,
where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2.
</description>
</arg>
</event>
</interface>
</protocol>

View File

@@ -7,7 +7,7 @@ wayland_protos = dependency(
hyprland_protos = dependency( hyprland_protos = dependency(
'hyprland-protocols', 'hyprland-protocols',
version: '>=0.6', version: '>=0.4',
fallback: 'hyprland-protocols', fallback: 'hyprland-protocols',
) )
@@ -33,14 +33,10 @@ protocols = [
'wayland-drm.xml', 'wayland-drm.xml',
'wlr-data-control-unstable-v1.xml', 'wlr-data-control-unstable-v1.xml',
'wlr-screencopy-unstable-v1.xml', 'wlr-screencopy-unstable-v1.xml',
'xx-color-management-v4.xml',
'frog-color-management-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml', hyprland_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml', hyprland_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml', hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-ctm-control-v1.xml', hyprland_protocol_dir / 'protocols/hyprland-ctm-control-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-surface-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-lock-notify-v1.xml',
wayland_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml', wayland_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',
wayland_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml', wayland_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml',
wayland_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml', wayland_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',

File diff suppressed because it is too large Load Diff

View File

@@ -2,18 +2,14 @@
#include "Compositor.hpp" #include "Compositor.hpp"
#include "debug/Log.hpp" #include "debug/Log.hpp"
#include "desktop/DesktopTypes.hpp"
#include "helpers/Splashes.hpp" #include "helpers/Splashes.hpp"
#include "config/ConfigValue.hpp" #include "config/ConfigValue.hpp"
#include "config/ConfigWatcher.hpp"
#include "managers/CursorManager.hpp" #include "managers/CursorManager.hpp"
#include "managers/TokenManager.hpp" #include "managers/TokenManager.hpp"
#include "managers/PointerManager.hpp" #include "managers/PointerManager.hpp"
#include "managers/SeatManager.hpp" #include "managers/SeatManager.hpp"
#include "managers/VersionKeeperManager.hpp" #include "managers/VersionKeeperManager.hpp"
#include "managers/DonationNagManager.hpp"
#include "managers/eventLoop/EventLoopManager.hpp" #include "managers/eventLoop/EventLoopManager.hpp"
#include <algorithm>
#include <aquamarine/output/Output.hpp> #include <aquamarine/output/Output.hpp>
#include <bit> #include <bit>
#include <ctime> #include <ctime>
@@ -21,23 +17,20 @@
#include <print> #include <print>
#include <cstring> #include <cstring>
#include <filesystem> #include <filesystem>
#include <ranges>
#include <print>
#include <unordered_set> #include <unordered_set>
#include "debug/HyprCtl.hpp" #include "debug/HyprCtl.hpp"
#include "debug/CrashReporter.hpp" #include "debug/CrashReporter.hpp"
#ifdef USES_SYSTEMD #ifdef USES_SYSTEMD
#include <helpers/SdDaemon.hpp> // for SdNotify #include <helpers/SdDaemon.hpp> // for SdNotify
#endif #endif
#include <ranges>
#include "helpers/varlist/VarList.hpp" #include "helpers/varlist/VarList.hpp"
#include "helpers/fs/FsUtils.hpp"
#include "protocols/FractionalScale.hpp" #include "protocols/FractionalScale.hpp"
#include "protocols/PointerConstraints.hpp" #include "protocols/PointerConstraints.hpp"
#include "protocols/LayerShell.hpp" #include "protocols/LayerShell.hpp"
#include "protocols/XDGShell.hpp" #include "protocols/XDGShell.hpp"
#include "protocols/XDGOutput.hpp" #include "protocols/XDGOutput.hpp"
#include "protocols/SecurityContext.hpp" #include "protocols/SecurityContext.hpp"
#include "protocols/ColorManagement.hpp"
#include "protocols/core/Compositor.hpp" #include "protocols/core/Compositor.hpp"
#include "protocols/core/Subcompositor.hpp" #include "protocols/core/Subcompositor.hpp"
#include "desktop/LayerSurface.hpp" #include "desktop/LayerSurface.hpp"
@@ -46,24 +39,6 @@
#include "helpers/ByteOperations.hpp" #include "helpers/ByteOperations.hpp"
#include "render/decorations/CHyprGroupBarDecoration.hpp" #include "render/decorations/CHyprGroupBarDecoration.hpp"
#include "managers/KeybindManager.hpp"
#include "managers/SessionLockManager.hpp"
#include "managers/XWaylandManager.hpp"
#include "config/ConfigManager.hpp"
#include "render/OpenGL.hpp"
#include "managers/input/InputManager.hpp"
#include "managers/AnimationManager.hpp"
#include "managers/EventManager.hpp"
#include "managers/HookSystemManager.hpp"
#include "managers/ProtocolManager.hpp"
#include "managers/LayoutManager.hpp"
#include "plugins/PluginSystem.hpp"
#include "helpers/Watchdog.hpp"
#include "hyprerror/HyprError.hpp"
#include "debug/HyprNotificationOverlay.hpp"
#include "debug/HyprDebugOverlay.hpp"
#include <hyprutils/string/String.hpp> #include <hyprutils/string/String.hpp>
#include <aquamarine/input/Input.hpp> #include <aquamarine/input/Input.hpp>
@@ -75,7 +50,7 @@
using namespace Hyprutils::String; using namespace Hyprutils::String;
using namespace Aquamarine; using namespace Aquamarine;
static int handleCritSignal(int signo, void* data) { int handleCritSignal(int signo, void* data) {
Debug::log(LOG, "Hyprland received signal {}", signo); Debug::log(LOG, "Hyprland received signal {}", signo);
if (signo == SIGTERM || signo == SIGINT || signo == SIGKILL) if (signo == SIGTERM || signo == SIGINT || signo == SIGKILL)
@@ -84,7 +59,7 @@ static int handleCritSignal(int signo, void* data) {
return 0; return 0;
} }
static void handleUnrecoverableSignal(int sig) { void handleUnrecoverableSignal(int sig) {
// remove our handlers // remove our handlers
signal(SIGABRT, SIG_DFL); signal(SIGABRT, SIG_DFL);
@@ -108,7 +83,7 @@ static void handleUnrecoverableSignal(int sig) {
abort(); abort();
} }
static void handleUserSignal(int sig) { void handleUserSignal(int sig) {
if (sig == SIGUSR1) { if (sig == SIGUSR1) {
// means we have to unwind a timed out event // means we have to unwind a timed out event
throw std::exception(); throw std::exception();
@@ -128,7 +103,7 @@ static eLogLevel aqLevelToHl(Aquamarine::eBackendLogLevel level) {
return NONE; return NONE;
} }
static void aqLog(Aquamarine::eBackendLogLevel level, std::string msg) { void aqLog(Aquamarine::eBackendLogLevel level, std::string msg) {
Debug::log(aqLevelToHl(level), "[AQ] {}", msg); Debug::log(aqLevelToHl(level), "[AQ] {}", msg);
} }
@@ -163,10 +138,7 @@ void CCompositor::restoreNofile() {
Debug::log(ERR, "Failed restoring NOFILE limits"); Debug::log(ERR, "Failed restoring NOFILE limits");
} }
CCompositor::CCompositor(bool onlyConfig) : m_bOnlyConfigVerification(onlyConfig), m_iHyprlandPID(getpid()) { CCompositor::CCompositor() : m_iHyprlandPID(getpid()) {
if (onlyConfig)
return;
m_szHyprTempDataRoot = std::string{getenv("XDG_RUNTIME_DIR")} + "/hypr"; m_szHyprTempDataRoot = std::string{getenv("XDG_RUNTIME_DIR")} + "/hypr";
if (m_szHyprTempDataRoot.starts_with("/hypr")) { if (m_szHyprTempDataRoot.starts_with("/hypr")) {
@@ -230,7 +202,7 @@ CCompositor::CCompositor(bool onlyConfig) : m_bOnlyConfigVerification(onlyConfig
} }
CCompositor::~CCompositor() { CCompositor::~CCompositor() {
if (!m_bIsShuttingDown && !m_bOnlyConfigVerification) if (!m_bIsShuttingDown)
cleanup(); cleanup();
} }
@@ -266,16 +238,6 @@ static bool filterGlobals(const wl_client* client, const wl_global* global, void
// //
void CCompositor::initServer(std::string socketName, int socketFd) { void CCompositor::initServer(std::string socketName, int socketFd) {
if (m_bOnlyConfigVerification) {
g_pHookSystem = makeUnique<CHookSystemManager>();
g_pKeybindManager = makeUnique<CKeybindManager>();
g_pAnimationManager = makeUnique<CHyprAnimationManager>();
g_pConfigManager = makeUnique<CConfigManager>();
std::println("\n\n======== Config parsing result:\n\n{}", g_pConfigManager->verify());
return;
}
m_sWLDisplay = wl_display_create(); m_sWLDisplay = wl_display_create();
wl_display_set_global_filter(m_sWLDisplay, ::filterGlobals, nullptr); wl_display_set_global_filter(m_sWLDisplay, ::filterGlobals, nullptr);
@@ -463,7 +425,7 @@ void CCompositor::initAllSignals() {
for (auto const& m : m_vMonitors) { for (auto const& m : m_vMonitors) {
scheduleFrameForMonitor(m); scheduleFrameForMonitor(m);
m->applyMonitorRule(&m->activeMonitorRule, true); g_pHyprRenderer->applyMonitorRule(m, &m->activeMonitorRule, true);
} }
g_pConfigManager->m_bWantsMonitorReload = true; g_pConfigManager->m_bWantsMonitorReload = true;
@@ -472,6 +434,11 @@ void CCompositor::initAllSignals() {
Debug::log(LOG, "Session got deactivated!"); Debug::log(LOG, "Session got deactivated!");
m_bSessionActive = false; m_bSessionActive = false;
for (auto const& m : m_vMonitors) {
m->noFrameSchedule = true;
m->framesToSkip = 1;
}
} }
}, },
nullptr); nullptr);
@@ -567,10 +534,12 @@ void CCompositor::cleanup() {
g_pProtocolManager.reset(); g_pProtocolManager.reset();
g_pHyprRenderer.reset(); g_pHyprRenderer.reset();
g_pHyprOpenGL.reset(); g_pHyprOpenGL.reset();
g_pThreadManager.reset();
g_pConfigManager.reset(); g_pConfigManager.reset();
g_pLayoutManager.reset(); g_pLayoutManager.reset();
g_pHyprError.reset(); g_pHyprError.reset();
g_pConfigManager.reset(); g_pConfigManager.reset();
g_pAnimationManager.reset();
g_pKeybindManager.reset(); g_pKeybindManager.reset();
g_pHookSystem.reset(); g_pHookSystem.reset();
g_pWatchdog.reset(); g_pWatchdog.reset();
@@ -579,9 +548,6 @@ void CCompositor::cleanup() {
g_pSeatManager.reset(); g_pSeatManager.reset();
g_pHyprCtl.reset(); g_pHyprCtl.reset();
g_pEventLoopManager.reset(); g_pEventLoopManager.reset();
g_pVersionKeeperMgr.reset();
g_pDonationNagManager.reset();
g_pConfigWatcher.reset();
if (m_pAqBackend) if (m_pAqBackend)
m_pAqBackend.reset(); m_pAqBackend.reset();
@@ -599,92 +565,92 @@ void CCompositor::initManagers(eManagersInitStage stage) {
switch (stage) { switch (stage) {
case STAGE_PRIORITY: { case STAGE_PRIORITY: {
Debug::log(LOG, "Creating the EventLoopManager!"); Debug::log(LOG, "Creating the EventLoopManager!");
g_pEventLoopManager = makeUnique<CEventLoopManager>(m_sWLDisplay, m_sWLEventLoop); g_pEventLoopManager = std::make_unique<CEventLoopManager>(m_sWLDisplay, m_sWLEventLoop);
Debug::log(LOG, "Creating the HookSystem!"); Debug::log(LOG, "Creating the HookSystem!");
g_pHookSystem = makeUnique<CHookSystemManager>(); g_pHookSystem = std::make_unique<CHookSystemManager>();
Debug::log(LOG, "Creating the KeybindManager!"); Debug::log(LOG, "Creating the KeybindManager!");
g_pKeybindManager = makeUnique<CKeybindManager>(); g_pKeybindManager = std::make_unique<CKeybindManager>();
Debug::log(LOG, "Creating the AnimationManager!"); Debug::log(LOG, "Creating the AnimationManager!");
g_pAnimationManager = makeUnique<CHyprAnimationManager>(); g_pAnimationManager = std::make_unique<CAnimationManager>();
Debug::log(LOG, "Creating the ConfigManager!"); Debug::log(LOG, "Creating the ConfigManager!");
g_pConfigManager = makeUnique<CConfigManager>(); g_pConfigManager = std::make_unique<CConfigManager>();
Debug::log(LOG, "Creating the CHyprError!"); Debug::log(LOG, "Creating the CHyprError!");
g_pHyprError = makeUnique<CHyprError>(); g_pHyprError = std::make_unique<CHyprError>();
Debug::log(LOG, "Creating the LayoutManager!"); Debug::log(LOG, "Creating the LayoutManager!");
g_pLayoutManager = makeUnique<CLayoutManager>(); g_pLayoutManager = std::make_unique<CLayoutManager>();
Debug::log(LOG, "Creating the TokenManager!"); Debug::log(LOG, "Creating the TokenManager!");
g_pTokenManager = makeUnique<CTokenManager>(); g_pTokenManager = std::make_unique<CTokenManager>();
g_pConfigManager->init(); g_pConfigManager->init();
g_pWatchdog = makeUnique<CWatchdog>(); // requires config g_pWatchdog = std::make_unique<CWatchdog>(); // requires config
// wait for watchdog to initialize to not hit data races in reading config values. // wait for watchdog to initialize to not hit data races in reading config values.
while (!g_pWatchdog->m_bWatchdogInitialized) { while (!g_pWatchdog->m_bWatchdogInitialized) {
std::this_thread::yield(); std::this_thread::yield();
} }
Debug::log(LOG, "Creating the PointerManager!"); Debug::log(LOG, "Creating the PointerManager!");
g_pPointerManager = makeUnique<CPointerManager>(); g_pPointerManager = std::make_unique<CPointerManager>();
Debug::log(LOG, "Creating the EventManager!"); Debug::log(LOG, "Creating the EventManager!");
g_pEventManager = makeUnique<CEventManager>(); g_pEventManager = std::make_unique<CEventManager>();
} break; } break;
case STAGE_BASICINIT: { case STAGE_BASICINIT: {
Debug::log(LOG, "Creating the CHyprOpenGLImpl!"); Debug::log(LOG, "Creating the CHyprOpenGLImpl!");
g_pHyprOpenGL = makeUnique<CHyprOpenGLImpl>(); g_pHyprOpenGL = std::make_unique<CHyprOpenGLImpl>();
Debug::log(LOG, "Creating the ProtocolManager!"); Debug::log(LOG, "Creating the ProtocolManager!");
g_pProtocolManager = makeUnique<CProtocolManager>(); g_pProtocolManager = std::make_unique<CProtocolManager>();
Debug::log(LOG, "Creating the SeatManager!"); Debug::log(LOG, "Creating the SeatManager!");
g_pSeatManager = makeUnique<CSeatManager>(); g_pSeatManager = std::make_unique<CSeatManager>();
} break; } break;
case STAGE_LATE: { case STAGE_LATE: {
Debug::log(LOG, "Creating the ThreadManager!");
g_pThreadManager = std::make_unique<CThreadManager>();
Debug::log(LOG, "Creating CHyprCtl"); Debug::log(LOG, "Creating CHyprCtl");
g_pHyprCtl = makeUnique<CHyprCtl>(); g_pHyprCtl = std::make_unique<CHyprCtl>();
Debug::log(LOG, "Creating the InputManager!"); Debug::log(LOG, "Creating the InputManager!");
g_pInputManager = makeUnique<CInputManager>(); g_pInputManager = std::make_unique<CInputManager>();
Debug::log(LOG, "Creating the HyprRenderer!"); Debug::log(LOG, "Creating the HyprRenderer!");
g_pHyprRenderer = makeUnique<CHyprRenderer>(); g_pHyprRenderer = std::make_unique<CHyprRenderer>();
Debug::log(LOG, "Creating the XWaylandManager!"); Debug::log(LOG, "Creating the XWaylandManager!");
g_pXWaylandManager = makeUnique<CHyprXWaylandManager>(); g_pXWaylandManager = std::make_unique<CHyprXWaylandManager>();
Debug::log(LOG, "Creating the SessionLockManager!"); Debug::log(LOG, "Creating the SessionLockManager!");
g_pSessionLockManager = makeUnique<CSessionLockManager>(); g_pSessionLockManager = std::make_unique<CSessionLockManager>();
Debug::log(LOG, "Creating the HyprDebugOverlay!"); Debug::log(LOG, "Creating the HyprDebugOverlay!");
g_pDebugOverlay = makeUnique<CHyprDebugOverlay>(); g_pDebugOverlay = std::make_unique<CHyprDebugOverlay>();
Debug::log(LOG, "Creating the HyprNotificationOverlay!"); Debug::log(LOG, "Creating the HyprNotificationOverlay!");
g_pHyprNotificationOverlay = makeUnique<CHyprNotificationOverlay>(); g_pHyprNotificationOverlay = std::make_unique<CHyprNotificationOverlay>();
Debug::log(LOG, "Creating the PluginSystem!"); Debug::log(LOG, "Creating the PluginSystem!");
g_pPluginSystem = makeUnique<CPluginSystem>(); g_pPluginSystem = std::make_unique<CPluginSystem>();
g_pConfigManager->handlePluginLoads(); g_pConfigManager->handlePluginLoads();
Debug::log(LOG, "Creating the DecorationPositioner!"); Debug::log(LOG, "Creating the DecorationPositioner!");
g_pDecorationPositioner = makeUnique<CDecorationPositioner>(); g_pDecorationPositioner = std::make_unique<CDecorationPositioner>();
Debug::log(LOG, "Creating the CursorManager!"); Debug::log(LOG, "Creating the CursorManager!");
g_pCursorManager = makeUnique<CCursorManager>(); g_pCursorManager = std::make_unique<CCursorManager>();
Debug::log(LOG, "Creating the VersionKeeper!"); Debug::log(LOG, "Creating the VersionKeeper!");
g_pVersionKeeperMgr = makeUnique<CVersionKeeperManager>(); g_pVersionKeeperMgr = std::make_unique<CVersionKeeperManager>();
Debug::log(LOG, "Creating the DonationNag!");
g_pDonationNagManager = makeUnique<CDonationNagManager>();
Debug::log(LOG, "Starting XWayland"); Debug::log(LOG, "Starting XWayland");
g_pXWayland = makeUnique<CXWayland>(g_pCompositor->m_bWantsXwayland); g_pXWayland = std::make_unique<CXWayland>(g_pCompositor->m_bEnableXwayland);
} break; } break;
default: UNREACHABLE(); default: UNREACHABLE();
} }
@@ -1003,11 +969,11 @@ SP<CWLSurfaceResource> CCompositor::vectorWindowToSurface(const Vector2D& pos, P
if (PPOPUP) { if (PPOPUP) {
const auto OFF = PPOPUP->coordsRelativeToParent(); const auto OFF = PPOPUP->coordsRelativeToParent();
sl = pos - pWindow->m_vRealPosition->goal() - OFF; sl = pos - pWindow->m_vRealPosition.goal() - OFF;
return PPOPUP->m_pWLSurface->resource(); return PPOPUP->m_pWLSurface->resource();
} }
auto [surf, local] = pWindow->m_pWLSurface->resource()->at(pos - pWindow->m_vRealPosition->goal(), true); auto [surf, local] = pWindow->m_pWLSurface->resource()->at(pos - pWindow->m_vRealPosition.goal(), true);
if (surf) { if (surf) {
sl = local; sl = local;
return surf; return surf;
@@ -1021,7 +987,7 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindo
return {}; return {};
if (pWindow->m_bIsX11) if (pWindow->m_bIsX11)
return vec - pWindow->m_vRealPosition->goal(); return vec - pWindow->m_vRealPosition.goal();
const auto PPOPUP = pWindow->m_pPopupHead->at(vec); const auto PPOPUP = pWindow->m_pPopupHead->at(vec);
if (PPOPUP) if (PPOPUP)
@@ -1040,9 +1006,9 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, PHLWINDOW pWindo
CBox geom = pWindow->m_pXDGSurface->current.geometry; CBox geom = pWindow->m_pXDGSurface->current.geometry;
if (std::get<1>(iterData) == Vector2D{-1337, -1337}) if (std::get<1>(iterData) == Vector2D{-1337, -1337})
return vec - pWindow->m_vRealPosition->goal(); return vec - pWindow->m_vRealPosition.goal();
return vec - pWindow->m_vRealPosition->goal() - std::get<1>(iterData) + Vector2D{geom.x, geom.y}; return vec - pWindow->m_vRealPosition.goal() - std::get<1>(iterData) + Vector2D{geom.x, geom.y};
} }
PHLMONITOR CCompositor::getMonitorFromOutput(SP<Aquamarine::IOutput> out) { PHLMONITOR CCompositor::getMonitorFromOutput(SP<Aquamarine::IOutput> out) {
@@ -1168,7 +1134,6 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface
g_pXWaylandManager->activateWindow(pWindow, true); // sets the m_pLastWindow g_pXWaylandManager->activateWindow(pWindow, true); // sets the m_pLastWindow
pWindow->updateDynamicRules(); pWindow->updateDynamicRules();
pWindow->onFocusAnimUpdate();
updateWindowAnimatedDecorationValues(pWindow); updateWindowAnimatedDecorationValues(pWindow);
@@ -1251,7 +1216,7 @@ void CCompositor::focusSurface(SP<CWLSurfaceResource> pSurface, PHLWINDOW pWindo
SP<CWLSurfaceResource> CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, PHLMONITOR monitor, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { SP<CWLSurfaceResource> CCompositor::vectorToLayerPopupSurface(const Vector2D& pos, PHLMONITOR monitor, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) {
for (auto const& lsl : monitor->m_aLayerSurfaceLayers | std::views::reverse) { for (auto const& lsl : monitor->m_aLayerSurfaceLayers | std::views::reverse) {
for (auto const& ls : lsl | std::views::reverse) { for (auto const& ls : lsl | std::views::reverse) {
if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->mapped) || ls->alpha->value() == 0.f) if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->mapped) || ls->alpha.value() == 0.f)
continue; continue;
auto SURFACEAT = ls->popupHead->at(pos, true); auto SURFACEAT = ls->popupHead->at(pos, true);
@@ -1269,7 +1234,7 @@ SP<CWLSurfaceResource> CCompositor::vectorToLayerPopupSurface(const Vector2D& po
SP<CWLSurfaceResource> CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<PHLLSREF>* layerSurfaces, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) { SP<CWLSurfaceResource> CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector<PHLLSREF>* layerSurfaces, Vector2D* sCoords, PHLLS* ppLayerSurfaceFound) {
for (auto const& ls : *layerSurfaces | std::views::reverse) { for (auto const& ls : *layerSurfaces | std::views::reverse) {
if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha->value() == 0.f) if (ls->fadingOut || !ls->layerSurface || (ls->layerSurface && !ls->layerSurface->surface->mapped) || ls->alpha.value() == 0.f)
continue; continue;
auto [surf, local] = ls->layerSurface->surface->at(pos - ls->geometry.pos(), true); auto [surf, local] = ls->layerSurface->surface->at(pos - ls->geometry.pos(), true);
@@ -1418,7 +1383,7 @@ void CCompositor::cleanupFadingOut(const MONITORID& monid) {
if (w->monitorID() != monid && w->m_pMonitor) if (w->monitorID() != monid && w->m_pMonitor)
continue; continue;
if (!w->m_bFadingOut || w->m_fAlpha->value() == 0.f) { if (!w->m_bFadingOut || w->m_fAlpha.value() == 0.f) {
w->m_bFadingOut = false; w->m_bFadingOut = false;
@@ -1500,21 +1465,7 @@ void CCompositor::addToFadingOutSafe(PHLWINDOW pWindow) {
} }
PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) { PHLWINDOW CCompositor::getWindowInDirection(PHLWINDOW pWindow, char dir) {
if (!isDirection(dir))
return nullptr;
const auto PMONITOR = pWindow->m_pMonitor.lock();
if (!PMONITOR)
return nullptr; // ??
const auto WINDOWIDEALBB = pWindow->isFullscreen() ? CBox{PMONITOR->vecPosition, PMONITOR->vecSize} : pWindow->getWindowIdealBoundingBoxIgnoreReserved();
const auto PWORKSPACE = pWindow->m_pWorkspace;
return getWindowInDirection(WINDOWIDEALBB, PWORKSPACE, dir, pWindow, pWindow->m_bIsFloating);
}
PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorkspace, char dir, PHLWINDOW ignoreWindow, bool useVectorAngles) {
if (!isDirection(dir)) if (!isDirection(dir))
return nullptr; return nullptr;
@@ -1522,24 +1473,34 @@ PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorks
static auto PMETHOD = CConfigValue<Hyprlang::INT>("binds:focus_preferred_method"); static auto PMETHOD = CConfigValue<Hyprlang::INT>("binds:focus_preferred_method");
static auto PMONITORFALLBACK = CConfigValue<Hyprlang::INT>("binds:window_direction_monitor_fallback"); static auto PMONITORFALLBACK = CConfigValue<Hyprlang::INT>("binds:window_direction_monitor_fallback");
const auto POSA = box.pos(); const auto PMONITOR = pWindow->m_pMonitor.lock();
const auto SIZEA = box.size();
auto leaderValue = -1; if (!PMONITOR)
PHLWINDOW leaderWindow = nullptr; return nullptr; // ??
if (!useVectorAngles) { const auto WINDOWIDEALBB = pWindow->isFullscreen() ? CBox{PMONITOR->vecPosition, PMONITOR->vecSize} : pWindow->getWindowIdealBoundingBoxIgnoreReserved();
const auto POSA = Vector2D(WINDOWIDEALBB.x, WINDOWIDEALBB.y);
const auto SIZEA = Vector2D(WINDOWIDEALBB.width, WINDOWIDEALBB.height);
const auto PWORKSPACE = pWindow->m_pWorkspace;
auto leaderValue = -1;
PHLWINDOW leaderWindow = nullptr;
if (!pWindow->m_bIsFloating) {
// for tiled windows, we calc edges
for (auto const& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w == ignoreWindow || !w->m_pWorkspace || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && w->m_bIsFloating) || !w->m_pWorkspace->isVisible()) if (w == pWindow || !w->m_pWorkspace || !w->m_bIsMapped || w->isHidden() || (!w->isFullscreen() && w->m_bIsFloating) || !w->m_pWorkspace->isVisible())
continue; continue;
if (pWorkspace->m_pMonitor == w->m_pMonitor && pWorkspace != w->m_pWorkspace) if (pWindow->m_pMonitor == w->m_pMonitor && pWindow->m_pWorkspace != w->m_pWorkspace)
continue; continue;
if (pWorkspace->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen) if (PWORKSPACE->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen)
continue; continue;
if (!*PMONITORFALLBACK && pWorkspace->m_pMonitor != w->m_pMonitor) if (!*PMONITORFALLBACK && pWindow->m_pMonitor != w->m_pMonitor)
continue; continue;
const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved(); const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved();
@@ -1601,6 +1562,9 @@ PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorks
} }
} }
} else { } else {
// for floating windows, we calculate best distance and angle.
// if there is a window with angle better than THRESHOLD, only distance counts
if (dir == 'u') if (dir == 'u')
dir = 't'; dir = 't';
if (dir == 'd') if (dir == 'd')
@@ -1619,20 +1583,20 @@ PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorks
constexpr float THRESHOLD = 0.3 * M_PI; constexpr float THRESHOLD = 0.3 * M_PI;
for (auto const& w : m_vWindows) { for (auto const& w : m_vWindows) {
if (w == ignoreWindow || !w->m_bIsMapped || !w->m_pWorkspace || w->isHidden() || (!w->isFullscreen() && !w->m_bIsFloating) || !w->m_pWorkspace->isVisible()) if (w == pWindow || !w->m_bIsMapped || !w->m_pWorkspace || w->isHidden() || (!w->isFullscreen() && !w->m_bIsFloating) || !w->m_pWorkspace->isVisible())
continue; continue;
if (pWorkspace->m_pMonitor == w->m_pMonitor && pWorkspace != w->m_pWorkspace) if (pWindow->m_pMonitor == w->m_pMonitor && pWindow->m_pWorkspace != w->m_pWorkspace)
continue; continue;
if (pWorkspace->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen) if (PWORKSPACE->m_bHasFullscreenWindow && !w->isFullscreen() && !w->m_bCreatedOverFullscreen)
continue; continue;
if (!*PMONITORFALLBACK && pWorkspace->m_pMonitor != w->m_pMonitor) if (!*PMONITORFALLBACK && pWindow->m_pMonitor != w->m_pMonitor)
continue; continue;
const auto DIST = w->middle().distance(box.middle()); const auto DIST = w->middle().distance(pWindow->middle());
const auto ANGLE = vectorAngles(Vector2D{w->middle() - box.middle()}, VECTORS.at(dir)); const auto ANGLE = vectorAngles(Vector2D{w->middle() - pWindow->middle()}, VECTORS.at(dir));
if (ANGLE > M_PI_2) if (ANGLE > M_PI_2)
continue; // if the angle is over 90 degrees, ignore. Wrong direction entirely. continue; // if the angle is over 90 degrees, ignore. Wrong direction entirely.
@@ -1644,8 +1608,8 @@ PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorks
} }
} }
if (!leaderWindow && pWorkspace->m_bHasFullscreenWindow) if (!leaderWindow && PWORKSPACE->m_bHasFullscreenWindow)
leaderWindow = pWorkspace->getFullscreenWindow(); leaderWindow = PWORKSPACE->getFullscreenWindow();
} }
if (leaderValue != -1) if (leaderValue != -1)
@@ -1654,37 +1618,62 @@ PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorks
return nullptr; return nullptr;
} }
PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional<bool> floating, bool visible) { PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional<bool> floating) {
auto it = std::ranges::find(m_vWindows, pWindow); bool gotToWindow = false;
const auto FINDER = [&](const PHLWINDOW& w) { return isWindowAvailableForCycle(pWindow, w, focusableOnly, floating, visible); }; for (auto const& w : m_vWindows) {
const auto IN_RIGHT = std::find_if(it, m_vWindows.end(), FINDER); if (w != pWindow && !gotToWindow)
if (IN_RIGHT != m_vWindows.end()) continue;
return *IN_RIGHT;
const auto IN_LEFT = std::find_if(m_vWindows.begin(), it, FINDER); if (w == pWindow) {
return *IN_LEFT; gotToWindow = true;
continue;
}
if (floating.has_value() && w->m_bIsFloating != floating.value())
continue;
if (w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()))
return w;
}
for (auto const& w : m_vWindows) {
if (floating.has_value() && w->m_bIsFloating != floating.value())
continue;
if (w != pWindow && w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()))
return w;
}
return nullptr;
} }
PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional<bool> floating, bool visible) { PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional<bool> floating) {
auto it = std::ranges::find(std::ranges::reverse_view(m_vWindows), pWindow); bool gotToWindow = false;
const auto FINDER = [&](const PHLWINDOW& w) { return isWindowAvailableForCycle(pWindow, w, focusableOnly, floating, visible); }; for (auto const& w : m_vWindows | std::views::reverse) {
const auto IN_LEFT = std::find_if(it, m_vWindows.rend(), FINDER); if (w != pWindow && !gotToWindow)
if (IN_LEFT != m_vWindows.rend()) continue;
return *IN_LEFT;
const auto IN_RIGHT = std::find_if(m_vWindows.rbegin(), it, FINDER);
return *IN_RIGHT;
}
inline static bool isWorkspaceMatches(PHLWINDOW pWindow, const PHLWINDOW w, bool anyWorkspace) { if (w == pWindow) {
return anyWorkspace ? w->m_pWorkspace && w->m_pWorkspace->isVisible() : w->m_pWorkspace == pWindow->m_pWorkspace; gotToWindow = true;
} continue;
}
inline static bool isFloatingMatches(PHLWINDOW w, std::optional<bool> floating) { if (floating.has_value() && w->m_bIsFloating != floating.value())
return !floating.has_value() || w->m_bIsFloating == floating.value(); continue;
};
bool CCompositor::isWindowAvailableForCycle(PHLWINDOW pWindow, const PHLWINDOW w, bool focusableOnly, std::optional<bool> floating, bool anyWorkspace) { if (w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()))
return isFloatingMatches(w, floating) && w != pWindow && isWorkspaceMatches(pWindow, w, anyWorkspace) && w->m_bIsMapped && !w->isHidden() && return w;
(!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()); }
for (auto const& w : m_vWindows | std::views::reverse) {
if (floating.has_value() && w->m_bIsFloating != floating.value())
continue;
if (w != pWindow && w->m_pWorkspace == pWindow->m_pWorkspace && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()))
return w;
}
return nullptr;
} }
WORKSPACEID CCompositor::getNextAvailableNamedWorkspace() { WORKSPACEID CCompositor::getNextAvailableNamedWorkspace() {
@@ -1719,8 +1708,12 @@ PHLWORKSPACE CCompositor::getWorkspaceByString(const std::string& str) {
} }
bool CCompositor::isPointOnAnyMonitor(const Vector2D& point) { bool CCompositor::isPointOnAnyMonitor(const Vector2D& point) {
return std::ranges::any_of( for (auto const& m : m_vMonitors) {
m_vMonitors, [&](const PHLMONITOR& m) { return VECINRECT(point, m->vecPosition.x, m->vecPosition.y, m->vecSize.x + m->vecPosition.x, m->vecSize.y + m->vecPosition.y); }); if (VECINRECT(point, m->vecPosition.x, m->vecPosition.y, m->vecSize.x + m->vecPosition.x, m->vecSize.y + m->vecPosition.y))
return true;
}
return false;
} }
bool CCompositor::isPointOnReservedArea(const Vector2D& point, const PHLMONITOR pMonitor) { bool CCompositor::isPointOnReservedArea(const Vector2D& point, const PHLMONITOR pMonitor) {
@@ -1842,8 +1835,8 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) {
pWindow->m_cRealBorderColorPrevious = pWindow->m_cRealBorderColor; pWindow->m_cRealBorderColorPrevious = pWindow->m_cRealBorderColor;
pWindow->m_cRealBorderColor = grad; pWindow->m_cRealBorderColor = grad;
pWindow->m_fBorderFadeAnimationProgress->setValueAndWarp(0.f); pWindow->m_fBorderFadeAnimationProgress.setValueAndWarp(0.f);
*pWindow->m_fBorderFadeAnimationProgress = 1.f; pWindow->m_fBorderFadeAnimationProgress = 1.f;
}; };
const bool IS_SHADOWED_BY_MODAL = pWindow->m_pXDGSurface && pWindow->m_pXDGSurface->toplevel && pWindow->m_pXDGSurface->toplevel->anyChildModal(); const bool IS_SHADOWED_BY_MODAL = pWindow->m_pXDGSurface && pWindow->m_pXDGSurface->toplevel && pWindow->m_pXDGSurface->toplevel->anyChildModal();
@@ -1865,15 +1858,19 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) {
} }
} }
// tick angle if it's not running (aka dead)
if (!pWindow->m_fBorderAngleAnimationProgress.isBeingAnimated())
pWindow->m_fBorderAngleAnimationProgress.setValueAndWarp(0.f);
// opacity // opacity
const auto PWORKSPACE = pWindow->m_pWorkspace; const auto PWORKSPACE = pWindow->m_pWorkspace;
if (pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) { if (pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) {
*pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaFullscreen.valueOrDefault().applyAlpha(*PFULLSCREENALPHA); pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaFullscreen.valueOrDefault().applyAlpha(*PFULLSCREENALPHA);
} else { } else {
if (pWindow == m_pLastWindow) if (pWindow == m_pLastWindow)
*pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alpha.valueOrDefault().applyAlpha(*PACTIVEALPHA); pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alpha.valueOrDefault().applyAlpha(*PACTIVEALPHA);
else else
*pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaInactive.valueOrDefault().applyAlpha(*PINACTIVEALPHA); pWindow->m_fActiveInactiveAlpha = pWindow->m_sWindowData.alphaInactive.valueOrDefault().applyAlpha(*PINACTIVEALPHA);
} }
// dim // dim
@@ -1886,16 +1883,16 @@ void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) {
if (IS_SHADOWED_BY_MODAL) if (IS_SHADOWED_BY_MODAL)
goalDim += (1.F - goalDim) / 2.F; goalDim += (1.F - goalDim) / 2.F;
*pWindow->m_fDimPercent = goalDim; pWindow->m_fDimPercent = goalDim;
// shadow // shadow
if (!pWindow->isX11OverrideRedirect() && !pWindow->m_bX11DoesntWantBorders) { if (!pWindow->isX11OverrideRedirect() && !pWindow->m_bX11DoesntWantBorders) {
if (pWindow == m_pLastWindow) if (pWindow == m_pLastWindow)
*pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOL); pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOL);
else else
*pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOLINACTIVE != INT64_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL); pWindow->m_cRealShadowColor = CHyprColor(*PSHADOWCOLINACTIVE != INT64_MAX ? *PSHADOWCOLINACTIVE : *PSHADOWCOL);
} else { } else {
pWindow->m_cRealShadowColor->setValueAndWarp(CHyprColor(0, 0, 0, 0)); // no shadow pWindow->m_cRealShadowColor.setValueAndWarp(CHyprColor(0, 0, 0, 0)); // no shadow
} }
pWindow->updateWindowDecos(); pWindow->updateWindowDecos();
@@ -1939,11 +1936,11 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor
// additionally, move floating and fs windows manually // additionally, move floating and fs windows manually
if (w->m_bIsFloating) if (w->m_bIsFloating)
*w->m_vRealPosition = w->m_vRealPosition->goal() - pMonitorA->vecPosition + pMonitorB->vecPosition; w->m_vRealPosition = w->m_vRealPosition.goal() - pMonitorA->vecPosition + pMonitorB->vecPosition;
if (w->isFullscreen()) { if (w->isFullscreen()) {
*w->m_vRealPosition = pMonitorB->vecPosition; w->m_vRealPosition = pMonitorB->vecPosition;
*w->m_vRealSize = pMonitorB->vecSize; w->m_vRealSize = pMonitorB->vecSize;
} }
w->updateToplevel(); w->updateToplevel();
@@ -1964,11 +1961,11 @@ void CCompositor::swapActiveWorkspaces(PHLMONITOR pMonitorA, PHLMONITOR pMonitor
// additionally, move floating and fs windows manually // additionally, move floating and fs windows manually
if (w->m_bIsFloating) if (w->m_bIsFloating)
*w->m_vRealPosition = w->m_vRealPosition->goal() - pMonitorB->vecPosition + pMonitorA->vecPosition; w->m_vRealPosition = w->m_vRealPosition.goal() - pMonitorB->vecPosition + pMonitorA->vecPosition;
if (w->isFullscreen()) { if (w->isFullscreen()) {
*w->m_vRealPosition = pMonitorA->vecPosition; w->m_vRealPosition = pMonitorA->vecPosition;
*w->m_vRealSize = pMonitorA->vecSize; w->m_vRealSize = pMonitorA->vecSize;
} }
w->updateToplevel(); w->updateToplevel();
@@ -2083,8 +2080,7 @@ PHLMONITOR CCompositor::getMonitorFromString(const std::string& name) {
void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMonitor, bool noWarpCursor) { void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMonitor, bool noWarpCursor) {
if (!pWorkspace || !pMonitor) // We trust the monitor to be correct.
return;
if (pWorkspace->m_pMonitor == pMonitor) if (pWorkspace->m_pMonitor == pMonitor)
return; return;
@@ -2142,14 +2138,14 @@ void CCompositor::moveWorkspaceToMonitor(PHLWORKSPACE pWorkspace, PHLMONITOR pMo
if (w->m_bIsMapped && !w->isHidden()) { if (w->m_bIsMapped && !w->isHidden()) {
if (POLDMON) { if (POLDMON) {
if (w->m_bIsFloating) if (w->m_bIsFloating)
*w->m_vRealPosition = w->m_vRealPosition->goal() - POLDMON->vecPosition + pMonitor->vecPosition; w->m_vRealPosition = w->m_vRealPosition.goal() - POLDMON->vecPosition + pMonitor->vecPosition;
if (w->isFullscreen()) { if (w->isFullscreen()) {
*w->m_vRealPosition = pMonitor->vecPosition; w->m_vRealPosition = pMonitor->vecPosition;
*w->m_vRealSize = pMonitor->vecSize; w->m_vRealSize = pMonitor->vecSize;
} }
} else { } else {
*w->m_vRealPosition = Vector2D{(int)w->m_vRealPosition->goal().x % (int)pMonitor->vecSize.x, (int)w->m_vRealPosition->goal().y % (int)pMonitor->vecSize.y}; w->m_vRealPosition = Vector2D{(int)w->m_vRealPosition.goal().x % (int)pMonitor->vecSize.x, (int)w->m_vRealPosition.goal().y % (int)pMonitor->vecSize.y};
} }
} }
@@ -2223,9 +2219,9 @@ void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) {
continue; continue;
if (!FULLSCREEN) if (!FULLSCREEN)
*w->m_fAlpha = 1.f; w->m_fAlpha = 1.f;
else if (!w->isFullscreen()) else if (!w->isFullscreen())
*w->m_fAlpha = !w->m_bCreatedOverFullscreen ? 0.f : 1.f; w->m_fAlpha = !w->m_bCreatedOverFullscreen ? 0.f : 1.f;
} }
} }
@@ -2234,11 +2230,16 @@ void CCompositor::updateFullscreenFadeOnWorkspace(PHLWORKSPACE pWorkspace) {
if (pWorkspace->m_iID == PMONITOR->activeWorkspaceID() || pWorkspace->m_iID == PMONITOR->activeSpecialWorkspaceID()) { if (pWorkspace->m_iID == PMONITOR->activeWorkspaceID() || pWorkspace->m_iID == PMONITOR->activeSpecialWorkspaceID()) {
for (auto const& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { for (auto const& ls : PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) {
if (!ls->fadingOut) if (!ls->fadingOut)
*ls->alpha = FULLSCREEN && pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f; ls->alpha = FULLSCREEN && pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN ? 0.f : 1.f;
} }
} }
} }
void CCompositor::changeWindowFullscreenModeInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON) {
setWindowFullscreenInternal(
PWINDOW, (eFullscreenMode)(ON ? (uint8_t)PWINDOW->m_sFullscreenState.internal | (uint8_t)MODE : ((uint8_t)PWINDOW->m_sFullscreenState.internal & (uint8_t)~MODE)));
}
void CCompositor::changeWindowFullscreenModeClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON) { void CCompositor::changeWindowFullscreenModeClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON) {
setWindowFullscreenClient(PWINDOW, setWindowFullscreenClient(PWINDOW,
(eFullscreenMode)(ON ? (uint8_t)PWINDOW->m_sFullscreenState.client | (uint8_t)MODE : ((uint8_t)PWINDOW->m_sFullscreenState.client & (uint8_t)~MODE))); (eFullscreenMode)(ON ? (uint8_t)PWINDOW->m_sFullscreenState.client | (uint8_t)MODE : ((uint8_t)PWINDOW->m_sFullscreenState.client & (uint8_t)~MODE)));
@@ -2324,7 +2325,7 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, SFullscreenS
updateFullscreenFadeOnWorkspace(PWORKSPACE); updateFullscreenFadeOnWorkspace(PWORKSPACE);
PWINDOW->sendWindowSize(PWINDOW->m_vRealSize->goal(), true); g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal(), true);
PWORKSPACE->forceReportSizesToWindows(); PWORKSPACE->forceReportSizesToWindows();
@@ -2407,9 +2408,6 @@ PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp_) {
} else if (regexp.starts_with("initialtitle:")) { } else if (regexp.starts_with("initialtitle:")) {
mode = MODE_INITIAL_TITLE_REGEX; mode = MODE_INITIAL_TITLE_REGEX;
regexCheck = regexp.substr(13); regexCheck = regexp.substr(13);
} else if (regexp.starts_with("tag:")) {
mode = MODE_TAG_REGEX;
regexCheck = regexp.substr(4);
} else if (regexp.starts_with("address:")) { } else if (regexp.starts_with("address:")) {
mode = MODE_ADDRESS; mode = MODE_ADDRESS;
matchCheck = regexp.substr(8); matchCheck = regexp.substr(8);
@@ -2447,18 +2445,6 @@ PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp_) {
continue; continue;
break; break;
} }
case MODE_TAG_REGEX: {
bool tagMatched = false;
for (auto const& t : w->m_tags.getTags()) {
if (RE2::FullMatch(t, regexCheck)) {
tagMatched = true;
break;
}
}
if (!tagMatched)
continue;
break;
}
case MODE_ADDRESS: { case MODE_ADDRESS: {
std::string addr = std::format("0x{:x}", (uintptr_t)w.get()); std::string addr = std::format("0x{:x}", (uintptr_t)w.get());
if (matchCheck != addr) if (matchCheck != addr)
@@ -2518,13 +2504,13 @@ PHLLS CCompositor::getLayerSurfaceFromSurface(SP<CWLSurfaceResource> pSurface) {
continue; continue;
ls->layerSurface->surface->breadthfirst( ls->layerSurface->surface->breadthfirst(
[&result](SP<CWLSurfaceResource> surf, const Vector2D& offset, void* data) { [](SP<CWLSurfaceResource> surf, const Vector2D& offset, void* data) {
if (surf == result.first) { if (surf == ((std::pair<SP<CWLSurfaceResource>, bool>*)data)->first) {
result.second = true; *(bool*)data = true;
return; return;
} }
}, },
nullptr); &result);
if (result.second) if (result.second)
return ls; return ls;
@@ -2595,7 +2581,7 @@ PHLWORKSPACE CCompositor::createNewWorkspace(const WORKSPACEID& id, const MONITO
const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, getMonitorFromID(monID), NAME, SPECIAL, isEmpty)); const auto PWORKSPACE = m_vWorkspaces.emplace_back(CWorkspace::create(id, getMonitorFromID(monID), NAME, SPECIAL, isEmpty));
PWORKSPACE->m_fAlpha->setValueAndWarp(0); PWORKSPACE->m_fAlpha.setValueAndWarp(0);
return PWORKSPACE; return PWORKSPACE;
} }
@@ -2611,12 +2597,7 @@ void CCompositor::setActiveMonitor(PHLMONITOR pMonitor) {
const auto PWORKSPACE = pMonitor->activeWorkspace; const auto PWORKSPACE = pMonitor->activeWorkspace;
const auto WORKSPACE_ID = PWORKSPACE ? std::to_string(PWORKSPACE->m_iID) : std::to_string(WORKSPACE_INVALID); g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", pMonitor->szName + "," + (PWORKSPACE ? PWORKSPACE->m_szName : "?")});
const auto WORKSPACE_NAME = PWORKSPACE ? PWORKSPACE->m_szName : "?";
g_pEventManager->postEvent(SHyprIPCEvent{"focusedmon", pMonitor->szName + "," + WORKSPACE_NAME});
g_pEventManager->postEvent(SHyprIPCEvent{"focusedmonv2", pMonitor->szName + "," + WORKSPACE_ID});
EMIT_HOOK_EVENT("focusedMon", pMonitor); EMIT_HOOK_EVENT("focusedMon", pMonitor);
m_pLastMonitor = pMonitor->self; m_pLastMonitor = pMonitor->self;
} }
@@ -2651,7 +2632,7 @@ void CCompositor::performUserChecks() {
} }
if (!*PNOCHECKQTUTILS) { if (!*PNOCHECKQTUTILS) {
if (!NFsUtils::executableExistsInPath("hyprland-dialog")) { if (!executableExistsInPath("hyprland-dialog")) {
g_pHyprNotificationOverlay->addNotification( g_pHyprNotificationOverlay->addNotification(
"Your system does not have hyprland-qtutils installed. This is a runtime dependency for some dialogs. Consider installing it.", CHyprColor{}, 15000, ICON_WARNING); "Your system does not have hyprland-qtutils installed. This is a runtime dependency for some dialogs. Consider installing it.", CHyprColor{}, 15000, ICON_WARNING);
} }
@@ -2673,7 +2654,6 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor
const bool FULLSCREEN = pWindow->isFullscreen(); const bool FULLSCREEN = pWindow->isFullscreen();
const auto FULLSCREENMODE = pWindow->m_sFullscreenState.internal; const auto FULLSCREENMODE = pWindow->m_sFullscreenState.internal;
const bool WASVISIBLE = pWindow->m_pWorkspace && pWindow->m_pWorkspace->isVisible();
if (FULLSCREEN) if (FULLSCREEN)
setWindowFullscreenInternal(pWindow, FSMODE_NONE); setWindowFullscreenInternal(pWindow, FSMODE_NONE);
@@ -2681,7 +2661,7 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor
const PHLWINDOW pFirstWindowOnWorkspace = pWorkspace->getFirstWindow(); const PHLWINDOW pFirstWindowOnWorkspace = pWorkspace->getFirstWindow();
const int visibleWindowsOnWorkspace = pWorkspace->getWindows(std::nullopt, true); const int visibleWindowsOnWorkspace = pWorkspace->getWindows(std::nullopt, true);
const auto PWINDOWMONITOR = pWindow->m_pMonitor.lock(); const auto PWINDOWMONITOR = pWindow->m_pMonitor.lock();
const auto POSTOMON = pWindow->m_vRealPosition->goal() - PWINDOWMONITOR->vecPosition; const auto POSTOMON = pWindow->m_vRealPosition.goal() - PWINDOWMONITOR->vecPosition;
const auto PWORKSPACEMONITOR = pWorkspace->m_pMonitor.lock(); const auto PWORKSPACEMONITOR = pWorkspace->m_pMonitor.lock();
if (!pWindow->m_bIsFloating) if (!pWindow->m_bIsFloating)
@@ -2711,14 +2691,14 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor
g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow); g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow);
if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) if (!pWindow->getDecorationByType(DECORATION_GROUPBAR))
pWindow->addWindowDeco(makeUnique<CHyprGroupBarDecoration>(pWindow)); pWindow->addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(pWindow));
} else { } else {
if (!pWindow->m_bIsFloating) if (!pWindow->m_bIsFloating)
g_pLayoutManager->getCurrentLayout()->onWindowCreatedTiling(pWindow); g_pLayoutManager->getCurrentLayout()->onWindowCreatedTiling(pWindow);
if (pWindow->m_bIsFloating) if (pWindow->m_bIsFloating)
*pWindow->m_vRealPosition = POSTOMON + PWORKSPACEMONITOR->vecPosition; pWindow->m_vRealPosition = POSTOMON + PWORKSPACEMONITOR->vecPosition;
} }
pWindow->updateToplevel(); pWindow->updateToplevel();
@@ -2741,11 +2721,6 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor
if (pWindow->m_pWorkspace) if (pWindow->m_pWorkspace)
pWindow->m_pWorkspace->updateWindows(); pWindow->m_pWorkspace->updateWindows();
g_pCompositor->updateSuspendedStates(); g_pCompositor->updateSuspendedStates();
if (!WASVISIBLE && pWindow->m_pWorkspace && pWindow->m_pWorkspace->isVisible()) {
pWindow->m_fMovingFromWorkspaceAlpha->setValueAndWarp(0.F);
*pWindow->m_fMovingFromWorkspaceAlpha = 1.F;
}
} }
PHLWINDOW CCompositor::getForceFocus() { PHLWINDOW CCompositor::getForceFocus() {
@@ -2765,9 +2740,11 @@ PHLWINDOW CCompositor::getForceFocus() {
void CCompositor::arrangeMonitors() { void CCompositor::arrangeMonitors() {
static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling"); static auto* const PXWLFORCESCALEZERO = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling");
std::vector<PHLMONITOR> toArrange(m_vMonitors.begin(), m_vMonitors.end()); std::vector<PHLMONITOR> toArrange;
std::vector<PHLMONITOR> arranged; std::vector<PHLMONITOR> arranged;
arranged.reserve(toArrange.size());
for (auto const& m : m_vMonitors)
toArrange.push_back(m);
Debug::log(LOG, "arrangeMonitors: {} to arrange", toArrange.size()); Debug::log(LOG, "arrangeMonitors: {} to arrange", toArrange.size());
@@ -2928,6 +2905,17 @@ void CCompositor::updateSuspendedStates() {
} }
} }
PHLWINDOW CCompositor::windowForCPointer(CWindow* pWindow) {
for (auto const& w : m_vWindows) {
if (w.get() != pWindow)
continue;
return w;
}
return {};
}
static void checkDefaultCursorWarp(PHLMONITOR monitor) { static void checkDefaultCursorWarp(PHLMONITOR monitor) {
static auto PCURSORMONITOR = CConfigValue<std::string>("cursor:default_monitor"); static auto PCURSORMONITOR = CConfigValue<std::string>("cursor:default_monitor");
static bool cursorDefaultDone = false; static bool cursorDefaultDone = false;
@@ -3005,65 +2993,4 @@ void CCompositor::onNewMonitor(SP<Aquamarine::IOutput> output) {
g_pHyprRenderer->damageMonitor(PNEWMONITOR); g_pHyprRenderer->damageMonitor(PNEWMONITOR);
PNEWMONITOR->onMonitorFrame(); PNEWMONITOR->onMonitorFrame();
if (PROTO::colorManagement && shouldChangePreferredImageDescription())
PROTO::colorManagement->onImagePreferredChanged();
}
SImageDescription CCompositor::getPreferredImageDescription() {
if (!PROTO::colorManagement) {
Debug::log(ERR, "FIXME: color management protocol is not enabled, returning empty image description");
return SImageDescription{};
}
Debug::log(WARN, "FIXME: color management protocol is enabled, determine correct preferred image description");
// should determine some common settings to avoid unnecessary transformations while keeping maximum displayable precision
return SImageDescription{.primaries = NColorPrimaries::BT709};
}
bool CCompositor::shouldChangePreferredImageDescription() {
Debug::log(WARN, "FIXME: color management protocol is enabled and outputs changed, check preferred image description changes");
return false;
}
void CCompositor::ensurePersistentWorkspacesPresent(const std::vector<SWorkspaceRule>& rules) {
for (const auto& rule : rules) {
if (!rule.isPersistent)
continue;
const auto PMONITOR = getMonitorFromString(rule.monitor);
if (!PMONITOR) {
Debug::log(ERR, "ensurePersistentWorkspacesPresent: couldn't resolve monitor for {}, skipping", rule.monitor);
continue;
}
WORKSPACEID id = rule.workspaceId;
std::string wsname = rule.workspaceName;
if (id == WORKSPACE_INVALID) {
const auto R = getWorkspaceIDNameFromString(rule.workspaceString);
id = R.id;
wsname = R.name;
}
if (id == WORKSPACE_INVALID) {
Debug::log(ERR, "ensurePersistentWorkspacesPresent: couldn't resolve id for workspace {}", rule.workspaceString);
continue;
}
if (const auto PWORKSPACE = getWorkspaceByID(id); PWORKSPACE) {
if (PWORKSPACE->m_pMonitor == PMONITOR) {
Debug::log(LOG, "ensurePersistentWorkspacesPresent: workspace persistent {} already on {}", rule.workspaceString, PMONITOR->szName);
continue;
}
Debug::log(LOG, "ensurePersistentWorkspacesPresent: workspace persistent {} not on {}, moving", rule.workspaceString, PMONITOR->szName);
moveWorkspaceToMonitor(PWORKSPACE, PMONITOR);
continue;
}
createNewWorkspace(id, PMONITOR ? PMONITOR : m_pLastMonitor.lock(), wsname, false);
}
// cleanup old
sanityCheckWorkspaces();
} }

View File

@@ -1,21 +1,38 @@
#pragma once #pragma once
#include <memory>
#include <list> #include <list>
#include <sys/resource.h> #include <sys/resource.h>
#include "defines.hpp" #include "defines.hpp"
#include "debug/Log.hpp"
#include "events/Events.hpp"
#include "config/ConfigManager.hpp"
#include "managers/ThreadManager.hpp"
#include "managers/XWaylandManager.hpp" #include "managers/XWaylandManager.hpp"
#include "managers/input/InputManager.hpp"
#include "managers/LayoutManager.hpp"
#include "managers/KeybindManager.hpp" #include "managers/KeybindManager.hpp"
#include "managers/AnimationManager.hpp"
#include "managers/EventManager.hpp"
#include "managers/ProtocolManager.hpp"
#include "managers/SessionLockManager.hpp" #include "managers/SessionLockManager.hpp"
#include "managers/HookSystemManager.hpp"
#include "debug/HyprDebugOverlay.hpp"
#include "debug/HyprNotificationOverlay.hpp"
#include "helpers/Monitor.hpp"
#include "desktop/Workspace.hpp"
#include "desktop/Window.hpp" #include "desktop/Window.hpp"
#include "protocols/types/ColorManagement.hpp" #include "render/Renderer.hpp"
#include "helpers/memory/Memory.hpp" #include "render/OpenGL.hpp"
#include "hyprerror/HyprError.hpp"
#include "plugins/PluginSystem.hpp"
#include "helpers/Watchdog.hpp"
#include <aquamarine/backend/Backend.hpp> #include <aquamarine/backend/Backend.hpp>
#include <aquamarine/output/Output.hpp> #include <aquamarine/output/Output.hpp>
class CWLSurfaceResource; class CWLSurfaceResource;
struct SWorkspaceRule;
enum eManagersInitStage : uint8_t { enum eManagersInitStage : uint8_t {
STAGE_PRIORITY = 0, STAGE_PRIORITY = 0,
@@ -25,7 +42,7 @@ enum eManagersInitStage : uint8_t {
class CCompositor { class CCompositor {
public: public:
CCompositor(bool onlyConfig = false); CCompositor();
~CCompositor(); ~CCompositor();
wl_display* m_sWLDisplay; wl_display* m_sWLDisplay;
@@ -72,11 +89,10 @@ class CCompositor {
bool m_bUnsafeState = false; // unsafe state is when there is no monitors. bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
bool m_bNextIsUnsafe = false; bool m_bNextIsUnsafe = false;
PHLMONITORREF m_pUnsafeOutput; // fallback output for the unsafe state PHLMONITORREF m_pUnsafeOutput; // fallback output for the unsafe state
bool m_bIsShuttingDown = false; bool m_bIsShuttingDown = false;
bool m_bFinalRequests = false; bool m_bFinalRequests = false;
bool m_bDesktopEnvSet = false; bool m_bDesktopEnvSet = false;
bool m_bWantsXwayland = true; bool m_bEnableXwayland = true;
bool m_bOnlyConfigVerification = false;
// ------------------------------------------------- // // ------------------------------------------------- //
@@ -107,9 +123,8 @@ class CCompositor {
void changeWindowZOrder(PHLWINDOW, bool); void changeWindowZOrder(PHLWINDOW, bool);
void cleanupFadingOut(const MONITORID& monid); void cleanupFadingOut(const MONITORID& monid);
PHLWINDOW getWindowInDirection(PHLWINDOW, char); PHLWINDOW getWindowInDirection(PHLWINDOW, char);
PHLWINDOW getWindowInDirection(const CBox& box, PHLWORKSPACE pWorkspace, char dir, PHLWINDOW ignoreWindow = nullptr, bool useVectorAngles = false); PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {}, bool visible = false); PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {});
PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {}, bool visible = false);
WORKSPACEID getNextAvailableNamedWorkspace(); WORKSPACEID getNextAvailableNamedWorkspace();
bool isPointOnAnyMonitor(const Vector2D&); bool isPointOnAnyMonitor(const Vector2D&);
bool isPointOnReservedArea(const Vector2D& point, const PHLMONITOR monitor = nullptr); bool isPointOnReservedArea(const Vector2D& point, const PHLMONITOR monitor = nullptr);
@@ -125,6 +140,7 @@ class CCompositor {
void setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE); void setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE);
void setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE); void setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE);
void setWindowFullscreenState(const PHLWINDOW PWINDOW, const SFullscreenState state); void setWindowFullscreenState(const PHLWINDOW PWINDOW, const SFullscreenState state);
void changeWindowFullscreenModeInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON);
void changeWindowFullscreenModeClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON); void changeWindowFullscreenModeClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE, const bool ON);
void updateFullscreenFadeOnWorkspace(PHLWORKSPACE); void updateFullscreenFadeOnWorkspace(PHLWORKSPACE);
PHLWINDOW getX11Parent(PHLWINDOW); PHLWINDOW getX11Parent(PHLWINDOW);
@@ -151,11 +167,8 @@ class CCompositor {
void setPreferredScaleForSurface(SP<CWLSurfaceResource> pSurface, double scale); void setPreferredScaleForSurface(SP<CWLSurfaceResource> pSurface, double scale);
void setPreferredTransformForSurface(SP<CWLSurfaceResource> pSurface, wl_output_transform transform); void setPreferredTransformForSurface(SP<CWLSurfaceResource> pSurface, wl_output_transform transform);
void updateSuspendedStates(); void updateSuspendedStates();
PHLWINDOW windowForCPointer(CWindow*);
void onNewMonitor(SP<Aquamarine::IOutput> output); void onNewMonitor(SP<Aquamarine::IOutput> output);
void ensurePersistentWorkspacesPresent(const std::vector<SWorkspaceRule>& rules);
SImageDescription getPreferredImageDescription();
bool shouldChangePreferredImageDescription();
std::string explicitConfigPath; std::string explicitConfigPath;
@@ -166,11 +179,10 @@ class CCompositor {
void setRandomSplash(); void setRandomSplash();
void initManagers(eManagersInitStage stage); void initManagers(eManagersInitStage stage);
void prepareFallbackOutput(); void prepareFallbackOutput();
bool isWindowAvailableForCycle(PHLWINDOW pWindow, PHLWINDOW w, bool focusableOnly, std::optional<bool> floating, bool anyWorkspace = false);
uint64_t m_iHyprlandPID = 0; uint64_t m_iHyprlandPID = 0;
wl_event_source* m_critSigSource = nullptr; wl_event_source* m_critSigSource = nullptr;
rlimit m_sOriginalNofile = {0}; rlimit m_sOriginalNofile = {0};
}; };
inline UP<CCompositor> g_pCompositor; inline std::unique_ptr<CCompositor> g_pCompositor;

View File

@@ -3,8 +3,6 @@
#include "helpers/math/Math.hpp" #include "helpers/math/Math.hpp"
#include <functional> #include <functional>
#include <any> #include <any>
#include <string>
#include <algorithm>
#include <hyprutils/math/Box.hpp> #include <hyprutils/math/Box.hpp>
enum eIcons : uint8_t { enum eIcons : uint8_t {
@@ -52,12 +50,6 @@ struct SHyprCtlCommand {
std::function<std::string(eHyprCtlOutputFormat, std::string)> fn; std::function<std::string(eHyprCtlOutputFormat, std::string)> fn;
}; };
struct SDispatchResult {
bool passEvent = false;
bool success = true;
std::string error;
};
typedef int64_t WINDOWID; typedef int64_t WINDOWID;
typedef int64_t MONITORID; typedef int64_t MONITORID;
typedef int64_t WORKSPACEID; typedef int64_t WORKSPACEID;

View File

@@ -139,12 +139,6 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.type = CONFIG_OPTION_INT, .type = CONFIG_OPTION_INT,
.data = SConfigOptionDescription::SRangeData{0, 0, 20}, .data = SConfigOptionDescription::SRangeData{0, 0, 20},
}, },
SConfigOptionDescription{
.value = "decoration:rounding_power",
.description = "rouding power of corners (2 is a circle)",
.type = CONFIG_OPTION_FLOAT,
.data = SConfigOptionDescription::SFloatData{2, 2, 10},
},
SConfigOptionDescription{ SConfigOptionDescription{
.value = "decoration:active_opacity", .value = "decoration:active_opacity",
.description = "opacity of active windows. [0.0 - 1.0]", .description = "opacity of active windows. [0.0 - 1.0]",
@@ -1295,30 +1289,6 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.type = CONFIG_OPTION_BOOL, .type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false}, .data = SConfigOptionDescription::SBoolData{false},
}, },
SConfigOptionDescription{
.value = "render:expand_undersized_textures",
.description = "Whether to expand textures that have not yet resized to be larger, or to just stretch them instead.",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true},
},
SConfigOptionDescription{
.value = "render:xp_mode",
.description = "Disable back buffer and bottom layer rendering.",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true},
},
SConfigOptionDescription{
.value = "render:ctm_animation",
.description = "Whether to enable a fade animation for CTM changes (hyprsunset). 2 means 'auto' (Yes on everything but Nvidia).",
.type = CONFIG_OPTION_INT,
.data = SConfigOptionDescription::SRangeData{2, 0, 2},
},
SConfigOptionDescription{
.value = "render:allow_early_buffer_release",
.description = "Allow early buffer release event. Fixes stuttering and missing frames for some apps. May cause graphical glitches and memory leaks in others",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true},
},
/* /*
* cursor: * cursor:
@@ -1633,16 +1603,10 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.data = SConfigOptionDescription::SBoolData{true}, .data = SConfigOptionDescription::SBoolData{true},
}, },
SConfigOptionDescription{ SConfigOptionDescription{
.value = "master:slave_count_for_center_master", .value = "master:always_center_master",
.description = "when using orientation=center, make the master window centered only when at least this many slave windows are open. (Set 0 to always_center_master)", .description = "when using orientation=center, keep the master window centered, even when it is the only window in the workspace.",
.type = CONFIG_OPTION_INT,
.data = SConfigOptionDescription::SRangeData{2, 0, 10}, //##TODO RANGE?
},
SConfigOptionDescription{
.value = "master:center_master_slaves_on_right",
.description = "set if the slaves should appear on right of master when slave_count_for_center_master > 2",
.type = CONFIG_OPTION_BOOL, .type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true}, .data = SConfigOptionDescription::SBoolData{false},
}, },
SConfigOptionDescription{ SConfigOptionDescription{
.value = "master:center_ignores_reserved", .value = "master:center_ignores_reserved",
@@ -1664,22 +1628,4 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.type = CONFIG_OPTION_BOOL, .type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true}, .data = SConfigOptionDescription::SBoolData{true},
}, },
SConfigOptionDescription{
.value = "experimental:wide_color_gamut",
.description = "force wide color gamut for all supported outputs",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "experimental:hdr",
.description = "force static hdr for all supported outputs",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "experimental:xx_color_management_v4",
.description = "enable color management protocol",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
}; };

View File

@@ -1,7 +1,6 @@
#include <re2/re2.h> #include <re2/re2.h>
#include "ConfigManager.hpp" #include "ConfigManager.hpp"
#include "ConfigWatcher.hpp"
#include "../managers/KeybindManager.hpp" #include "../managers/KeybindManager.hpp"
#include "../Compositor.hpp" #include "../Compositor.hpp"
@@ -12,20 +11,7 @@
#include "../protocols/LayerShell.hpp" #include "../protocols/LayerShell.hpp"
#include "../xwayland/XWayland.hpp" #include "../xwayland/XWayland.hpp"
#include "../protocols/OutputManagement.hpp" #include "../protocols/OutputManagement.hpp"
#include "../managers/AnimationManager.hpp"
#include "../desktop/LayerSurface.hpp"
#include "defaultConfig.hpp"
#include "../render/Renderer.hpp"
#include "../hyprerror/HyprError.hpp"
#include "../managers/input/InputManager.hpp"
#include "../managers/eventLoop/EventLoopManager.hpp"
#include "../managers/LayoutManager.hpp"
#include "../managers/EventManager.hpp"
#include "../debug/HyprNotificationOverlay.hpp"
#include "../plugins/PluginSystem.hpp"
#include "managers/HookSystemManager.hpp"
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <hyprutils/path/Path.hpp> #include <hyprutils/path/Path.hpp>
@@ -45,9 +31,7 @@
#include <unordered_set> #include <unordered_set>
#include <hyprutils/string/String.hpp> #include <hyprutils/string/String.hpp>
#include <filesystem> #include <filesystem>
#include <memory>
using namespace Hyprutils::String; using namespace Hyprutils::String;
using namespace Hyprutils::Animation;
//NOLINTNEXTLINE //NOLINTNEXTLINE
extern "C" char** environ; extern "C" char** environ;
@@ -144,18 +128,6 @@ static void configHandleGapDestroy(void** data) {
delete reinterpret_cast<CCssGapData*>(*data); delete reinterpret_cast<CCssGapData*>(*data);
} }
static Hyprlang::CParseResult handleExec(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;
const auto RESULT = g_pConfigManager->handleExec(COMMAND, VALUE);
Hyprlang::CParseResult result;
if (RESULT.has_value())
result.setError(RESULT.value().c_str());
return result;
}
static Hyprlang::CParseResult handleRawExec(const char* c, const char* v) { static Hyprlang::CParseResult handleRawExec(const char* c, const char* v) {
const std::string VALUE = v; const std::string VALUE = v;
const std::string COMMAND = c; const std::string COMMAND = c;
@@ -180,18 +152,6 @@ static Hyprlang::CParseResult handleExecOnce(const char* c, const char* v) {
return result; return result;
} }
static Hyprlang::CParseResult handleExecRawOnce(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;
const auto RESULT = g_pConfigManager->handleExecRawOnce(COMMAND, VALUE);
Hyprlang::CParseResult result;
if (RESULT.has_value())
result.setError(RESULT.value().c_str());
return result;
}
static Hyprlang::CParseResult handleExecShutdown(const char* c, const char* v) { static Hyprlang::CParseResult handleExecShutdown(const char* c, const char* v) {
const std::string VALUE = v; const std::string VALUE = v;
const std::string COMMAND = c; const std::string COMMAND = c;
@@ -375,8 +335,8 @@ static Hyprlang::CParseResult handlePlugin(const char* c, const char* v) {
CConfigManager::CConfigManager() { CConfigManager::CConfigManager() {
const auto ERR = verifyConfigExists(); const auto ERR = verifyConfigExists();
m_configPaths.emplace_back(getMainConfigPath()); configPaths.emplace_back(getMainConfigPath());
m_pConfig = makeUnique<Hyprlang::CConfig>(m_configPaths.begin()->c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true}); m_pConfig = std::make_unique<Hyprlang::CConfig>(configPaths.begin()->c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true});
m_pConfig->addConfigValue("general:border_size", Hyprlang::INT{1}); m_pConfig->addConfigValue("general:border_size", Hyprlang::INT{1});
m_pConfig->addConfigValue("general:no_border_on_floating", Hyprlang::INT{0}); m_pConfig->addConfigValue("general:no_border_on_floating", Hyprlang::INT{0});
@@ -453,7 +413,6 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("debug:log_damage", Hyprlang::INT{0}); m_pConfig->addConfigValue("debug:log_damage", Hyprlang::INT{0});
m_pConfig->addConfigValue("debug:overlay", Hyprlang::INT{0}); m_pConfig->addConfigValue("debug:overlay", Hyprlang::INT{0});
m_pConfig->addConfigValue("debug:damage_blink", Hyprlang::INT{0}); m_pConfig->addConfigValue("debug:damage_blink", Hyprlang::INT{0});
m_pConfig->addConfigValue("debug:pass", Hyprlang::INT{0});
m_pConfig->addConfigValue("debug:disable_logs", Hyprlang::INT{1}); m_pConfig->addConfigValue("debug:disable_logs", Hyprlang::INT{1});
m_pConfig->addConfigValue("debug:disable_time", Hyprlang::INT{1}); m_pConfig->addConfigValue("debug:disable_time", Hyprlang::INT{1});
m_pConfig->addConfigValue("debug:enable_stdout_logs", Hyprlang::INT{0}); m_pConfig->addConfigValue("debug:enable_stdout_logs", Hyprlang::INT{0});
@@ -467,7 +426,6 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("debug:colored_stdout_logs", Hyprlang::INT{1}); m_pConfig->addConfigValue("debug:colored_stdout_logs", Hyprlang::INT{1});
m_pConfig->addConfigValue("decoration:rounding", Hyprlang::INT{0}); m_pConfig->addConfigValue("decoration:rounding", Hyprlang::INT{0});
m_pConfig->addConfigValue("decoration:rounding_power", {2.F});
m_pConfig->addConfigValue("decoration:blur:enabled", Hyprlang::INT{1}); m_pConfig->addConfigValue("decoration:blur:enabled", Hyprlang::INT{1});
m_pConfig->addConfigValue("decoration:blur:size", Hyprlang::INT{8}); m_pConfig->addConfigValue("decoration:blur:size", Hyprlang::INT{8});
m_pConfig->addConfigValue("decoration:blur:passes", Hyprlang::INT{1}); m_pConfig->addConfigValue("decoration:blur:passes", Hyprlang::INT{1});
@@ -518,8 +476,7 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("master:special_scale_factor", {1.f}); m_pConfig->addConfigValue("master:special_scale_factor", {1.f});
m_pConfig->addConfigValue("master:mfact", {0.55f}); m_pConfig->addConfigValue("master:mfact", {0.55f});
m_pConfig->addConfigValue("master:new_status", {"slave"}); m_pConfig->addConfigValue("master:new_status", {"slave"});
m_pConfig->addConfigValue("master:slave_count_for_center_master", Hyprlang::INT{2}); m_pConfig->addConfigValue("master:always_center_master", Hyprlang::INT{0});
m_pConfig->addConfigValue("master:center_master_slaves_on_right", Hyprlang::INT{1});
m_pConfig->addConfigValue("master:center_ignores_reserved", Hyprlang::INT{0}); m_pConfig->addConfigValue("master:center_ignores_reserved", Hyprlang::INT{0});
m_pConfig->addConfigValue("master:new_on_active", {"none"}); m_pConfig->addConfigValue("master:new_on_active", {"none"});
m_pConfig->addConfigValue("master:new_on_top", Hyprlang::INT{0}); m_pConfig->addConfigValue("master:new_on_top", Hyprlang::INT{0});
@@ -614,9 +571,9 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("xwayland:force_zero_scaling", Hyprlang::INT{0}); m_pConfig->addConfigValue("xwayland:force_zero_scaling", Hyprlang::INT{0});
m_pConfig->addConfigValue("opengl:nvidia_anti_flicker", Hyprlang::INT{1}); m_pConfig->addConfigValue("opengl:nvidia_anti_flicker", Hyprlang::INT{1});
m_pConfig->addConfigValue("opengl:force_introspection", Hyprlang::INT{1}); // TODO: remove this. I don't think it does us any good to disable intro. m_pConfig->addConfigValue("opengl:force_introspection", Hyprlang::INT{2});
m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:no_hardware_cursors", Hyprlang::INT{2});
m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:no_break_fs_vrr", Hyprlang::INT{0});
m_pConfig->addConfigValue("cursor:min_refresh_rate", Hyprlang::INT{24}); m_pConfig->addConfigValue("cursor:min_refresh_rate", Hyprlang::INT{24});
m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:hotspot_padding", Hyprlang::INT{0});
@@ -631,7 +588,7 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("cursor:sync_gsettings_theme", Hyprlang::INT{1}); m_pConfig->addConfigValue("cursor:sync_gsettings_theme", Hyprlang::INT{1});
m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:hide_on_key_press", Hyprlang::INT{0});
m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1}); m_pConfig->addConfigValue("cursor:hide_on_touch", Hyprlang::INT{1});
m_pConfig->addConfigValue("cursor:use_cpu_buffer", Hyprlang::INT{2}); m_pConfig->addConfigValue("cursor:use_cpu_buffer", Hyprlang::INT{0});
m_pConfig->addConfigValue("cursor:warp_back_after_non_mouse_input", Hyprlang::INT{0}); m_pConfig->addConfigValue("cursor:warp_back_after_non_mouse_input", Hyprlang::INT{0});
m_pConfig->addConfigValue("autogenerated", Hyprlang::INT{0}); m_pConfig->addConfigValue("autogenerated", Hyprlang::INT{0});
@@ -655,16 +612,8 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("render:explicit_sync_kms", Hyprlang::INT{2}); m_pConfig->addConfigValue("render:explicit_sync_kms", Hyprlang::INT{2});
m_pConfig->addConfigValue("render:direct_scanout", Hyprlang::INT{0}); m_pConfig->addConfigValue("render:direct_scanout", Hyprlang::INT{0});
m_pConfig->addConfigValue("render:expand_undersized_textures", Hyprlang::INT{1}); m_pConfig->addConfigValue("render:expand_undersized_textures", Hyprlang::INT{1});
m_pConfig->addConfigValue("render:xp_mode", Hyprlang::INT{0});
m_pConfig->addConfigValue("render:ctm_animation", Hyprlang::INT{2});
m_pConfig->addConfigValue("render:allow_early_buffer_release", Hyprlang::INT{1});
m_pConfig->addConfigValue("ecosystem:no_update_news", Hyprlang::INT{0}); m_pConfig->addConfigValue("ecosystem:no_update_news", Hyprlang::INT{0});
m_pConfig->addConfigValue("ecosystem:no_donation_nag", Hyprlang::INT{0});
m_pConfig->addConfigValue("experimental:wide_color_gamut", Hyprlang::INT{0});
m_pConfig->addConfigValue("experimental:hdr", Hyprlang::INT{0});
m_pConfig->addConfigValue("experimental:xx_color_management_v4", Hyprlang::INT{0});
// devices // devices
m_pConfig->addSpecialCategory("device", {"name"}); m_pConfig->addSpecialCategory("device", {"name"});
@@ -704,10 +653,8 @@ CConfigManager::CConfigManager() {
m_pConfig->addSpecialConfigValue("device", "active_area_size", Hyprlang::VEC2{0, 0}); // only for tablets m_pConfig->addSpecialConfigValue("device", "active_area_size", Hyprlang::VEC2{0, 0}); // only for tablets
// keywords // keywords
m_pConfig->registerHandler(&::handleExec, "exec", {false}); m_pConfig->registerHandler(&::handleRawExec, "exec", {false});
m_pConfig->registerHandler(&::handleRawExec, "execr", {false});
m_pConfig->registerHandler(&::handleExecOnce, "exec-once", {false}); m_pConfig->registerHandler(&::handleExecOnce, "exec-once", {false});
m_pConfig->registerHandler(&::handleExecRawOnce, "execr-once", {false});
m_pConfig->registerHandler(&::handleExecShutdown, "exec-shutdown", {false}); m_pConfig->registerHandler(&::handleExecShutdown, "exec-shutdown", {false});
m_pConfig->registerHandler(&::handleMonitor, "monitor", {false}); m_pConfig->registerHandler(&::handleMonitor, "monitor", {false});
m_pConfig->registerHandler(&::handleBind, "bind", {true}); m_pConfig->registerHandler(&::handleBind, "bind", {true});
@@ -729,20 +676,18 @@ CConfigManager::CConfigManager() {
m_pConfig->commence(); m_pConfig->commence();
setDefaultAnimationVars();
resetHLConfig(); resetHLConfig();
if (!g_pCompositor->m_bOnlyConfigVerification) { Debug::log(INFO,
Debug::log( "!!!!HEY YOU, YES YOU!!!!: further logs to stdout / logfile are disabled by default. BEFORE SENDING THIS LOG, ENABLE THEM. Use debug:disable_logs = false to do so: "
INFO, "https://wiki.hyprland.org/Configuring/Variables/#debug");
"!!!!HEY YOU, YES YOU!!!!: further logs to stdout / logfile are disabled by default. BEFORE SENDING THIS LOG, ENABLE THEM. Use debug:disable_logs = false to do so: "
"https://wiki.hyprland.org/Configuring/Variables/#debug");
}
Debug::disableLogs = reinterpret_cast<int64_t* const*>(m_pConfig->getConfigValuePtr("debug:disable_logs")->getDataStaticPtr()); Debug::disableLogs = reinterpret_cast<int64_t* const*>(m_pConfig->getConfigValuePtr("debug:disable_logs")->getDataStaticPtr());
Debug::disableTime = reinterpret_cast<int64_t* const*>(m_pConfig->getConfigValuePtr("debug:disable_time")->getDataStaticPtr()); Debug::disableTime = reinterpret_cast<int64_t* const*>(m_pConfig->getConfigValuePtr("debug:disable_time")->getDataStaticPtr());
if (g_pEventLoopManager && ERR.has_value()) if (ERR.has_value())
g_pEventLoopManager->doLater([ERR] { g_pHyprError->queueCreate(ERR.value(), CHyprColor{1.0, 0.1, 0.1, 1.0}); }); g_pHyprError->queueCreate(ERR.value(), CHyprColor{1.0, 0.1, 0.1, 1.0});
} }
std::optional<std::string> CConfigManager::generateConfig(std::string configPath) { std::optional<std::string> CConfigManager::generateConfig(std::string configPath) {
@@ -768,24 +713,20 @@ std::optional<std::string> CConfigManager::generateConfig(std::string configPath
} }
std::string CConfigManager::getMainConfigPath() { std::string CConfigManager::getMainConfigPath() {
static std::string CONFIG_PATH = [this]() -> std::string { if (!g_pCompositor->explicitConfigPath.empty())
if (!g_pCompositor->explicitConfigPath.empty()) return g_pCompositor->explicitConfigPath;
return g_pCompositor->explicitConfigPath;
if (const auto CFG_ENV = getenv("HYPRLAND_CONFIG"); CFG_ENV) if (const auto CFG_ENV = getenv("HYPRLAND_CONFIG"); CFG_ENV)
return CFG_ENV; return CFG_ENV;
const auto PATHS = Hyprutils::Path::findConfig(ISDEBUG ? "hyprlandd" : "hyprland"); const auto PATHS = Hyprutils::Path::findConfig(ISDEBUG ? "hyprlandd" : "hyprland");
if (PATHS.first.has_value()) { if (PATHS.first.has_value()) {
return PATHS.first.value(); return PATHS.first.value();
} else if (PATHS.second.has_value()) { } else if (PATHS.second.has_value()) {
const auto CONFIGPATH = Hyprutils::Path::fullConfigPath(PATHS.second.value(), ISDEBUG ? "hyprlandd" : "hyprland"); const auto CONFIGPATH = Hyprutils::Path::fullConfigPath(PATHS.second.value(), ISDEBUG ? "hyprlandd" : "hyprland");
return generateConfig(CONFIGPATH).value(); return generateConfig(CONFIGPATH).value();
} else } else
throw std::runtime_error("Neither HOME nor XDG_CONFIG_HOME are set in the environment. Could not find config in XDG_CONFIG_DIRS or /etc/xdg."); throw std::runtime_error("Neither HOME nor XDG_CONFIG_HOME are set in the environment. Could not find config in XDG_CONFIG_DIRS or /etc/xdg.");
}();
return CONFIG_PATH;
} }
std::optional<std::string> CConfigManager::verifyConfigExists() { std::optional<std::string> CConfigManager::verifyConfigExists() {
@@ -801,7 +742,7 @@ std::string CConfigManager::getConfigString() {
std::string configString; std::string configString;
std::string currFileContent; std::string currFileContent;
for (const auto& path : m_configPaths) { for (const auto& path : configPaths) {
std::ifstream configFile(path); std::ifstream configFile(path);
configString += ("\n\nConfig File: " + path + ": "); configString += ("\n\nConfig File: " + path + ": ");
if (!configFile.is_open()) { if (!configFile.is_open()) {
@@ -824,65 +765,78 @@ void CConfigManager::reload() {
EMIT_HOOK_EVENT("preConfigReload", nullptr); EMIT_HOOK_EVENT("preConfigReload", nullptr);
setDefaultAnimationVars(); setDefaultAnimationVars();
resetHLConfig(); resetHLConfig();
configCurrentPath = getMainConfigPath(); configCurrentPath = getMainConfigPath();
const auto ERR = m_pConfig->parse(); const auto ERR = m_pConfig->parse();
m_bLastConfigVerificationWasSuccessful = !ERR.error;
postConfigReload(ERR); postConfigReload(ERR);
} }
std::string CConfigManager::verify() {
setDefaultAnimationVars();
resetHLConfig();
configCurrentPath = getMainConfigPath();
const auto ERR = m_pConfig->parse();
m_bLastConfigVerificationWasSuccessful = !ERR.error;
if (ERR.error)
return ERR.getError();
return "config ok";
}
void CConfigManager::setDefaultAnimationVars() { void CConfigManager::setDefaultAnimationVars() {
m_AnimationTree.createNode("__internal_fadeCTM"); if (isFirstLaunch) {
m_AnimationTree.createNode("global"); INITANIMCFG("global");
INITANIMCFG("windows");
INITANIMCFG("layers");
INITANIMCFG("fade");
INITANIMCFG("border");
INITANIMCFG("borderangle");
// global // windows
m_AnimationTree.createNode("windows", "global"); INITANIMCFG("windowsIn");
m_AnimationTree.createNode("layers", "global"); INITANIMCFG("windowsOut");
m_AnimationTree.createNode("fade", "global"); INITANIMCFG("windowsMove");
m_AnimationTree.createNode("border", "global");
m_AnimationTree.createNode("borderangle", "global");
m_AnimationTree.createNode("workspaces", "global");
// layer // layers
m_AnimationTree.createNode("layersIn", "layers"); INITANIMCFG("layersIn");
m_AnimationTree.createNode("layersOut", "layers"); INITANIMCFG("layersOut");
// windows // fade
m_AnimationTree.createNode("windowsIn", "windows"); INITANIMCFG("fadeIn");
m_AnimationTree.createNode("windowsOut", "windows"); INITANIMCFG("fadeOut");
m_AnimationTree.createNode("windowsMove", "windows"); INITANIMCFG("fadeSwitch");
INITANIMCFG("fadeShadow");
INITANIMCFG("fadeDim");
// fade // border
m_AnimationTree.createNode("fadeIn", "fade");
m_AnimationTree.createNode("fadeOut", "fade");
m_AnimationTree.createNode("fadeSwitch", "fade");
m_AnimationTree.createNode("fadeShadow", "fade");
m_AnimationTree.createNode("fadeDim", "fade");
m_AnimationTree.createNode("fadeLayers", "fade");
m_AnimationTree.createNode("fadeLayersIn", "fadeLayers");
m_AnimationTree.createNode("fadeLayersOut", "fadeLayers");
// workspaces // workspaces
m_AnimationTree.createNode("workspacesIn", "workspaces"); INITANIMCFG("workspaces");
m_AnimationTree.createNode("workspacesOut", "workspaces"); INITANIMCFG("workspacesIn");
m_AnimationTree.createNode("specialWorkspace", "workspaces"); INITANIMCFG("workspacesOut");
m_AnimationTree.createNode("specialWorkspaceIn", "specialWorkspace"); INITANIMCFG("specialWorkspace");
m_AnimationTree.createNode("specialWorkspaceOut", "specialWorkspace"); INITANIMCFG("specialWorkspaceIn");
INITANIMCFG("specialWorkspaceOut");
}
// init the root nodes // init the values
m_AnimationTree.setConfigForNode("global", 1, 8.f, "", "default"); animationConfig["global"] = {false, "default", "", 8.f, 1, &animationConfig["general"], nullptr};
m_AnimationTree.setConfigForNode("__internal_fadeCTM", 1, 5.f, "", "linear");
m_AnimationTree.setConfigForNode("borderangle", 0, 0.f, "", "default"); CREATEANIMCFG("windows", "global");
CREATEANIMCFG("layers", "global");
CREATEANIMCFG("fade", "global");
CREATEANIMCFG("border", "global");
CREATEANIMCFG("borderangle", "global");
CREATEANIMCFG("workspaces", "global");
CREATEANIMCFG("layersIn", "layers");
CREATEANIMCFG("layersOut", "layers");
CREATEANIMCFG("windowsIn", "windows");
CREATEANIMCFG("windowsOut", "windows");
CREATEANIMCFG("windowsMove", "windows");
CREATEANIMCFG("fadeIn", "fade");
CREATEANIMCFG("fadeOut", "fade");
CREATEANIMCFG("fadeSwitch", "fade");
CREATEANIMCFG("fadeShadow", "fade");
CREATEANIMCFG("fadeDim", "fade");
CREATEANIMCFG("fadeLayers", "fade");
CREATEANIMCFG("fadeLayersIn", "fadeLayers");
CREATEANIMCFG("fadeLayersOut", "fadeLayers");
CREATEANIMCFG("workspacesIn", "workspaces");
CREATEANIMCFG("workspacesOut", "workspaces");
CREATEANIMCFG("specialWorkspace", "workspaces");
CREATEANIMCFG("specialWorkspaceIn", "specialWorkspace");
CREATEANIMCFG("specialWorkspaceOut", "specialWorkspace");
} }
std::optional<std::string> CConfigManager::resetHLConfig() { std::optional<std::string> CConfigManager::resetHLConfig() {
@@ -890,8 +844,6 @@ std::optional<std::string> CConfigManager::resetHLConfig() {
m_vWindowRules.clear(); m_vWindowRules.clear();
g_pKeybindManager->clearKeybinds(); g_pKeybindManager->clearKeybinds();
g_pAnimationManager->removeAllBeziers(); g_pAnimationManager->removeAllBeziers();
g_pAnimationManager->addBezierWithName("linear", Vector2D(0.0, 0.0), Vector2D(1.0, 1.0));
m_mAdditionalReservedAreas.clear(); m_mAdditionalReservedAreas.clear();
m_dBlurLSNamespaces.clear(); m_dBlurLSNamespaces.clear();
m_vWorkspaceRules.clear(); m_vWorkspaceRules.clear();
@@ -902,27 +854,20 @@ std::optional<std::string> CConfigManager::resetHLConfig() {
finalExecRequests.clear(); finalExecRequests.clear();
// paths // paths
m_configPaths.clear(); configPaths.clear();
std::string mainConfigPath = getMainConfigPath(); std::string mainConfigPath = getMainConfigPath();
Debug::log(LOG, "Using config: {}", mainConfigPath); Debug::log(LOG, "Using config: {}", mainConfigPath);
m_configPaths.emplace_back(mainConfigPath); configPaths.push_back(mainConfigPath);
const auto RET = verifyConfigExists(); const auto RET = verifyConfigExists();
return RET; return RET;
} }
void CConfigManager::updateWatcher() {
static const auto PDISABLEAUTORELOAD = CConfigValue<Hyprlang::INT>("misc:disable_autoreload");
g_pConfigWatcher->setWatchList(*PDISABLEAUTORELOAD ? std::vector<std::string>{} : m_configPaths);
}
void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) { void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
static const auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("render:explicit_sync"); static const auto PENABLEEXPLICIT = CConfigValue<Hyprlang::INT>("render:explicit_sync");
static int prevEnabledExplicit = *PENABLEEXPLICIT; static int prevEnabledExplicit = *PENABLEEXPLICIT;
updateWatcher();
for (auto const& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
w->uncacheWindowDecos(); w->uncacheWindowDecos();
} }
@@ -936,12 +881,11 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
g_pInputManager->setPointerConfigs(); g_pInputManager->setPointerConfigs();
g_pInputManager->setTouchDeviceConfigs(); g_pInputManager->setTouchDeviceConfigs();
g_pInputManager->setTabletConfigs(); g_pInputManager->setTabletConfigs();
g_pHyprOpenGL->m_bReloadScreenShader = true;
g_pHyprOpenGL->ensureBackgroundTexturePresence();
} }
if (!isFirstLaunch)
g_pHyprOpenGL->m_bReloadScreenShader = true;
// parseError will be displayed next frame // parseError will be displayed next frame
if (result.error) if (result.error)
@@ -953,7 +897,7 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
g_pHyprError->queueCreate(result.getError(), CHyprColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0)); g_pHyprError->queueCreate(result.getError(), CHyprColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
else if (std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("autogenerated")) == 1) else if (std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("autogenerated")) == 1)
g_pHyprError->queueCreate( g_pHyprError->queueCreate(
"Warning: You're using an autogenerated config! Edit the config file to get rid of this message. (config file: " + getMainConfigPath() + "Warning: You're using an autogenerated config! (config file: " + getMainConfigPath() +
" )\nSUPER+Q -> kitty (if it doesn't launch, make sure it's installed or choose a different terminal in the config)\nSUPER+M -> exit Hyprland", " )\nSUPER+Q -> kitty (if it doesn't launch, make sure it's installed or choose a different terminal in the config)\nSUPER+M -> exit Hyprland",
CHyprColor(1.0, 1.0, 70.0 / 255.0, 1.0)); CHyprColor(1.0, 1.0, 70.0 / 255.0, 1.0));
else if (*PENABLEEXPLICIT != prevEnabledExplicit) else if (*PENABLEEXPLICIT != prevEnabledExplicit)
@@ -973,16 +917,26 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
} }
#ifndef NO_XWAYLAND #ifndef NO_XWAYLAND
const auto PENABLEXWAYLAND = std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("xwayland:enabled")); const auto PENABLEXWAYLAND = std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("xwayland:enabled"));
g_pCompositor->m_bWantsXwayland = PENABLEXWAYLAND;
// enable/disable xwayland usage // enable/disable xwayland usage
if (!isFirstLaunch && if (!isFirstLaunch) {
g_pXWayland /* XWayland has to be initialized by CCompositor::initManagers for this to make sense, and it doesn't have to be (e.g. very early plugin load) */) { bool prevEnabledXwayland = g_pCompositor->m_bEnableXwayland;
bool prevEnabledXwayland = g_pXWayland->enabled(); if (PENABLEXWAYLAND != prevEnabledXwayland) {
if (g_pCompositor->m_bWantsXwayland != prevEnabledXwayland) g_pCompositor->m_bEnableXwayland = PENABLEXWAYLAND;
g_pXWayland = makeUnique<CXWayland>(g_pCompositor->m_bWantsXwayland); if (PENABLEXWAYLAND) {
Debug::log(LOG, "xwayland has been enabled");
} else {
Debug::log(LOG, "xwayland has been disabled, cleaning up...");
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_pXDGSurface || !w->m_bIsX11)
continue;
g_pCompositor->closeWindow(w);
}
}
g_pXWayland = std::make_unique<CXWayland>(g_pCompositor->m_bEnableXwayland);
}
} else } else
g_pCompositor->m_bWantsXwayland = PENABLEXWAYLAND; g_pCompositor->m_bEnableXwayland = PENABLEXWAYLAND;
#endif #endif
if (!isFirstLaunch && !g_pCompositor->m_bUnsafeState) if (!isFirstLaunch && !g_pCompositor->m_bUnsafeState)
@@ -1038,10 +992,6 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
// update plugins // update plugins
handlePluginLoads(); handlePluginLoads();
// update persistent workspaces
if (!isFirstLaunch)
ensurePersistentWorkspacesPresent();
EMIT_HOOK_EVENT("configReloaded", nullptr); EMIT_HOOK_EVENT("configReloaded", nullptr);
if (g_pEventManager) if (g_pEventManager)
g_pEventManager->postEvent(SHyprIPCEvent{"configreloaded", ""}); g_pEventManager->postEvent(SHyprIPCEvent{"configreloaded", ""});
@@ -1049,14 +999,17 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
void CConfigManager::init() { void CConfigManager::init() {
g_pConfigWatcher->setOnChange([this](const CConfigWatcher::SConfigWatchEvent& e) {
Debug::log(LOG, "CConfigManager: file {} modified, reloading", e.file);
reload();
});
const std::string CONFIGPATH = getMainConfigPath(); const std::string CONFIGPATH = getMainConfigPath();
reload(); reload();
struct stat fileStat;
int err = stat(CONFIGPATH.c_str(), &fileStat);
if (err != 0) {
Debug::log(WARN, "Error at statting config, error {}", errno);
}
configModifyTimes[CONFIGPATH] = fileStat.st_mtime;
isFirstLaunch = false; isFirstLaunch = false;
} }
@@ -1097,6 +1050,37 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std::
return RET.error ? RET.getError() : ""; return RET.error ? RET.getError() : "";
} }
void CConfigManager::tick() {
std::string CONFIGPATH = getMainConfigPath();
if (!std::filesystem::exists(CONFIGPATH)) {
Debug::log(ERR, "Config doesn't exist??");
return;
}
bool parse = false;
for (auto const& cf : configPaths) {
struct stat fileStat;
int err = stat(cf.c_str(), &fileStat);
if (err != 0) {
Debug::log(WARN, "Error at ticking config at {}, error {}: {}", cf, err, strerror(err));
continue;
}
// check if we need to reload cfg
if (fileStat.st_mtime != configModifyTimes[cf] || m_bForceReload) {
parse = true;
configModifyTimes[cf] = fileStat.st_mtime;
}
}
if (parse) {
m_bForceReload = false;
reload();
}
}
Hyprlang::CConfigValue* CConfigManager::getConfigValueSafeDevice(const std::string& dev, const std::string& val, const std::string& fallback) { Hyprlang::CConfigValue* CConfigManager::getConfigValueSafeDevice(const std::string& dev, const std::string& val, const std::string& fallback) {
const auto VAL = m_pConfig->getSpecialConfigValuePtr("device", val.c_str(), dev.c_str()); const auto VAL = m_pConfig->getSpecialConfigValuePtr("device", val.c_str(), dev.c_str());
@@ -1274,10 +1258,10 @@ std::vector<SP<CWindowRule>> CConfigManager::getMatchingRules(PHLWINDOW pWindow,
if (rule->szValue.starts_with("tag:") && !tags.isTagged(rule->szValue.substr(4))) if (rule->szValue.starts_with("tag:") && !tags.isTagged(rule->szValue.substr(4)))
continue; continue;
if (rule->szValue.starts_with("title:") && !rule->rV1Regex.passes(pWindow->m_szTitle)) if (rule->szValue.starts_with("title:") && !RE2::FullMatch(pWindow->m_szTitle, rule->szValue.substr(6)))
continue; continue;
if (!rule->rV1Regex.passes(pWindow->m_szClass)) if (!RE2::FullMatch(pWindow->m_szClass, rule->szValue))
continue; continue;
} catch (...) { } catch (...) {
@@ -1367,16 +1351,16 @@ std::vector<SP<CWindowRule>> CConfigManager::getMatchingRules(PHLWINDOW pWindow,
if (!rule->szTag.empty() && !tags.isTagged(rule->szTag)) if (!rule->szTag.empty() && !tags.isTagged(rule->szTag))
continue; continue;
if (!rule->szClass.empty() && !rule->rClass.passes(pWindow->m_szClass)) if (!rule->szClass.empty() && !RE2::FullMatch(pWindow->m_szClass, rule->szClass))
continue; continue;
if (!rule->szTitle.empty() && !rule->rTitle.passes(pWindow->m_szTitle)) if (!rule->szTitle.empty() && !RE2::FullMatch(pWindow->m_szTitle, rule->szTitle))
continue; continue;
if (!rule->szInitialTitle.empty() && !rule->rInitialTitle.passes(pWindow->m_szInitialTitle)) if (!rule->szInitialTitle.empty() && !RE2::FullMatch(pWindow->m_szInitialTitle, rule->szInitialTitle))
continue; continue;
if (!rule->szInitialClass.empty() && !rule->rInitialClass.passes(pWindow->m_szInitialClass)) if (!rule->szInitialClass.empty() && !RE2::FullMatch(pWindow->m_szInitialClass, rule->szInitialClass))
continue; continue;
} catch (std::exception& e) { } catch (std::exception& e) {
@@ -1435,7 +1419,7 @@ std::vector<SP<CLayerRule>> CConfigManager::getMatchingRules(PHLLS pLS) {
if (lr->targetNamespace.starts_with("address:0x")) { if (lr->targetNamespace.starts_with("address:0x")) {
if (std::format("address:0x{:x}", (uintptr_t)pLS.get()) != lr->targetNamespace) if (std::format("address:0x{:x}", (uintptr_t)pLS.get()) != lr->targetNamespace)
continue; continue;
} else if (!lr->targetNamespaceRegex.passes(pLS->layerSurface->layerNamespace)) } else if (!RE2::FullMatch(pLS->layerSurface->layerNamespace, lr->targetNamespace))
continue; continue;
// hit // hit
@@ -1465,7 +1449,7 @@ void CConfigManager::dispatchExecOnce() {
isLaunchingExecOnce = true; isLaunchingExecOnce = true;
for (auto const& c : firstExecRequests) { for (auto const& c : firstExecRequests) {
c.withRules ? handleExec("", c.exec) : handleRawExec("", c.exec); handleRawExec("", c);
} }
firstExecRequests.clear(); // free some kb of memory :P firstExecRequests.clear(); // free some kb of memory :P
@@ -1499,6 +1483,22 @@ void CConfigManager::dispatchExecShutdown() {
handleExecShutdown("", "hyprctl dispatch exit"); handleExecShutdown("", "hyprctl dispatch exit");
} }
void CConfigManager::appendMonitorRule(const SMonitorRule& r) {
m_vMonitorRules.emplace_back(r);
}
bool CConfigManager::replaceMonitorRule(const SMonitorRule& newrule) {
// Looks for an existing monitor rule (compared by name).
// If the rule exists, it is replaced with the input rule.
for (auto& r : m_vMonitorRules) {
if (r.name == newrule.name) {
r = newrule;
return true;
}
}
return false;
}
void CConfigManager::performMonitorReload() { void CConfigManager::performMonitorReload() {
bool overAgain = false; bool overAgain = false;
@@ -1509,7 +1509,7 @@ void CConfigManager::performMonitorReload() {
auto rule = getMonitorRuleFor(m); auto rule = getMonitorRuleFor(m);
if (!m->applyMonitorRule(&rule)) { if (!g_pHyprRenderer->applyMonitorRule(m, &rule)) {
overAgain = true; overAgain = true;
break; break;
} }
@@ -1567,7 +1567,7 @@ void CConfigManager::ensureMonitorStatus() {
auto rule = getMonitorRuleFor(rm); auto rule = getMonitorRuleFor(rm);
if (rule.disabled == rm->m_bEnabled) if (rule.disabled == rm->m_bEnabled)
rm->applyMonitorRule(&rule); g_pHyprRenderer->applyMonitorRule(rm, &rule);
} }
} }
@@ -1650,8 +1650,8 @@ void CConfigManager::ensureVRR(PHLMONITOR pMonitor) {
} }
} }
SP<SAnimationPropertyConfig> CConfigManager::getAnimationPropertyConfig(const std::string& name) { SAnimationPropertyConfig* CConfigManager::getAnimationPropertyConfig(const std::string& name) {
return m_AnimationTree.getConfig(name); return &animationConfig[name];
} }
void CConfigManager::addParseError(const std::string& err) { void CConfigManager::addParseError(const std::string& err) {
@@ -1686,7 +1686,7 @@ void CConfigManager::addExecRule(const SExecRequestedRule& rule) {
} }
void CConfigManager::handlePluginLoads() { void CConfigManager::handlePluginLoads() {
if (!g_pPluginSystem) if (g_pPluginSystem == nullptr)
return; return;
bool pluginsChanged = false; bool pluginsChanged = false;
@@ -1705,7 +1705,8 @@ void CConfigManager::handlePluginLoads() {
if (pluginsChanged) { if (pluginsChanged) {
g_pHyprError->destroy(); g_pHyprError->destroy();
reload(); m_bForceReload = true;
tick();
} }
} }
@@ -1713,8 +1714,12 @@ ICustomConfigValueData::~ICustomConfigValueData() {
; // empty ; // empty
} }
const std::unordered_map<std::string, SP<SAnimationPropertyConfig>>& CConfigManager::getAnimationConfig() { std::unordered_map<std::string, SAnimationPropertyConfig> CConfigManager::getAnimationConfig() {
return m_AnimationTree.getFullConfig(); return animationConfig;
}
void onPluginLoadUnload(const std::string& name, bool load) {
//
} }
void CConfigManager::addPluginConfigVar(HANDLE handle, const std::string& name, const Hyprlang::CConfigValue& value) { void CConfigManager::addPluginConfigVar(HANDLE handle, const std::string& name, const Hyprlang::CConfigValue& value) {
@@ -1767,17 +1772,7 @@ std::string CConfigManager::getDefaultWorkspaceFor(const std::string& name) {
std::optional<std::string> CConfigManager::handleRawExec(const std::string& command, const std::string& args) { std::optional<std::string> CConfigManager::handleRawExec(const std::string& command, const std::string& args) {
if (isFirstLaunch) { if (isFirstLaunch) {
firstExecRequests.push_back({args, false}); firstExecRequests.push_back(args);
return {};
}
g_pKeybindManager->spawnRaw(args);
return {};
}
std::optional<std::string> CConfigManager::handleExec(const std::string& command, const std::string& args) {
if (isFirstLaunch) {
firstExecRequests.push_back({args, true});
return {}; return {};
} }
@@ -1787,14 +1782,7 @@ std::optional<std::string> CConfigManager::handleExec(const std::string& command
std::optional<std::string> CConfigManager::handleExecOnce(const std::string& command, const std::string& args) { std::optional<std::string> CConfigManager::handleExecOnce(const std::string& command, const std::string& args) {
if (isFirstLaunch) if (isFirstLaunch)
firstExecRequests.push_back({args, true}); firstExecRequests.push_back(args);
return {};
}
std::optional<std::string> CConfigManager::handleExecRawOnce(const std::string& command, const std::string& args) {
if (isFirstLaunch)
firstExecRequests.push_back({args, false});
return {}; return {};
} }
@@ -2077,6 +2065,17 @@ std::optional<std::string> CConfigManager::handleBezier(const std::string& comma
return {}; return {};
} }
void CConfigManager::setAnimForChildren(SAnimationPropertyConfig* const ANIM) {
for (auto& [name, anim] : animationConfig) {
if (anim.pParentAnimation == ANIM && !anim.overridden) {
// if a child isnt overridden, set the values of the parent
anim.pValues = ANIM->pValues;
setAnimForChildren(&anim);
}
}
};
std::optional<std::string> CConfigManager::handleAnimation(const std::string& command, const std::string& args) { std::optional<std::string> CConfigManager::handleAnimation(const std::string& command, const std::string& args) {
const auto ARGS = CVarList(args); const auto ARGS = CVarList(args);
@@ -2085,9 +2084,14 @@ std::optional<std::string> CConfigManager::handleAnimation(const std::string& co
// anim name // anim name
const auto ANIMNAME = ARGS[0]; const auto ANIMNAME = ARGS[0];
if (!m_AnimationTree.nodeExists(ANIMNAME)) const auto PANIM = animationConfig.find(ANIMNAME);
if (PANIM == animationConfig.end())
return "no such animation"; return "no such animation";
PANIM->second.overridden = true;
PANIM->second.pValues = &PANIM->second;
// This helper casts strings like "1", "true", "off", "yes"... to int. // This helper casts strings like "1", "true", "off", "yes"... to int.
int64_t enabledInt = configStringToInt(ARGS[1]).value_or(0) == 1; int64_t enabledInt = configStringToInt(ARGS[1]).value_or(0) == 1;
@@ -2095,41 +2099,43 @@ std::optional<std::string> CConfigManager::handleAnimation(const std::string& co
if (enabledInt != 0 && enabledInt != 1) if (enabledInt != 0 && enabledInt != 1)
return "invalid animation on/off state"; return "invalid animation on/off state";
if (!enabledInt) { PANIM->second.internalEnabled = configStringToInt(ARGS[1]).value_or(0) == 1;
m_AnimationTree.setConfigForNode(ANIMNAME, enabledInt, 1, "default");
return {};
}
float speed = -1; if (PANIM->second.internalEnabled) {
// speed
if (isNumber(ARGS[2], true)) {
PANIM->second.internalSpeed = std::stof(ARGS[2]);
// speed if (PANIM->second.internalSpeed <= 0) {
if (isNumber(ARGS[2], true)) { PANIM->second.internalSpeed = 1.f;
speed = std::stof(ARGS[2]); return "invalid speed";
}
if (speed <= 0) { } else {
speed = 1.f; PANIM->second.internalSpeed = 10.f;
return "invalid speed"; return "invalid speed";
} }
} else {
speed = 10.f; // curve
return "invalid speed"; PANIM->second.internalBezier = ARGS[3];
if (!g_pAnimationManager->bezierExists(ARGS[3])) {
PANIM->second.internalBezier = "default";
return "no such bezier";
}
// style
PANIM->second.internalStyle = ARGS[4];
if (ARGS[4] != "") {
auto ERR = g_pAnimationManager->styleValidInConfigVar(ANIMNAME, ARGS[4]);
if (ERR != "")
return ERR;
}
} }
std::string bezierName = ARGS[3]; // now, check for children, recursively
m_AnimationTree.setConfigForNode(ANIMNAME, enabledInt, speed, ARGS[3], ARGS[4]); setAnimForChildren(&PANIM->second);
if (!g_pAnimationManager->bezierExists(bezierName)) {
const auto PANIMNODE = m_AnimationTree.getConfig(ANIMNAME);
PANIMNODE->internalBezier = "default";
return "no such bezier";
}
if (ARGS[4] != "") {
auto ERR = g_pAnimationManager->styleValidInConfigVar(ANIMNAME, ARGS[4]);
if (ERR != "")
return ERR;
}
return {}; return {};
} }
@@ -2295,8 +2301,6 @@ std::optional<std::string> CConfigManager::handleWindowRule(const std::string& c
return "Invalid rule: " + RULE; return "Invalid rule: " + RULE;
} }
newRule->rV1Regex = {VALUE.starts_with("title:") ? VALUE.substr(6) : VALUE};
if (RULE.starts_with("size") || RULE.starts_with("maxsize") || RULE.starts_with("minsize")) if (RULE.starts_with("size") || RULE.starts_with("maxsize") || RULE.starts_with("minsize"))
m_vWindowRules.insert(m_vWindowRules.begin(), newRule); m_vWindowRules.insert(m_vWindowRules.begin(), newRule);
else else
@@ -2325,8 +2329,6 @@ std::optional<std::string> CConfigManager::handleLayerRule(const std::string& co
return "Invalid rule found: " + RULE; return "Invalid rule found: " + RULE;
} }
rule->targetNamespaceRegex = {VALUE};
m_vLayerRules.emplace_back(rule); m_vLayerRules.emplace_back(rule);
for (auto const& m : g_pCompositor->m_vMonitors) for (auto const& m : g_pCompositor->m_vMonitors)
@@ -2425,25 +2427,17 @@ std::optional<std::string> CConfigManager::handleWindowRuleV2(const std::string&
if (TAGPOS != std::string::npos) if (TAGPOS != std::string::npos)
rule->szTag = extract(TAGPOS + 4); rule->szTag = extract(TAGPOS + 4);
if (CLASSPOS != std::string::npos) { if (CLASSPOS != std::string::npos)
rule->szClass = extract(CLASSPOS + 6); rule->szClass = extract(CLASSPOS + 6);
rule->rClass = {rule->szClass};
}
if (TITLEPOS != std::string::npos) { if (TITLEPOS != std::string::npos)
rule->szTitle = extract(TITLEPOS + 6); rule->szTitle = extract(TITLEPOS + 6);
rule->rTitle = {rule->szTitle};
}
if (INITIALCLASSPOS != std::string::npos) { if (INITIALCLASSPOS != std::string::npos)
rule->szInitialClass = extract(INITIALCLASSPOS + 13); rule->szInitialClass = extract(INITIALCLASSPOS + 13);
rule->rInitialClass = {rule->szInitialClass};
}
if (INITIALTITLEPOS != std::string::npos) { if (INITIALTITLEPOS != std::string::npos)
rule->szInitialTitle = extract(INITIALTITLEPOS + 13); rule->szInitialTitle = extract(INITIALTITLEPOS + 13);
rule->rInitialTitle = {rule->szInitialTitle};
}
if (X11POS != std::string::npos) if (X11POS != std::string::npos)
rule->bX11 = extract(X11POS + 9) == "1" ? 1 : 0; rule->bX11 = extract(X11POS + 9) == "1" ? 1 : 0;
@@ -2694,14 +2688,8 @@ std::optional<std::string> CConfigManager::handleSource(const std::string& comma
Debug::log(ERR, "source= path garbage"); Debug::log(ERR, "source= path garbage");
return "source= path " + rawpath + " bogus!"; return "source= path " + rawpath + " bogus!";
} }
std::unique_ptr<glob_t, void (*)(glob_t*)> glob_buf{new glob_t, [](glob_t* g) { globfree(g); }};
std::unique_ptr<glob_t, void (*)(glob_t*)> glob_buf{static_cast<glob_t*>(calloc(1, sizeof(glob_t))), // allocate and zero-initialize memset(glob_buf.get(), 0, sizeof(glob_t));
[](glob_t* g) {
if (g) {
globfree(g); // free internal resources allocated by glob()
free(g); // free the memory for the glob_t structure
}
}};
if (auto r = glob(absolutePath(rawpath, configCurrentPath).c_str(), GLOB_TILDE, nullptr, glob_buf.get()); r != 0) { if (auto r = glob(absolutePath(rawpath, configCurrentPath).c_str(), GLOB_TILDE, nullptr, glob_buf.get()); r != 0) {
std::string err = std::format("source= globbing error: {}", r == GLOB_NOMATCH ? "found no match" : GLOB_ABORTED ? "read error" : "out of memory"); std::string err = std::format("source= globbing error: {}", r == GLOB_NOMATCH ? "found no match" : GLOB_ABORTED ? "read error" : "out of memory");
@@ -2723,8 +2711,16 @@ std::optional<std::string> CConfigManager::handleSource(const std::string& comma
Debug::log(ERR, "source= file doesn't exist: {}", value); Debug::log(ERR, "source= file doesn't exist: {}", value);
return "source= file " + value + " doesn't exist!"; return "source= file " + value + " doesn't exist!";
} }
m_configPaths.emplace_back(value); configPaths.push_back(value);
struct stat fileStat;
int err = stat(value.c_str(), &fileStat);
if (err != 0) {
Debug::log(WARN, "Error at ticking config at {}, error {}: {}", value, err, strerror(err));
return {};
}
configModifyTimes[value] = fileStat.st_mtime;
auto configCurrentPathBackup = configCurrentPath; auto configCurrentPathBackup = configCurrentPath;
configCurrentPath = value; configCurrentPath = value;
@@ -2786,7 +2782,7 @@ bool CConfigManager::shouldUseSoftwareCursors() {
switch (*PNOHW) { switch (*PNOHW) {
case 0: return false; case 0: return false;
case 1: return true; case 1: return true;
default: break; default: return g_pHyprRenderer->isNvidia();
} }
return true; return true;
@@ -2844,7 +2840,3 @@ std::string SConfigOptionDescription::jsonify() const {
return json; return json;
} }
void CConfigManager::ensurePersistentWorkspacesPresent() {
g_pCompositor->ensurePersistentWorkspacesPresent(m_vWorkspaceRules);
}

View File

@@ -1,30 +1,31 @@
#pragma once #pragma once
#include <hyprutils/animation/AnimationConfig.hpp>
#define CONFIG_MANAGER_H #define CONFIG_MANAGER_H
#include <map> #include <map>
#include "../debug/Log.hpp"
#include <unordered_map> #include <unordered_map>
#include "../defines.hpp" #include "../defines.hpp"
#include <variant> #include <variant>
#include <vector> #include <vector>
#include <algorithm>
#include <optional> #include <optional>
#include <functional> #include <functional>
#include <xf86drmMode.h> #include <xf86drmMode.h>
#include "../helpers/WLClasses.hpp"
#include "../helpers/Monitor.hpp" #include "../helpers/Monitor.hpp"
#include "../helpers/varlist/VarList.hpp"
#include "../desktop/Window.hpp" #include "../desktop/Window.hpp"
#include "../desktop/LayerRule.hpp" #include "../desktop/LayerSurface.hpp"
#include "defaultConfig.hpp"
#include "ConfigDataValues.hpp" #include "ConfigDataValues.hpp"
#include "../SharedDefs.hpp"
#include "../helpers/Color.hpp"
#include "../desktop/DesktopTypes.hpp"
#include "../helpers/memory/Memory.hpp"
#include "../desktop/WindowRule.hpp"
#include "../managers/XWaylandManager.hpp"
#include <hyprlang.hpp> #include <hyprlang.hpp>
#define INITANIMCFG(name) animationConfig[name] = {}
#define CREATEANIMCFG(name, parent) animationConfig[name] = {false, "", "", 0.f, -1, &animationConfig["global"], &animationConfig[parent]}
#define HANDLE void* #define HANDLE void*
struct SWorkspaceRule { struct SWorkspaceRule {
@@ -53,6 +54,18 @@ struct SMonitorAdditionalReservedArea {
int right = 0; int right = 0;
}; };
struct SAnimationPropertyConfig {
bool overridden = true;
std::string internalBezier = "";
std::string internalStyle = "";
float internalSpeed = 0.f;
int internalEnabled = -1;
SAnimationPropertyConfig* pValues = nullptr;
SAnimationPropertyConfig* pParentAnimation = nullptr;
};
struct SPluginKeyword { struct SPluginKeyword {
HANDLE handle = nullptr; HANDLE handle = nullptr;
std::string name = ""; std::string name = "";
@@ -133,18 +146,12 @@ struct SConfigOptionDescription {
std::variant<SBoolData, SRangeData, SFloatData, SStringData, SColorData, SChoiceData, SGradientData, SVectorData> data; std::variant<SBoolData, SRangeData, SFloatData, SStringData, SColorData, SChoiceData, SGradientData, SVectorData> data;
}; };
struct SFirstExecRequest {
std::string exec = "";
bool withRules = false;
};
class CConfigManager { class CConfigManager {
public: public:
CConfigManager(); CConfigManager();
void tick();
void init(); void init();
void reload();
std::string verify();
int getDeviceInt(const std::string&, const std::string&, const std::string& fallback = ""); int getDeviceInt(const std::string&, const std::string&, const std::string& fallback = "");
float getDeviceFloat(const std::string&, const std::string&, const std::string& fallback = ""); float getDeviceFloat(const std::string&, const std::string&, const std::string& fallback = "");
@@ -156,7 +163,8 @@ class CConfigManager {
void* const* getConfigValuePtr(const std::string&); void* const* getConfigValuePtr(const std::string&);
Hyprlang::CConfigValue* getHyprlangConfigValuePtr(const std::string& name, const std::string& specialCat = ""); Hyprlang::CConfigValue* getHyprlangConfigValuePtr(const std::string& name, const std::string& specialCat = "");
std::string getMainConfigPath(); void onPluginLoadUnload(const std::string& name, bool load);
static std::string getMainConfigPath();
std::string getConfigString(); std::string getConfigString();
SMonitorRule getMonitorRuleFor(const PHLMONITOR); SMonitorRule getMonitorRuleFor(const PHLMONITOR);
@@ -169,45 +177,43 @@ class CConfigManager {
std::vector<SP<CWindowRule>> getMatchingRules(PHLWINDOW, bool dynamic = true, bool shadowExec = false); std::vector<SP<CWindowRule>> getMatchingRules(PHLWINDOW, bool dynamic = true, bool shadowExec = false);
std::vector<SP<CLayerRule>> getMatchingRules(PHLLS); std::vector<SP<CLayerRule>> getMatchingRules(PHLLS);
void ensurePersistentWorkspacesPresent();
const std::vector<SConfigOptionDescription>& getAllDescriptions(); const std::vector<SConfigOptionDescription>& getAllDescriptions();
std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas; std::unordered_map<std::string, SMonitorAdditionalReservedArea> m_mAdditionalReservedAreas;
const std::unordered_map<std::string, SP<Hyprutils::Animation::SAnimationPropertyConfig>>& getAnimationConfig(); std::unordered_map<std::string, SAnimationPropertyConfig> getAnimationConfig();
void addPluginConfigVar(HANDLE handle, const std::string& name, const Hyprlang::CConfigValue& value); void addPluginConfigVar(HANDLE handle, const std::string& name, const Hyprlang::CConfigValue& value);
void addPluginKeyword(HANDLE handle, const std::string& name, Hyprlang::PCONFIGHANDLERFUNC fun, Hyprlang::SHandlerOptions opts = {}); void addPluginKeyword(HANDLE handle, const std::string& name, Hyprlang::PCONFIGHANDLERFUNC fun, Hyprlang::SHandlerOptions opts = {});
void removePluginConfig(HANDLE handle); void removePluginConfig(HANDLE handle);
// no-op when done. // no-op when done.
void dispatchExecOnce(); void dispatchExecOnce();
void dispatchExecShutdown(); void dispatchExecShutdown();
void performMonitorReload(); void performMonitorReload();
void ensureMonitorStatus(); void appendMonitorRule(const SMonitorRule&);
void ensureVRR(PHLMONITOR pMonitor = nullptr); bool replaceMonitorRule(const SMonitorRule&);
void ensureMonitorStatus();
void ensureVRR(PHLMONITOR pMonitor = nullptr);
bool shouldUseSoftwareCursors(); bool shouldUseSoftwareCursors();
void updateWatcher();
std::string parseKeyword(const std::string&, const std::string&); std::string parseKeyword(const std::string&, const std::string&);
void addParseError(const std::string&); void addParseError(const std::string&);
SP<Hyprutils::Animation::SAnimationPropertyConfig> getAnimationPropertyConfig(const std::string&); SAnimationPropertyConfig* getAnimationPropertyConfig(const std::string&);
void addExecRule(const SExecRequestedRule&); void addExecRule(const SExecRequestedRule&);
void handlePluginLoads(); void handlePluginLoads();
std::string getErrors(); std::string getErrors();
// keywords // keywords
std::optional<std::string> handleRawExec(const std::string&, const std::string&); std::optional<std::string> handleRawExec(const std::string&, const std::string&);
std::optional<std::string> handleExec(const std::string&, const std::string&);
std::optional<std::string> handleExecOnce(const std::string&, const std::string&); std::optional<std::string> handleExecOnce(const std::string&, const std::string&);
std::optional<std::string> handleExecRawOnce(const std::string&, const std::string&);
std::optional<std::string> handleExecShutdown(const std::string&, const std::string&); std::optional<std::string> handleExecShutdown(const std::string&, const std::string&);
std::optional<std::string> handleMonitor(const std::string&, const std::string&); std::optional<std::string> handleMonitor(const std::string&, const std::string&);
std::optional<std::string> handleBind(const std::string&, const std::string&); std::optional<std::string> handleBind(const std::string&, const std::string&);
@@ -256,55 +262,56 @@ class CConfigManager {
}; };
std::unordered_map<std::string, std::function<CWindowOverridableVar<float>*(PHLWINDOW)>> mfWindowProperties = { std::unordered_map<std::string, std::function<CWindowOverridableVar<float>*(PHLWINDOW)>> mfWindowProperties = {
{"roundingpower", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.roundingPower; }},
{"scrollmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollMouse; }}, {"scrollmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollMouse; }},
{"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollTouchpad; }}}; {"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollTouchpad; }}};
bool m_bWantsMonitorReload = false; bool m_bWantsMonitorReload = false;
bool m_bNoMonitorReload = false; bool m_bForceReload = false;
bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking bool m_bNoMonitorReload = false;
bool m_bLastConfigVerificationWasSuccessful = true; bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking
private: private:
UP<Hyprlang::CConfig> m_pConfig; std::unique_ptr<Hyprlang::CConfig> m_pConfig;
std::vector<std::string> m_configPaths; std::vector<std::string> configPaths; // stores all the config paths
std::unordered_map<std::string, time_t> configModifyTimes; // stores modify times
Hyprutils::Animation::CAnimationConfigTree m_AnimationTree; std::unordered_map<std::string, SAnimationPropertyConfig> animationConfig; // stores all the animations with their set values
std::string m_szCurrentSubmap = ""; // For storing the current keybind submap std::string m_szCurrentSubmap = ""; // For storing the current keybind submap
std::vector<SExecRequestedRule> execRequestedRules; // rules requested with exec, e.g. [workspace 2] kitty std::vector<SExecRequestedRule> execRequestedRules; // rules requested with exec, e.g. [workspace 2] kitty
std::vector<std::string> m_vDeclaredPlugins; std::vector<std::string> m_vDeclaredPlugins;
std::vector<SPluginKeyword> pluginKeywords; std::vector<SPluginKeyword> pluginKeywords;
std::vector<SPluginVariable> pluginVariables; std::vector<SPluginVariable> pluginVariables;
bool isFirstLaunch = true; // For exec-once bool isFirstLaunch = true; // For exec-once
std::vector<SMonitorRule> m_vMonitorRules; std::vector<SMonitorRule> m_vMonitorRules;
std::vector<SWorkspaceRule> m_vWorkspaceRules; std::vector<SWorkspaceRule> m_vWorkspaceRules;
std::vector<SP<CWindowRule>> m_vWindowRules; std::vector<SP<CWindowRule>> m_vWindowRules;
std::vector<SP<CLayerRule>> m_vLayerRules; std::vector<SP<CLayerRule>> m_vLayerRules;
std::vector<std::string> m_dBlurLSNamespaces; std::vector<std::string> m_dBlurLSNamespaces;
bool firstExecDispatched = false; bool firstExecDispatched = false;
bool m_bManualCrashInitiated = false; bool m_bManualCrashInitiated = false;
std::vector<std::string> firstExecRequests;
std::vector<std::string> finalExecRequests;
std::vector<SFirstExecRequest> firstExecRequests; // bool is for if with rules std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins
std::vector<std::string> finalExecRequests; std::string m_szConfigErrors = "";
std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins
std::string m_szConfigErrors = "";
// internal methods // internal methods
void updateBlurredLS(const std::string&, const bool); void setAnimForChildren(SAnimationPropertyConfig* const);
void setDefaultAnimationVars(); void updateBlurredLS(const std::string&, const bool);
std::optional<std::string> resetHLConfig(); void setDefaultAnimationVars();
std::optional<std::string> generateConfig(std::string configPath); std::optional<std::string> resetHLConfig();
std::optional<std::string> verifyConfigExists(); static std::optional<std::string> generateConfig(std::string configPath);
void postConfigReload(const Hyprlang::CParseResult& result); static std::optional<std::string> verifyConfigExists();
SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&); void postConfigReload(const Hyprlang::CParseResult& result);
void reload();
SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&);
}; };
inline UP<CConfigManager> g_pConfigManager; inline std::unique_ptr<CConfigManager> g_pConfigManager;

View File

@@ -3,6 +3,7 @@
#include <string> #include <string>
#include <typeindex> #include <typeindex>
#include <hyprlang.hpp> #include <hyprlang.hpp>
#include "../debug/Log.hpp"
#include "../macros.hpp" #include "../macros.hpp"
#include "ConfigManager.hpp" #include "ConfigManager.hpp"
@@ -70,4 +71,4 @@ template <>
inline Hyprlang::CUSTOMTYPE CConfigValue<Hyprlang::CUSTOMTYPE>::operator*() const { inline Hyprlang::CUSTOMTYPE CConfigValue<Hyprlang::CUSTOMTYPE>::operator*() const {
RASSERT(false, "Impossible to implement operator* of CConfigValue<Hyprlang::CUSTOMTYPE>, use ptr()"); RASSERT(false, "Impossible to implement operator* of CConfigValue<Hyprlang::CUSTOMTYPE>, use ptr()");
return *ptr(); return *ptr();
} }

View File

@@ -1,73 +0,0 @@
#include "ConfigWatcher.hpp"
#include <sys/inotify.h>
#include "../debug/Log.hpp"
#include <ranges>
#include <fcntl.h>
#include <unistd.h>
CConfigWatcher::CConfigWatcher() : m_inotifyFd(inotify_init()) {
if (m_inotifyFd < 0) {
Debug::log(ERR, "CConfigWatcher couldn't open an inotify node. Config will not be automatically reloaded");
return;
}
const int FLAGS = fcntl(m_inotifyFd, F_GETFL, 0);
if (fcntl(m_inotifyFd, F_SETFL, FLAGS | O_NONBLOCK) < 0) {
Debug::log(ERR, "CConfigWatcher couldn't non-block inotify node. Config will not be automatically reloaded");
close(m_inotifyFd);
m_inotifyFd = -1;
return;
}
}
CConfigWatcher::~CConfigWatcher() {
if (m_inotifyFd >= 0)
close(m_inotifyFd);
}
int CConfigWatcher::getInotifyFD() {
return m_inotifyFd;
}
void CConfigWatcher::setWatchList(const std::vector<std::string>& paths) {
// we clear all watches first, because whichever fired is now invalid
// or that is at least what it seems to be.
// since we don't know which fired,
// plus it doesn't matter that much, these ops are done rarely and fast anyways.
// cleanup old paths
for (auto& watch : m_watches) {
inotify_rm_watch(m_inotifyFd, watch.wd);
}
m_watches.clear();
// add new paths
for (const auto& path : paths) {
m_watches.emplace_back(SInotifyWatch{
.wd = inotify_add_watch(m_inotifyFd, path.c_str(), IN_MODIFY),
.file = path,
});
}
}
void CConfigWatcher::setOnChange(const std::function<void(const SConfigWatchEvent&)>& fn) {
m_watchCallback = fn;
}
void CConfigWatcher::onInotifyEvent() {
inotify_event ev;
while (read(m_inotifyFd, &ev, sizeof(ev)) > 0) {
const auto WD = std::ranges::find_if(m_watches.begin(), m_watches.end(), [wd = ev.wd](const auto& e) { return e.wd == wd; });
if (WD == m_watches.end()) {
Debug::log(ERR, "CConfigWatcher: got an event for wd {} which we don't have?!", ev.wd);
return;
}
m_watchCallback(SConfigWatchEvent{
.file = WD->file,
});
}
}

View File

@@ -1,32 +0,0 @@
#pragma once
#include "../helpers/memory/Memory.hpp"
#include <vector>
#include <string>
#include <functional>
class CConfigWatcher {
public:
CConfigWatcher();
~CConfigWatcher();
struct SConfigWatchEvent {
std::string file;
};
int getInotifyFD();
void setWatchList(const std::vector<std::string>& paths);
void setOnChange(const std::function<void(const SConfigWatchEvent&)>& fn);
void onInotifyEvent();
private:
struct SInotifyWatch {
int wd = -1;
std::string file;
};
std::function<void(const SConfigWatchEvent&)> m_watchCallback;
std::vector<SInotifyWatch> m_watches;
int m_inotifyFd = -1;
};
inline UP<CConfigWatcher> g_pConfigWatcher = makeUnique<CConfigWatcher>();

View File

@@ -94,7 +94,6 @@ general {
# https://wiki.hyprland.org/Configuring/Variables/#decoration # https://wiki.hyprland.org/Configuring/Variables/#decoration
decoration { decoration {
rounding = 10 rounding = 10
rounding_power = 2
# Change transparency of focused and unfocused windows # Change transparency of focused and unfocused windows
active_opacity = 1.0 active_opacity = 1.0

View File

@@ -6,7 +6,6 @@
#include <cerrno> #include <cerrno>
#include <sys/stat.h> #include <sys/stat.h>
#include <filesystem> #include <filesystem>
#include "../helpers/MiscFunctions.hpp"
#include "../plugins/PluginSystem.hpp" #include "../plugins/PluginSystem.hpp"
#include "../signal-safe.hpp" #include "../signal-safe.hpp"
@@ -112,7 +111,7 @@ void NCrashReporter::createAndSaveCrash(int sig) {
#ifdef LEGACY_RENDERER #ifdef LEGACY_RENDERER
finalCrashReport += "legacyrenderer\n"; finalCrashReport += "legacyrenderer\n";
#endif #endif
#if ISDEBUG #ifndef ISDEBUG
finalCrashReport += "debug\n"; finalCrashReport += "debug\n";
#endif #endif
#ifdef NO_XWAYLAND #ifdef NO_XWAYLAND
@@ -162,7 +161,7 @@ void NCrashReporter::createAndSaveCrash(int sig) {
#if defined(__DragonFly__) || defined(__FreeBSD__) #if defined(__DragonFly__) || defined(__FreeBSD__)
finalCrashReport.writeCmdOutput("pciconf -lv | grep -F -A4 vga"); finalCrashReport.writeCmdOutput("pciconf -lv | grep -F -A4 vga");
#else #else
finalCrashReport.writeCmdOutput("lspci -vnn | grep -E '(VGA|Display|3D)'"); finalCrashReport.writeCmdOutput("lspci -vnn | grep VGA");
#endif #endif
finalCrashReport += "\n\nos-release:\n"; finalCrashReport += "\n\nos-release:\n";

View File

@@ -39,18 +39,8 @@ using namespace Hyprutils::String;
#include "debug/RollingLogFollow.hpp" #include "debug/RollingLogFollow.hpp"
#include "config/ConfigManager.hpp" #include "config/ConfigManager.hpp"
#include "helpers/MiscFunctions.hpp" #include "helpers/MiscFunctions.hpp"
#include "../desktop/LayerSurface.hpp"
#include "../version.h" #include "../version.h"
#include "../Compositor.hpp"
#include "../managers/input/InputManager.hpp"
#include "../managers/XWaylandManager.hpp"
#include "../managers/LayoutManager.hpp"
#include "../plugins/PluginSystem.hpp"
#include "../managers/AnimationManager.hpp"
#include "../debug/HyprNotificationOverlay.hpp"
#include "../render/Renderer.hpp"
static void trimTrailingComma(std::string& str) { static void trimTrailingComma(std::string& str) {
if (!str.empty() && str.back() == ',') if (!str.empty() && str.back() == ',')
str.pop_back(); str.pop_back();
@@ -152,7 +142,7 @@ std::string CHyprCtl::getMonitorData(Hyprutils::Memory::CSharedPointer<CMonitor>
return result; return result;
} }
static std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) { std::string monitorsRequest(eHyprCtlOutputFormat format, std::string request) {
CVarList vars(request, 0, ' '); CVarList vars(request, 0, ' ');
auto allMonitors = false; auto allMonitors = false;
@@ -258,8 +248,8 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) {
"focusHistoryID": {}, "focusHistoryID": {},
"inhibitingIdle": {} "inhibitingIdle": {}
}},)#", }},)#",
(uintptr_t)w.get(), (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition->goal().x, (int)w->m_vRealPosition->goal().y, (uintptr_t)w.get(), (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y,
(int)w->m_vRealSize->goal().x, (int)w->m_vRealSize->goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, (int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID,
escapeJSONStrings(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), ((int)w->m_bIsFloating == 1 ? "true" : "false"), (w->m_bIsPseudotiled ? "true" : "false"), escapeJSONStrings(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), ((int)w->m_bIsFloating == 1 ? "true" : "false"), (w->m_bIsPseudotiled ? "true" : "false"),
(int64_t)w->monitorID(), escapeJSONStrings(w->m_szClass), escapeJSONStrings(w->m_szTitle), escapeJSONStrings(w->m_szInitialClass), (int64_t)w->monitorID(), escapeJSONStrings(w->m_szClass), escapeJSONStrings(w->m_szTitle), escapeJSONStrings(w->m_szInitialClass),
escapeJSONStrings(w->m_szInitialTitle), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"), escapeJSONStrings(w->m_szInitialTitle), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"),
@@ -271,16 +261,15 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) {
"{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: " "{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: "
"{}\n\txwayland: {}\n\tpinned: " "{}\n\txwayland: {}\n\tpinned: "
"{}\n\tfullscreen: {}\n\tfullscreenClient: {}\n\tgrouped: {}\n\ttags: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\tinhibitingIdle: {}\n\n", "{}\n\tfullscreen: {}\n\tfullscreenClient: {}\n\tgrouped: {}\n\ttags: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\tinhibitingIdle: {}\n\n",
(uintptr_t)w.get(), w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition->goal().x, (int)w->m_vRealPosition->goal().y, (uintptr_t)w.get(), w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goal().x, (int)w->m_vRealPosition.goal().y,
(int)w->m_vRealSize->goal().x, (int)w->m_vRealSize->goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, (int)w->m_vRealSize.goal().x, (int)w->m_vRealSize.goal().y, w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID, (!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName),
(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), (int)w->m_bIsFloating, (int)w->m_bIsPseudotiled, (int64_t)w->monitorID(), w->m_szClass, w->m_szTitle, (int)w->m_bIsFloating, (int)w->m_bIsPseudotiled, (int64_t)w->monitorID(), w->m_szClass, w->m_szTitle, w->m_szInitialClass, w->m_szInitialTitle, w->getPID(),
w->m_szInitialClass, w->m_szInitialTitle, w->getPID(), (int)w->m_bIsX11, (int)w->m_bPinned, (uint8_t)w->m_sFullscreenState.internal, (int)w->m_bIsX11, (int)w->m_bPinned, (uint8_t)w->m_sFullscreenState.internal, (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format),
(uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w), (uintptr_t)w->m_pSwallowed.lock().get(), getFocusHistoryID(w), (int)g_pInputManager->isWindowInhibiting(w, false));
(int)g_pInputManager->isWindowInhibiting(w, false));
} }
} }
static std::string clientsRequest(eHyprCtlOutputFormat format, std::string request) { std::string clientsRequest(eHyprCtlOutputFormat format, std::string request) {
std::string result = ""; std::string result = "";
if (format == eHyprCtlOutputFormat::FORMAT_JSON) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
result += "["; result += "[";
@@ -379,8 +368,7 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, eHyprCtlOutputF
return result; return result;
} }
} }
std::string activeWorkspaceRequest(eHyprCtlOutputFormat format, std::string request) {
static std::string activeWorkspaceRequest(eHyprCtlOutputFormat format, std::string request) {
if (!g_pCompositor->m_pLastMonitor) if (!g_pCompositor->m_pLastMonitor)
return "unsafe state"; return "unsafe state";
@@ -393,7 +381,7 @@ static std::string activeWorkspaceRequest(eHyprCtlOutputFormat format, std::stri
return CHyprCtl::getWorkspaceData(w, format); return CHyprCtl::getWorkspaceData(w, format);
} }
static std::string workspacesRequest(eHyprCtlOutputFormat format, std::string request) { std::string workspacesRequest(eHyprCtlOutputFormat format, std::string request) {
std::string result = ""; std::string result = "";
if (format == eHyprCtlOutputFormat::FORMAT_JSON) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
@@ -414,7 +402,7 @@ static std::string workspacesRequest(eHyprCtlOutputFormat format, std::string re
return result; return result;
} }
static std::string workspaceRulesRequest(eHyprCtlOutputFormat format, std::string request) { std::string workspaceRulesRequest(eHyprCtlOutputFormat format, std::string request) {
std::string result = ""; std::string result = "";
if (format == eHyprCtlOutputFormat::FORMAT_JSON) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
result += "["; result += "[";
@@ -434,7 +422,7 @@ static std::string workspaceRulesRequest(eHyprCtlOutputFormat format, std::strin
return result; return result;
} }
static std::string activeWindowRequest(eHyprCtlOutputFormat format, std::string request) { std::string activeWindowRequest(eHyprCtlOutputFormat format, std::string request) {
const auto PWINDOW = g_pCompositor->m_pLastWindow.lock(); const auto PWINDOW = g_pCompositor->m_pLastWindow.lock();
if (!validMapped(PWINDOW)) if (!validMapped(PWINDOW))
@@ -448,7 +436,7 @@ static std::string activeWindowRequest(eHyprCtlOutputFormat format, std::string
return result; return result;
} }
static std::string layersRequest(eHyprCtlOutputFormat format, std::string request) { std::string layersRequest(eHyprCtlOutputFormat format, std::string request) {
std::string result = ""; std::string result = "";
if (format == eHyprCtlOutputFormat::FORMAT_JSON) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
@@ -522,7 +510,7 @@ static std::string layersRequest(eHyprCtlOutputFormat format, std::string reques
return result; return result;
} }
static std::string layoutsRequest(eHyprCtlOutputFormat format, std::string request) { std::string layoutsRequest(eHyprCtlOutputFormat format, std::string request) {
std::string result = ""; std::string result = "";
if (format == eHyprCtlOutputFormat::FORMAT_JSON) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
result += "["; result += "[";
@@ -544,7 +532,7 @@ static std::string layoutsRequest(eHyprCtlOutputFormat format, std::string reque
return result; return result;
} }
static std::string configErrorsRequest(eHyprCtlOutputFormat format, std::string request) { std::string configErrorsRequest(eHyprCtlOutputFormat format, std::string request) {
std::string result = ""; std::string result = "";
std::string currErrors = g_pConfigManager->getErrors(); std::string currErrors = g_pConfigManager->getErrors();
CVarList errLines(currErrors, 0, '\n'); CVarList errLines(currErrors, 0, '\n');
@@ -567,7 +555,7 @@ static std::string configErrorsRequest(eHyprCtlOutputFormat format, std::string
return result; return result;
} }
static std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) { std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
std::string result = ""; std::string result = "";
auto getModState = [](SP<IKeyboard> keyboard, const char* xkbModName) -> bool { auto getModState = [](SP<IKeyboard> keyboard, const char* xkbModName) -> bool {
@@ -737,14 +725,14 @@ static std::string devicesRequest(eHyprCtlOutputFormat format, std::string reque
return result; return result;
} }
static std::string animationsRequest(eHyprCtlOutputFormat format, std::string request) { std::string animationsRequest(eHyprCtlOutputFormat format, std::string request) {
std::string ret = ""; std::string ret = "";
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
ret += "animations:\n"; ret += "animations:\n";
for (auto const& ac : g_pConfigManager->getAnimationConfig()) { for (auto const& ac : g_pConfigManager->getAnimationConfig()) {
ret += std::format("\n\tname: {}\n\t\toverriden: {}\n\t\tbezier: {}\n\t\tenabled: {}\n\t\tspeed: {:.2f}\n\t\tstyle: {}\n", ac.first, (int)ac.second->overridden, ret += std::format("\n\tname: {}\n\t\toverriden: {}\n\t\tbezier: {}\n\t\tenabled: {}\n\t\tspeed: {:.2f}\n\t\tstyle: {}\n", ac.first, (int)ac.second.overridden,
ac.second->internalBezier, ac.second->internalEnabled, ac.second->internalSpeed, ac.second->internalStyle); ac.second.internalBezier, ac.second.internalEnabled, ac.second.internalSpeed, ac.second.internalStyle);
} }
ret += "beziers:\n"; ret += "beziers:\n";
@@ -766,8 +754,8 @@ static std::string animationsRequest(eHyprCtlOutputFormat format, std::string re
"speed": {:.2f}, "speed": {:.2f},
"style": "{}" "style": "{}"
}},)#", }},)#",
ac.first, ac.second->overridden ? "true" : "false", escapeJSONStrings(ac.second->internalBezier), ac.second->internalEnabled ? "true" : "false", ac.first, ac.second.overridden ? "true" : "false", escapeJSONStrings(ac.second.internalBezier), ac.second.internalEnabled ? "true" : "false",
ac.second->internalSpeed, escapeJSONStrings(ac.second->internalStyle)); ac.second.internalSpeed, escapeJSONStrings(ac.second.internalStyle));
} }
ret[ret.length() - 1] = ']'; ret[ret.length() - 1] = ']';
@@ -790,7 +778,7 @@ static std::string animationsRequest(eHyprCtlOutputFormat format, std::string re
return ret; return ret;
} }
static std::string rollinglogRequest(eHyprCtlOutputFormat format, std::string request) { std::string rollinglogRequest(eHyprCtlOutputFormat format, std::string request) {
std::string result = ""; std::string result = "";
if (format == eHyprCtlOutputFormat::FORMAT_JSON) { if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
@@ -804,7 +792,7 @@ static std::string rollinglogRequest(eHyprCtlOutputFormat format, std::string re
return result; return result;
} }
static std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::string request) { std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::string request) {
std::string ret = ""; std::string ret = "";
const auto SHORTCUTS = PROTO::globalShortcuts->getAllShortcuts(); const auto SHORTCUTS = PROTO::globalShortcuts->getAllShortcuts();
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
@@ -827,7 +815,7 @@ static std::string globalShortcutsRequest(eHyprCtlOutputFormat format, std::stri
return ret; return ret;
} }
static std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) { std::string bindsRequest(eHyprCtlOutputFormat format, std::string request) {
std::string ret = ""; std::string ret = "";
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
for (auto const& kb : g_pKeybindManager->m_vKeybinds) { for (auto const& kb : g_pKeybindManager->m_vKeybinds) {
@@ -895,14 +883,14 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
HYPRLAND_VERSION, GIT_BRANCH, GIT_COMMIT_HASH, GIT_DIRTY, commitMsg, GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, AQUAMARINE_VERSION, HYPRLAND_VERSION, GIT_BRANCH, GIT_COMMIT_HASH, GIT_DIRTY, commitMsg, GIT_COMMIT_DATE, GIT_TAG, GIT_COMMITS, AQUAMARINE_VERSION,
HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION, HYPRGRAPHICS_VERSION); HYPRLANG_VERSION, HYPRUTILS_VERSION, HYPRCURSOR_VERSION, HYPRGRAPHICS_VERSION);
#if (!defined(LEGACY_RENDERER) && !ISDEBUG && !defined(NO_XWAYLAND)) #if (!defined(LEGACY_RENDERER) && !defined(ISDEBUG) && !defined(NO_XWAYLAND))
result += "no flags were set\n"; result += "no flags were set\n";
#else #else
result += "flags set:\n"; result += "flags set:\n";
#ifdef LEGACY_RENDERER #ifdef LEGACY_RENDERER
result += "legacyrenderer\n"; result += "legacyrenderer\n";
#endif #endif
#if ISDEBUG #ifdef ISDEBUG
result += "debug\n"; result += "debug\n";
#endif #endif
#ifdef NO_XWAYLAND #ifdef NO_XWAYLAND
@@ -933,7 +921,7 @@ std::string versionRequest(eHyprCtlOutputFormat format, std::string request) {
#ifdef LEGACY_RENDERER #ifdef LEGACY_RENDERER
result += "\"legacyrenderer\","; result += "\"legacyrenderer\",";
#endif #endif
#if ISDEBUG #ifdef ISDEBUG
result += "\"debug\","; result += "\"debug\",";
#endif #endif
#ifdef NO_XWAYLAND #ifdef NO_XWAYLAND
@@ -988,7 +976,7 @@ std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request)
} }
} catch (...) { GPUINFO = "error"; } } catch (...) { GPUINFO = "error"; }
#else #else
const std::string GPUINFO = execAndGet("lspci -vnn | grep -E '(VGA|Display|3D)'"); const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA");
#endif #endif
result += "GPU information: \n" + GPUINFO; result += "GPU information: \n" + GPUINFO;
if (GPUINFO.contains("NVIDIA") && std::filesystem::exists("/proc/driver/nvidia/version")) { if (GPUINFO.contains("NVIDIA") && std::filesystem::exists("/proc/driver/nvidia/version")) {
@@ -1030,7 +1018,7 @@ std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request)
return result; return result;
} }
static std::string dispatchRequest(eHyprCtlOutputFormat format, std::string in) { std::string dispatchRequest(eHyprCtlOutputFormat format, std::string in) {
// get rid of the dispatch keyword // get rid of the dispatch keyword
in = in.substr(in.find_first_of(' ') + 1); in = in.substr(in.find_first_of(' ') + 1);
@@ -1051,7 +1039,7 @@ static std::string dispatchRequest(eHyprCtlOutputFormat format, std::string in)
return res.success ? "ok" : res.error; return res.success ? "ok" : res.error;
} }
static std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) { std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) {
// Find the first space to strip the keyword keyword // Find the first space to strip the keyword keyword
auto const firstSpacePos = in.find_first_of(' '); auto const firstSpacePos = in.find_first_of(' ');
if (firstSpacePos == std::string::npos) // Handle the case where there's no space found (invalid input) if (firstSpacePos == std::string::npos) // Handle the case where there's no space found (invalid input)
@@ -1100,9 +1088,6 @@ static std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in)
} }
} }
if (COMMAND.contains("misc:disable_autoreload"))
g_pConfigManager->updateWatcher();
// decorations will probably need a repaint // decorations will probably need a repaint
if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("zoom_factor") || COMMAND == "source" || if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("zoom_factor") || COMMAND == "source" ||
COMMAND.starts_with("windowrule")) { COMMAND.starts_with("windowrule")) {
@@ -1120,29 +1105,32 @@ static std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in)
return retval; return retval;
} }
static std::string reloadRequest(eHyprCtlOutputFormat format, std::string request) { std::string reloadRequest(eHyprCtlOutputFormat format, std::string request) {
const auto REQMODE = request.substr(request.find_last_of(' ') + 1); const auto REQMODE = request.substr(request.find_last_of(' ') + 1);
if (REQMODE == "config-only") g_pConfigManager->m_bForceReload = true;
g_pConfigManager->m_bNoMonitorReload = true;
g_pConfigManager->reload(); if (REQMODE == "config-only") {
g_pConfigManager->m_bNoMonitorReload = true;
}
g_pConfigManager->tick();
return "ok"; return "ok";
} }
static std::string killRequest(eHyprCtlOutputFormat format, std::string request) { std::string killRequest(eHyprCtlOutputFormat format, std::string request) {
g_pInputManager->setClickMode(CLICKMODE_KILL); g_pInputManager->setClickMode(CLICKMODE_KILL);
return "ok"; return "ok";
} }
static std::string splashRequest(eHyprCtlOutputFormat format, std::string request) { std::string splashRequest(eHyprCtlOutputFormat format, std::string request) {
return g_pCompositor->m_szCurrentSplash; return g_pCompositor->m_szCurrentSplash;
} }
static std::string cursorPosRequest(eHyprCtlOutputFormat format, std::string request) { std::string cursorPosRequest(eHyprCtlOutputFormat format, std::string request) {
const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal().floor(); const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal().floor();
if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) { if (format == eHyprCtlOutputFormat::FORMAT_NORMAL) {
@@ -1160,33 +1148,41 @@ static std::string cursorPosRequest(eHyprCtlOutputFormat format, std::string req
return "error"; return "error";
} }
static std::string dispatchBatch(eHyprCtlOutputFormat format, std::string request) { std::string dispatchBatch(eHyprCtlOutputFormat format, std::string request) {
// split by ; ignores ; inside [] and adds ; on last command // split by ;
request = request.substr(9); request = request.substr(9);
std::string reply = ""; std::string curitem = "";
const std::string DELIMITER = "\n\n\n"; std::string reply = "";
int bracket = 0;
size_t idx = 0;
for (size_t i = 0; i <= request.size(); ++i) { auto nextItem = [&]() {
char ch = (i < request.size()) ? request[i] : ';'; auto idx = request.find_first_of(';');
if (ch == '[')
++bracket; if (idx != std::string::npos) {
else if (ch == ']') curitem = request.substr(0, idx);
--bracket; request = request.substr(idx + 1);
else if (ch == ';' && bracket == 0) { } else {
if (idx < i) curitem = request;
reply += g_pHyprCtl->getReply(trim(request.substr(idx, i - idx))).append(DELIMITER); request = "";
idx = i + 1;
continue;
} }
curitem = trim(curitem);
};
nextItem();
const std::string DELIMITER = "\n\n\n";
while (curitem != "" || request != "") {
reply += g_pHyprCtl->getReply(curitem) + DELIMITER;
nextItem();
} }
return reply.substr(0, std::max(static_cast<int>(reply.size() - DELIMITER.size()), 0)); return reply.substr(0, std::max(static_cast<int>(reply.size() - DELIMITER.size()), 0));
} }
static std::string dispatchSetCursor(eHyprCtlOutputFormat format, std::string request) { std::string dispatchSetCursor(eHyprCtlOutputFormat format, std::string request) {
CVarList vars(request, 0, ' '); CVarList vars(request, 0, ' ');
const auto SIZESTR = vars[vars.size() - 1]; const auto SIZESTR = vars[vars.size() - 1];
@@ -1210,7 +1206,7 @@ static std::string dispatchSetCursor(eHyprCtlOutputFormat format, std::string re
return "ok"; return "ok";
} }
static std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string request) { std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::string request) {
CVarList vars(request, 0, ' '); CVarList vars(request, 0, ' ');
const auto KB = vars[1]; const auto KB = vars[1];
@@ -1285,7 +1281,7 @@ static std::string switchXKBLayoutRequest(eHyprCtlOutputFormat format, std::stri
return "ok"; return "ok";
} }
static std::string dispatchSeterror(eHyprCtlOutputFormat format, std::string request) { std::string dispatchSeterror(eHyprCtlOutputFormat format, std::string request) {
CVarList vars(request, 0, ' '); CVarList vars(request, 0, ' ');
std::string errorMessage = ""; std::string errorMessage = "";
@@ -1314,12 +1310,12 @@ static std::string dispatchSeterror(eHyprCtlOutputFormat format, std::string req
return "ok"; return "ok";
} }
static std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) { std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) {
auto result = g_pKeybindManager->m_mDispatchers["setprop"](request.substr(request.find_first_of(' ') + 1)); auto result = g_pKeybindManager->m_mDispatchers["setprop"](request.substr(request.find_first_of(' ') + 1, -1));
return "DEPRECATED: use hyprctl dispatch setprop instead" + (result.success ? "" : "\n" + result.error); return "DEPRECATED: use hyprctl dispatch setprop instead" + (result.success ? "" : "\n" + result.error);
} }
static std::string dispatchGetOption(eHyprCtlOutputFormat format, std::string request) { std::string dispatchGetOption(eHyprCtlOutputFormat format, std::string request) {
std::string curitem = ""; std::string curitem = "";
auto nextItem = [&]() { auto nextItem = [&]() {
@@ -1375,7 +1371,7 @@ static std::string dispatchGetOption(eHyprCtlOutputFormat format, std::string re
return "invalid type (internal error)"; return "invalid type (internal error)";
} }
static std::string decorationRequest(eHyprCtlOutputFormat format, std::string request) { std::string decorationRequest(eHyprCtlOutputFormat format, std::string request) {
CVarList vars(request, 0, ' '); CVarList vars(request, 0, ' ');
const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[1]); const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[1]);
@@ -1401,7 +1397,7 @@ static std::string decorationRequest(eHyprCtlOutputFormat format, std::string re
return result; return result;
} }
static std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) { std::string dispatchOutput(eHyprCtlOutputFormat format, std::string request) {
CVarList vars(request, 0, ' '); CVarList vars(request, 0, ' ');
if (vars.size() < 2) if (vars.size() < 2)
@@ -1456,7 +1452,7 @@ static std::string dispatchOutput(eHyprCtlOutputFormat format, std::string reque
return "ok"; return "ok";
} }
static std::string dispatchPlugin(eHyprCtlOutputFormat format, std::string request) { std::string dispatchPlugin(eHyprCtlOutputFormat format, std::string request) {
CVarList vars(request, 0, ' '); CVarList vars(request, 0, ' ');
if (vars.size() < 2) if (vars.size() < 2)
@@ -1525,7 +1521,7 @@ static std::string dispatchPlugin(eHyprCtlOutputFormat format, std::string reque
return "ok"; return "ok";
} }
static std::string dispatchNotify(eHyprCtlOutputFormat format, std::string request) { std::string dispatchNotify(eHyprCtlOutputFormat format, std::string request) {
CVarList vars(request, 0, ' '); CVarList vars(request, 0, ' ');
if (vars.size() < 5) if (vars.size() < 5)
@@ -1580,7 +1576,7 @@ static std::string dispatchNotify(eHyprCtlOutputFormat format, std::string reque
return "ok"; return "ok";
} }
static std::string dispatchDismissNotify(eHyprCtlOutputFormat format, std::string request) { std::string dispatchDismissNotify(eHyprCtlOutputFormat format, std::string request) {
CVarList vars(request, 0, ' '); CVarList vars(request, 0, ' ');
int amount = -1; int amount = -1;
@@ -1600,7 +1596,7 @@ static std::string dispatchDismissNotify(eHyprCtlOutputFormat format, std::strin
return "ok"; return "ok";
} }
static std::string getIsLocked(eHyprCtlOutputFormat format, std::string request) { std::string getIsLocked(eHyprCtlOutputFormat format, std::string request) {
std::string lockedStr = g_pSessionLockManager->isSessionLocked() ? "true" : "false"; std::string lockedStr = g_pSessionLockManager->isSessionLocked() ? "true" : "false";
if (format == eHyprCtlOutputFormat::FORMAT_JSON) if (format == eHyprCtlOutputFormat::FORMAT_JSON)
lockedStr = std::format(R"#( lockedStr = std::format(R"#(
@@ -1612,7 +1608,7 @@ static std::string getIsLocked(eHyprCtlOutputFormat format, std::string request)
return lockedStr; return lockedStr;
} }
static std::string getDescriptions(eHyprCtlOutputFormat format, std::string request) { std::string getDescriptions(eHyprCtlOutputFormat format, std::string request) {
std::string json = "{"; std::string json = "{";
const auto& DESCS = g_pConfigManager->getAllDescriptions(); const auto& DESCS = g_pConfigManager->getAllDescriptions();
@@ -1627,7 +1623,7 @@ static std::string getDescriptions(eHyprCtlOutputFormat format, std::string requ
return json; return json;
} }
static std::string submapRequest(eHyprCtlOutputFormat format, std::string request) { std::string submapRequest(eHyprCtlOutputFormat format, std::string request) {
std::string submap = g_pKeybindManager->getCurrentSubmap(); std::string submap = g_pKeybindManager->getCurrentSubmap();
if (submap.empty()) if (submap.empty())
submap = "default"; submap = "default";
@@ -1796,7 +1792,7 @@ std::string CHyprCtl::makeDynamicCall(const std::string& input) {
return getReply(input); return getReply(input);
} }
static bool successWrite(int fd, const std::string& data, bool needLog = true) { bool successWrite(int fd, const std::string& data, bool needLog = true) {
if (write(fd, data.c_str(), data.length()) > 0) if (write(fd, data.c_str(), data.length()) > 0)
return true; return true;
@@ -1809,7 +1805,7 @@ static bool successWrite(int fd, const std::string& data, bool needLog = true) {
return false; return false;
} }
static void runWritingDebugLogThread(const int conn) { void runWritingDebugLogThread(const int conn) {
using namespace std::chrono_literals; using namespace std::chrono_literals;
Debug::log(LOG, "In followlog thread, got connection, start writing: {}", conn); Debug::log(LOG, "In followlog thread, got connection, start writing: {}", conn);
//will be finished, when reading side close connection //will be finished, when reading side close connection
@@ -1832,11 +1828,11 @@ static void runWritingDebugLogThread(const int conn) {
}).detach(); }).detach();
} }
static bool isFollowUpRollingLogRequest(const std::string& request) { bool isFollowUpRollingLogRequest(const std::string& request) {
return request.contains("rollinglog") && request.contains("f"); return request.contains("rollinglog") && request.contains("f");
} }
static int hyprCtlFDTick(int fd, uint32_t mask, void* data) { int hyprCtlFDTick(int fd, uint32_t mask, void* data) {
if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP) if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP)
return 0; return 0;

View File

@@ -1,8 +1,8 @@
#pragma once #pragma once
#include "../Compositor.hpp"
#include <fstream> #include <fstream>
#include "../helpers/MiscFunctions.hpp" #include "../helpers/MiscFunctions.hpp"
#include "../desktop/Window.hpp"
#include <functional> #include <functional>
// exposed for main.cpp // exposed for main.cpp
@@ -38,4 +38,4 @@ class CHyprCtl {
std::string m_socketPath; std::string m_socketPath;
}; };
inline UP<CHyprCtl> g_pHyprCtl; inline std::unique_ptr<CHyprCtl> g_pHyprCtl;

View File

@@ -2,9 +2,6 @@
#include "HyprDebugOverlay.hpp" #include "HyprDebugOverlay.hpp"
#include "config/ConfigValue.hpp" #include "config/ConfigValue.hpp"
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "../render/pass/TexPassElement.hpp"
#include "../render/Renderer.hpp"
#include "../managers/AnimationManager.hpp"
CHyprDebugOverlay::CHyprDebugOverlay() { CHyprDebugOverlay::CHyprDebugOverlay() {
m_pTexture = makeShared<CTexture>(); m_pTexture = makeShared<CTexture>();
@@ -198,10 +195,10 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
double posX = 0, posY = 0; double posX = 0, posY = 0;
cairo_get_current_point(cr, &posX, &posY); cairo_get_current_point(cr, &posX, &posY);
g_pHyprRenderer->damageBox(m_wbLastDrawnBox); g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
m_wbLastDrawnBox = {(int)g_pCompositor->m_vMonitors.front()->vecPosition.x + MARGIN_LEFT - 1, (int)g_pCompositor->m_vMonitors.front()->vecPosition.y + offset + MARGIN_TOP - 1, m_wbLastDrawnBox = {(int)g_pCompositor->m_vMonitors.front()->vecPosition.x + MARGIN_LEFT - 1, (int)g_pCompositor->m_vMonitors.front()->vecPosition.y + offset + MARGIN_TOP - 1,
(int)maxTextW + 2, posY - offset - MARGIN_TOP + 2}; (int)maxTextW + 2, posY - offset - MARGIN_TOP + 2};
g_pHyprRenderer->damageBox(m_wbLastDrawnBox); g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
return posY - offset; return posY - offset;
} }
@@ -271,8 +268,6 @@ void CHyprDebugOverlay::draw() {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.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);
CTexPassElement::SRenderData data; CBox pMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
data.tex = m_pTexture; g_pHyprOpenGL->renderTexture(m_pTexture, &pMonBox, 1.f);
data.box = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
g_pHyprRenderer->m_sRenderPass.add(makeShared<CTexPassElement>(data));
} }

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "../defines.hpp" #include "../defines.hpp"
#include "../helpers/Monitor.hpp"
#include "../render/Texture.hpp" #include "../render/Texture.hpp"
#include <cairo/cairo.h> #include <cairo/cairo.h>
#include <map> #include <map>
@@ -48,4 +49,4 @@ class CHyprDebugOverlay {
friend class CHyprRenderer; friend class CHyprRenderer;
}; };
inline UP<CHyprDebugOverlay> g_pDebugOverlay; inline std::unique_ptr<CHyprDebugOverlay> g_pDebugOverlay;

View File

@@ -3,13 +3,8 @@
#include "HyprNotificationOverlay.hpp" #include "HyprNotificationOverlay.hpp"
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "../config/ConfigValue.hpp" #include "../config/ConfigValue.hpp"
#include "../render/pass/TexPassElement.hpp"
#include "../managers/AnimationManager.hpp" inline auto iconBackendFromLayout(PangoLayout* layout) {
#include "../managers/HookSystemManager.hpp"
#include "../render/Renderer.hpp"
static inline auto iconBackendFromLayout(PangoLayout* layout) {
// preference: Nerd > FontAwesome > text // preference: Nerd > FontAwesome > text
auto eIconBackendChecks = std::array<eIconBackend, 2>{ICONS_BACKEND_NF, ICONS_BACKEND_FA}; auto eIconBackendChecks = std::array<eIconBackend, 2>{ICONS_BACKEND_NF, ICONS_BACKEND_FA};
for (auto iconID : eIconBackendChecks) { for (auto iconID : eIconBackendChecks) {
@@ -26,7 +21,7 @@ CHyprNotificationOverlay::CHyprNotificationOverlay() {
if (m_vNotifications.size() == 0) if (m_vNotifications.size() == 0)
return; return;
g_pHyprRenderer->damageBox(m_bLastDamage); g_pHyprRenderer->damageBox(&m_bLastDamage);
}); });
m_pTexture = makeShared<CTexture>(); m_pTexture = makeShared<CTexture>();
@@ -40,7 +35,7 @@ CHyprNotificationOverlay::~CHyprNotificationOverlay() {
} }
void CHyprNotificationOverlay::addNotification(const std::string& text, const CHyprColor& color, const float timeMs, const eIcons icon, const float fontSize) { void CHyprNotificationOverlay::addNotification(const std::string& text, const CHyprColor& color, const float timeMs, const eIcons icon, const float fontSize) {
const auto PNOTIF = m_vNotifications.emplace_back(makeUnique<SNotification>()).get(); const auto PNOTIF = m_vNotifications.emplace_back(std::make_unique<SNotification>()).get();
PNOTIF->text = icon != eIcons::ICON_NONE ? " " + text /* tiny bit of padding otherwise icon touches text */ : text; PNOTIF->text = icon != eIcons::ICON_NONE ? " " + text /* tiny bit of padding otherwise icon touches text */ : text;
PNOTIF->color = color == CHyprColor(0) ? ICONS_COLORS[icon] : color; PNOTIF->color = color == CHyprColor(0) ? ICONS_COLORS[icon] : color;
@@ -225,8 +220,8 @@ void CHyprNotificationOverlay::draw(PHLMONITOR pMonitor) {
CBox damage = drawNotifications(pMonitor); CBox damage = drawNotifications(pMonitor);
g_pHyprRenderer->damageBox(damage); g_pHyprRenderer->damageBox(&damage);
g_pHyprRenderer->damageBox(m_bLastDamage); g_pHyprRenderer->damageBox(&m_bLastDamage);
g_pCompositor->scheduleFrameForMonitor(pMonitor); g_pCompositor->scheduleFrameForMonitor(pMonitor);
@@ -246,12 +241,8 @@ void CHyprNotificationOverlay::draw(PHLMONITOR pMonitor) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, MONSIZE.x, MONSIZE.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, MONSIZE.x, MONSIZE.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
CTexPassElement::SRenderData data; CBox pMonBox = {0, 0, MONSIZE.x, MONSIZE.y};
data.tex = m_pTexture; g_pHyprOpenGL->renderTexture(m_pTexture, &pMonBox, 1.f);
data.box = {0, 0, MONSIZE.x, MONSIZE.y};
data.a = 1.F;
g_pHyprRenderer->m_sRenderPass.add(makeShared<CTexPassElement>(data));
} }
bool CHyprNotificationOverlay::hasAny() { bool CHyprNotificationOverlay::hasAny() {

View File

@@ -2,6 +2,7 @@
#include "../defines.hpp" #include "../defines.hpp"
#include "../helpers/Timer.hpp" #include "../helpers/Timer.hpp"
#include "../helpers/Monitor.hpp"
#include "../render/Texture.hpp" #include "../render/Texture.hpp"
#include "../SharedDefs.hpp" #include "../SharedDefs.hpp"
@@ -46,18 +47,18 @@ class CHyprNotificationOverlay {
bool hasAny(); bool hasAny();
private: private:
CBox drawNotifications(PHLMONITOR pMonitor); CBox drawNotifications(PHLMONITOR pMonitor);
CBox m_bLastDamage; CBox m_bLastDamage;
std::vector<UP<SNotification>> m_vNotifications; std::vector<std::unique_ptr<SNotification>> m_vNotifications;
cairo_surface_t* m_pCairoSurface = nullptr; cairo_surface_t* m_pCairoSurface = nullptr;
cairo_t* m_pCairo = nullptr; cairo_t* m_pCairo = nullptr;
PHLMONITORREF m_pLastMonitor; PHLMONITORREF m_pLastMonitor;
Vector2D m_vecLastSize = Vector2D(-1, -1); Vector2D m_vecLastSize = Vector2D(-1, -1);
SP<CTexture> m_pTexture; SP<CTexture> m_pTexture;
}; };
inline UP<CHyprNotificationOverlay> g_pHyprNotificationOverlay; inline std::unique_ptr<CHyprNotificationOverlay> g_pHyprNotificationOverlay;

View File

@@ -1,5 +1,6 @@
#include "Log.hpp" #include "Log.hpp"
#include "../defines.hpp" #include "../defines.hpp"
#include "../Compositor.hpp"
#include "RollingLogFollow.hpp" #include "RollingLogFollow.hpp"
#include <fstream> #include <fstream>

View File

@@ -5,6 +5,8 @@
#include <fstream> #include <fstream>
#include <chrono> #include <chrono>
#include <mutex> #include <mutex>
#include "../includes.hpp"
#include "../helpers/MiscFunctions.hpp"
#define LOGMESSAGESIZE 1024 #define LOGMESSAGESIZE 1024
#define ROLLING_LOG_SIZE 4096 #define ROLLING_LOG_SIZE 4096

View File

@@ -1,5 +1,3 @@
#pragma once
#include "includes.hpp" #include "includes.hpp"
#include "debug/Log.hpp" #include "debug/Log.hpp"
#include "helpers/Color.hpp" #include "helpers/Color.hpp"

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#include "../helpers/memory/Memory.hpp" #include "../macros.hpp"
class CWorkspace; class CWorkspace;
class CWindow; class CWindow;
class CLayerSurface; class CLayerSurface;

View File

@@ -1,4 +1,3 @@
#include <re2/re2.h>
#include "LayerRule.hpp" #include "LayerRule.hpp"
#include <unordered_set> #include <unordered_set>
#include <algorithm> #include <algorithm>

View File

@@ -2,7 +2,6 @@
#include <string> #include <string>
#include <cstdint> #include <cstdint>
#include "Rule.hpp"
class CLayerRule { class CLayerRule {
public: public:
@@ -22,10 +21,8 @@ class CLayerRule {
RULE_ZUMBA, RULE_ZUMBA,
}; };
eRuleType ruleType = RULE_INVALID; eRuleType ruleType = RULE_INVALID;
const std::string targetNamespace; const std::string targetNamespace;
const std::string rule; const std::string rule;
CRuleRegexContainer targetNamespaceRegex;
}; };

View File

@@ -4,13 +4,6 @@
#include "../protocols/LayerShell.hpp" #include "../protocols/LayerShell.hpp"
#include "../protocols/core/Compositor.hpp" #include "../protocols/core/Compositor.hpp"
#include "../managers/SeatManager.hpp" #include "../managers/SeatManager.hpp"
#include "../managers/AnimationManager.hpp"
#include "../render/Renderer.hpp"
#include "../config/ConfigManager.hpp"
#include "../helpers/Monitor.hpp"
#include "../managers/input/InputManager.hpp"
#include "../managers/HookSystemManager.hpp"
#include "../managers/EventManager.hpp"
PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) { PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) {
PHLLS pLS = SP<CLayerSurface>(new CLayerSurface(resource)); PHLLS pLS = SP<CLayerSurface>(new CLayerSurface(resource));
@@ -31,21 +24,23 @@ PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) {
pLS->szNamespace = resource->layerNamespace; pLS->szNamespace = resource->layerNamespace;
pLS->layer = resource->current.layer; pLS->layer = resource->current.layer;
pLS->popupHead = makeUnique<CPopup>(pLS); pLS->popupHead = std::make_unique<CPopup>(pLS);
pLS->popupHead->m_pSelf = pLS->popupHead; pLS->monitor = pMonitor;
pLS->monitor = pMonitor;
pMonitor->m_aLayerSurfaceLayers[resource->current.layer].emplace_back(pLS); pMonitor->m_aLayerSurfaceLayers[resource->current.layer].emplace_back(pLS);
pLS->forceBlur = g_pConfigManager->shouldBlurLS(pLS->szNamespace); pLS->forceBlur = g_pConfigManager->shouldBlurLS(pLS->szNamespace);
g_pAnimationManager->createAnimation(0.f, pLS->alpha, g_pConfigManager->getAnimationPropertyConfig("fadeLayersIn"), pLS, AVARDAMAGE_ENTIRE); pLS->alpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeLayersIn"), pLS, AVARDAMAGE_ENTIRE);
g_pAnimationManager->createAnimation(Vector2D(0, 0), pLS->realPosition, g_pConfigManager->getAnimationPropertyConfig("layersIn"), pLS, AVARDAMAGE_ENTIRE); pLS->realPosition.create(g_pConfigManager->getAnimationPropertyConfig("layersIn"), pLS, AVARDAMAGE_ENTIRE);
g_pAnimationManager->createAnimation(Vector2D(0, 0), pLS->realSize, g_pConfigManager->getAnimationPropertyConfig("layersIn"), pLS, AVARDAMAGE_ENTIRE); pLS->realSize.create(g_pConfigManager->getAnimationPropertyConfig("layersIn"), pLS, AVARDAMAGE_ENTIRE);
pLS->alpha.registerVar();
pLS->realPosition.registerVar();
pLS->realSize.registerVar();
pLS->registerCallbacks(); pLS->registerCallbacks();
pLS->alpha->setValueAndWarp(0.f); pLS->alpha.setValueAndWarp(0.f);
Debug::log(LOG, "LayerSurface {:x} (namespace {} layer {}) created on monitor {}", (uintptr_t)resource.get(), resource->layerNamespace, (int)pLS->layer, pMonitor->szName); Debug::log(LOG, "LayerSurface {:x} (namespace {} layer {}) created on monitor {}", (uintptr_t)resource.get(), resource->layerNamespace, (int)pLS->layer, pMonitor->szName);
@@ -53,7 +48,7 @@ PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) {
} }
void CLayerSurface::registerCallbacks() { void CLayerSurface::registerCallbacks() {
alpha->setUpdateCallback([this](auto) { alpha.setUpdateCallback([this](void*) {
if (dimAround) if (dimAround)
g_pHyprRenderer->damageMonitor(monitor.lock()); g_pHyprRenderer->damageMonitor(monitor.lock());
}); });
@@ -98,7 +93,7 @@ void CLayerSurface::onDestroy() {
onUnmap(); onUnmap();
} else { } else {
Debug::log(LOG, "Removing LayerSurface that wasn't mapped."); Debug::log(LOG, "Removing LayerSurface that wasn't mapped.");
alpha->setValueAndWarp(0.f); alpha.setValueAndWarp(0.f);
fadingOut = true; fadingOut = true;
g_pCompositor->addToFadingOutSafe(self.lock()); g_pCompositor->addToFadingOutSafe(self.lock());
} }
@@ -115,7 +110,7 @@ void CLayerSurface::onDestroy() {
// and damage // and damage
CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height}; CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height};
g_pHyprRenderer->damageBox(geomFixed); g_pHyprRenderer->damageBox(&geomFixed);
} }
readyToDelete = true; readyToDelete = true;
@@ -179,7 +174,7 @@ void CLayerSurface::onMap() {
position = Vector2D(geometry.x, geometry.y); position = Vector2D(geometry.x, geometry.y);
CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height}; CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height};
g_pHyprRenderer->damageBox(geomFixed); g_pHyprRenderer->damageBox(&geomFixed);
const bool FULLSCREEN = PMONITOR->activeWorkspace && PMONITOR->activeWorkspace->m_bHasFullscreenWindow && PMONITOR->activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN; const bool FULLSCREEN = PMONITOR->activeWorkspace && PMONITOR->activeWorkspace->m_bHasFullscreenWindow && PMONITOR->activeWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN;
startAnimation(!(layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS)); startAnimation(!(layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS));
@@ -215,7 +210,7 @@ void CLayerSurface::onUnmap() {
} }
// make a snapshot and start fade // make a snapshot and start fade
g_pHyprRenderer->makeLayerSnapshot(self.lock()); g_pHyprOpenGL->makeLayerSnapshot(self.lock());
startAnimation(false); startAnimation(false);
@@ -240,13 +235,13 @@ void CLayerSurface::onUnmap() {
g_pSeatManager->setKeyboardFocus(g_pCompositor->m_pLastFocus.lock()); g_pSeatManager->setKeyboardFocus(g_pCompositor->m_pLastFocus.lock());
CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height}; CBox geomFixed = {geometry.x + PMONITOR->vecPosition.x, geometry.y + PMONITOR->vecPosition.y, geometry.width, geometry.height};
g_pHyprRenderer->damageBox(geomFixed); g_pHyprRenderer->damageBox(&geomFixed);
geomFixed = {geometry.x + (int)PMONITOR->vecPosition.x, geometry.y + (int)PMONITOR->vecPosition.y, (int)layerSurface->surface->current.size.x, geomFixed = {geometry.x + (int)PMONITOR->vecPosition.x, geometry.y + (int)PMONITOR->vecPosition.y, (int)layerSurface->surface->current.size.x,
(int)layerSurface->surface->current.size.y}; (int)layerSurface->surface->current.size.y};
g_pHyprRenderer->damageBox(geomFixed); g_pHyprRenderer->damageBox(&geomFixed);
g_pInputManager->simulateMouseMovement(); g_pInputManager->sendMotionEventsToFocused();
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID); g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->ID);
} }
@@ -275,7 +270,7 @@ void CLayerSurface::onCommit() {
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd
CBox geomFixed = {geometry.x, geometry.y, geometry.width, geometry.height}; CBox geomFixed = {geometry.x, geometry.y, geometry.width, geometry.height};
g_pHyprRenderer->damageBox(geomFixed); g_pHyprRenderer->damageBox(&geomFixed);
if (layerSurface->current.committed != 0) { if (layerSurface->current.committed != 0) {
if (layerSurface->current.committed & CLayerShellResource::eCommittedState::STATE_LAYER) { if (layerSurface->current.committed & CLayerShellResource::eCommittedState::STATE_LAYER) {
@@ -312,17 +307,17 @@ void CLayerSurface::onCommit() {
} }
} }
if (realPosition->goal() != geometry.pos()) { if (realPosition.goal() != geometry.pos()) {
if (realPosition->isBeingAnimated()) if (realPosition.isBeingAnimated())
*realPosition = geometry.pos(); realPosition = geometry.pos();
else else
realPosition->setValueAndWarp(geometry.pos()); realPosition.setValueAndWarp(geometry.pos());
} }
if (realSize->goal() != geometry.size()) { if (realSize.goal() != geometry.size()) {
if (realSize->isBeingAnimated()) if (realSize.isBeingAnimated())
*realSize = geometry.size(); realSize = geometry.size();
else else
realSize->setValueAndWarp(geometry.size()); realSize.setValueAndWarp(geometry.size());
} }
if (mapped && (layerSurface->current.committed & CLayerShellResource::eCommittedState::STATE_INTERACTIVITY)) { if (mapped && (layerSurface->current.committed & CLayerShellResource::eCommittedState::STATE_INTERACTIVITY)) {
@@ -332,7 +327,7 @@ void CLayerSurface::onCommit() {
nullptr); nullptr);
if (!WASLASTFOCUS && popupHead) { if (!WASLASTFOCUS && popupHead) {
popupHead->breadthfirst( popupHead->breadthfirst(
[&WASLASTFOCUS](WP<CPopup> popup, void* data) { [&WASLASTFOCUS](CPopup* popup, void* data) {
WASLASTFOCUS = WASLASTFOCUS || (popup->m_pWLSurface && g_pSeatManager->state.keyboardFocus == popup->m_pWLSurface->resource()); WASLASTFOCUS = WASLASTFOCUS || (popup->m_pWLSurface && g_pSeatManager->state.keyboardFocus == popup->m_pWLSurface->resource());
}, },
nullptr); nullptr);
@@ -439,17 +434,17 @@ void CLayerSurface::applyRules() {
} }
void CLayerSurface::startAnimation(bool in, bool instant) { void CLayerSurface::startAnimation(bool in, bool instant) {
const auto ANIMSTYLE = animationStyle.value_or(realPosition.m_pConfig->pValues->internalStyle);
if (in) { if (in) {
realPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersIn")); realPosition.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("layersIn");
realSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersIn")); realSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("layersIn");
alpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeLayersIn")); alpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeLayersIn");
} else { } else {
realPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersOut")); realPosition.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("layersOut");
realSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("layersOut")); realSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("layersOut");
alpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeLayersOut")); alpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeLayersOut");
} }
const auto ANIMSTYLE = animationStyle.value_or(realPosition->getStyle());
if (ANIMSTYLE.starts_with("slide")) { if (ANIMSTYLE.starts_with("slide")) {
// get closest edge // get closest edge
const auto MIDDLE = geometry.middle(); const auto MIDDLE = geometry.middle();
@@ -490,9 +485,9 @@ void CLayerSurface::startAnimation(bool in, bool instant) {
} }
} }
realSize->setValueAndWarp(geometry.size()); realSize.setValueAndWarp(geometry.size());
alpha->setValueAndWarp(in ? 0.f : 1.f); alpha.setValueAndWarp(in ? 0.f : 1.f);
*alpha = in ? 1.f : 0.f; alpha = in ? 1.f : 0.f;
Vector2D prePos; Vector2D prePos;
@@ -517,11 +512,11 @@ void CLayerSurface::startAnimation(bool in, bool instant) {
} }
if (in) { if (in) {
realPosition->setValueAndWarp(prePos); realPosition.setValueAndWarp(prePos);
*realPosition = geometry.pos(); realPosition = geometry.pos();
} else { } else {
realPosition->setValueAndWarp(geometry.pos()); realPosition.setValueAndWarp(geometry.pos());
*realPosition = prePos; realPosition = prePos;
} }
} else if (ANIMSTYLE.starts_with("popin")) { } else if (ANIMSTYLE.starts_with("popin")) {
@@ -540,25 +535,25 @@ void CLayerSurface::startAnimation(bool in, bool instant) {
const auto GOALSIZE = (geometry.size() * minPerc).clamp({5, 5}); const auto GOALSIZE = (geometry.size() * minPerc).clamp({5, 5});
const auto GOALPOS = geometry.pos() + (geometry.size() - GOALSIZE) / 2.f; const auto GOALPOS = geometry.pos() + (geometry.size() - GOALSIZE) / 2.f;
alpha->setValueAndWarp(in ? 0.f : 1.f); alpha.setValueAndWarp(in ? 0.f : 1.f);
*alpha = in ? 1.f : 0.f; alpha = in ? 1.f : 0.f;
if (in) { if (in) {
realSize->setValueAndWarp(GOALSIZE); realSize.setValueAndWarp(GOALSIZE);
realPosition->setValueAndWarp(GOALPOS); realPosition.setValueAndWarp(GOALPOS);
*realSize = geometry.size(); realSize = geometry.size();
*realPosition = geometry.pos(); realPosition = geometry.pos();
} else { } else {
realSize->setValueAndWarp(geometry.size()); realSize.setValueAndWarp(geometry.size());
realPosition->setValueAndWarp(geometry.pos()); realPosition.setValueAndWarp(geometry.pos());
*realSize = GOALSIZE; realSize = GOALSIZE;
*realPosition = GOALPOS; realPosition = GOALPOS;
} }
} else { } else {
// fade // fade
realPosition->setValueAndWarp(geometry.pos()); realPosition.setValueAndWarp(geometry.pos());
realSize->setValueAndWarp(geometry.size()); realSize.setValueAndWarp(geometry.size());
*alpha = in ? 1.f : 0.f; alpha = in ? 1.f : 0.f;
} }
if (!in) if (!in)
@@ -569,7 +564,7 @@ bool CLayerSurface::isFadedOut() {
if (!fadingOut) if (!fadingOut)
return false; return false;
return !realPosition->isBeingAnimated() && !realSize->isBeingAnimated() && !alpha->isBeingAnimated(); return !realPosition.isBeingAnimated() && !realSize.isBeingAnimated() && !alpha.isBeingAnimated();
} }
int CLayerSurface::popupsCount() { int CLayerSurface::popupsCount() {
@@ -577,7 +572,7 @@ int CLayerSurface::popupsCount() {
return 0; return 0;
int no = -1; // we have one dummy int no = -1; // we have one dummy
popupHead->breadthfirst([](WP<CPopup> p, void* data) { *(int*)data += 1; }, &no); popupHead->breadthfirst([](CPopup* p, void* data) { *(int*)data += 1; }, &no);
return no; return no;
} }

View File

@@ -4,6 +4,7 @@
#include "../defines.hpp" #include "../defines.hpp"
#include "WLSurface.hpp" #include "WLSurface.hpp"
#include "../helpers/AnimatedVariable.hpp" #include "../helpers/AnimatedVariable.hpp"
#include "LayerRule.hpp"
class CLayerShellResource; class CLayerShellResource;
@@ -17,17 +18,17 @@ class CLayerSurface {
public: public:
~CLayerSurface(); ~CLayerSurface();
void applyRules(); void applyRules();
void startAnimation(bool in, bool instant = false); void startAnimation(bool in, bool instant = false);
bool isFadedOut(); bool isFadedOut();
int popupsCount(); int popupsCount();
PHLANIMVAR<Vector2D> realPosition; CAnimatedVariable<Vector2D> realPosition;
PHLANIMVAR<Vector2D> realSize; CAnimatedVariable<Vector2D> realSize;
PHLANIMVAR<float> alpha; CAnimatedVariable<float> alpha;
WP<CLayerShellResource> layerSurface; WP<CLayerShellResource> layerSurface;
wl_list link; wl_list link;
// the header providing the enum type cannot be imported here // the header providing the enum type cannot be imported here
int interactivity = 0; int interactivity = 0;
@@ -59,7 +60,7 @@ class CLayerSurface {
CBox geometry = {0, 0, 0, 0}; CBox geometry = {0, 0, 0, 0};
Vector2D position; Vector2D position;
std::string szNamespace = ""; std::string szNamespace = "";
UP<CPopup> popupHead; std::unique_ptr<CPopup> popupHead;
void onDestroy(); void onDestroy();
void onMap(); void onMap();

View File

@@ -6,10 +6,6 @@
#include "../protocols/core/Compositor.hpp" #include "../protocols/core/Compositor.hpp"
#include "../managers/SeatManager.hpp" #include "../managers/SeatManager.hpp"
#include "../managers/eventLoop/EventLoopManager.hpp" #include "../managers/eventLoop/EventLoopManager.hpp"
#include "../desktop/LayerSurface.hpp"
#include "../managers/input/InputManager.hpp"
#include "../render/Renderer.hpp"
#include "../render/OpenGL.hpp"
#include <ranges> #include <ranges>
CPopup::CPopup(PHLWINDOW pOwner) : m_pWindowOwner(pOwner) { CPopup::CPopup(PHLWINDOW pOwner) : m_pWindowOwner(pOwner) {
@@ -20,8 +16,7 @@ CPopup::CPopup(PHLLS pOwner) : m_pLayerOwner(pOwner) {
initAllSignals(); initAllSignals();
} }
CPopup::CPopup(SP<CXDGPopupResource> popup, WP<CPopup> pOwner) : CPopup::CPopup(SP<CXDGPopupResource> popup, CPopup* pOwner) : m_pWindowOwner(pOwner->m_pWindowOwner), m_pLayerOwner(pOwner->m_pLayerOwner), m_pParent(pOwner), m_pResource(popup) {
m_pWindowOwner(pOwner->m_pWindowOwner), m_pLayerOwner(pOwner->m_pLayerOwner), m_pParent(pOwner), m_pResource(popup) {
m_pWLSurface = CWLSurface::create(); m_pWLSurface = CWLSurface::create();
m_pWLSurface->assign(popup->surface->surface.lock(), this); m_pWLSurface->assign(popup->surface->surface.lock(), this);
@@ -59,8 +54,7 @@ void CPopup::initAllSignals() {
} }
void CPopup::onNewPopup(SP<CXDGPopupResource> popup) { void CPopup::onNewPopup(SP<CXDGPopupResource> popup) {
const auto& POPUP = m_vChildren.emplace_back(makeShared<CPopup>(popup, m_pSelf)); const auto POPUP = m_vChildren.emplace_back(makeShared<CPopup>(popup, this)).get();
POPUP->m_pSelf = POPUP;
Debug::log(LOG, "New popup at {:x}", (uintptr_t)POPUP); Debug::log(LOG, "New popup at {:x}", (uintptr_t)POPUP);
} }
@@ -85,14 +79,13 @@ void CPopup::onMap() {
CBox box = m_pWLSurface->resource()->extends(); CBox box = m_pWLSurface->resource()->extends();
box.translate(COORDS).expand(4); box.translate(COORDS).expand(4);
g_pHyprRenderer->damageBox(box); g_pHyprRenderer->damageBox(&box);
m_vLastPos = coordsRelativeToParent(); m_vLastPos = coordsRelativeToParent();
g_pInputManager->simulateMouseMovement(); g_pInputManager->simulateMouseMovement();
m_pSubsurfaceHead = makeUnique<CSubsurface>(m_pSelf); m_pSubsurfaceHead = std::make_unique<CSubsurface>(this);
m_pSubsurfaceHead->m_pSelf = m_pSubsurfaceHead;
//unconstrain(); //unconstrain();
sendScale(); sendScale();
@@ -120,7 +113,7 @@ void CPopup::onUnmap() {
CBox box = m_pWLSurface->resource()->extends(); CBox box = m_pWLSurface->resource()->extends();
box.translate(COORDS).expand(4); box.translate(COORDS).expand(4);
g_pHyprRenderer->damageBox(box); g_pHyprRenderer->damageBox(&box);
m_pSubsurfaceHead.reset(); m_pSubsurfaceHead.reset();
@@ -129,20 +122,19 @@ void CPopup::onUnmap() {
// damage all children // damage all children
breadthfirst( breadthfirst(
[](WP<CPopup> p, void* data) { [](CPopup* p, void* data) {
if (!p->m_pResource) if (!p->m_pResource)
return; return;
auto box = CBox{p->coordsGlobal(), p->size()}; auto box = CBox{p->coordsGlobal(), p->size()};
g_pHyprRenderer->damageBox(box); g_pHyprRenderer->damageBox(&box);
}, },
nullptr); nullptr);
// TODO: probably refocus, but without a motion event? const bool WASLASTFOCUS = g_pSeatManager->state.keyboardFocus == m_pWLSurface->resource() || g_pSeatManager->state.pointerFocus == m_pWLSurface->resource();
// const bool WASLASTFOCUS = g_pSeatManager->state.keyboardFocus == m_pWLSurface->resource() || g_pSeatManager->state.pointerFocus == m_pWLSurface->resource();
// if (WASLASTFOCUS) if (WASLASTFOCUS)
// g_pInputManager->simulateMouseMovement(); g_pInputManager->simulateMouseMovement();
} }
void CPopup::onCommit(bool ignoreSiblings) { void CPopup::onCommit(bool ignoreSiblings) {
@@ -174,10 +166,10 @@ void CPopup::onCommit(bool ignoreSiblings) {
if (m_vLastSize != m_pResource->surface->surface->current.size || m_bRequestedReposition || m_vLastPos != COORDSLOCAL) { if (m_vLastSize != m_pResource->surface->surface->current.size || m_bRequestedReposition || m_vLastPos != COORDSLOCAL) {
CBox box = {localToGlobal(m_vLastPos), m_vLastSize}; CBox box = {localToGlobal(m_vLastPos), m_vLastSize};
g_pHyprRenderer->damageBox(box); g_pHyprRenderer->damageBox(&box);
m_vLastSize = m_pResource->surface->surface->current.size; m_vLastSize = m_pResource->surface->surface->current.size;
box = {COORDS, m_vLastSize}; box = {COORDS, m_vLastSize};
g_pHyprRenderer->damageBox(box); g_pHyprRenderer->damageBox(&box);
m_vLastPos = COORDSLOCAL; m_vLastPos = COORDSLOCAL;
} }
@@ -227,7 +219,7 @@ Vector2D CPopup::coordsRelativeToParent() {
if (!m_pResource) if (!m_pResource)
return {}; return {};
WP<CPopup> current = m_pSelf; CPopup* current = this;
offset -= current->m_pResource->surface->current.geometry.pos(); offset -= current->m_pResource->surface->current.geometry.pos();
while (current->m_pParent && current->m_pResource) { while (current->m_pParent && current->m_pResource) {
@@ -251,16 +243,16 @@ Vector2D CPopup::localToGlobal(const Vector2D& rel) {
Vector2D CPopup::t1ParentCoords() { Vector2D CPopup::t1ParentCoords() {
if (!m_pWindowOwner.expired()) if (!m_pWindowOwner.expired())
return m_pWindowOwner->m_vRealPosition->value(); return m_pWindowOwner->m_vRealPosition.value();
if (!m_pLayerOwner.expired()) if (!m_pLayerOwner.expired())
return m_pLayerOwner->realPosition->value(); return m_pLayerOwner->realPosition.value();
ASSERT(false); ASSERT(false);
return {}; return {};
} }
void CPopup::recheckTree() { void CPopup::recheckTree() {
WP<CPopup> curr = m_pSelf; CPopup* curr = this;
while (curr->m_pParent) { while (curr->m_pParent) {
curr = curr->m_pParent; curr = curr->m_pParent;
} }
@@ -300,17 +292,17 @@ bool CPopup::visible() {
return false; return false;
} }
void CPopup::bfHelper(std::vector<WP<CPopup>> const& nodes, std::function<void(WP<CPopup>, void*)> fn, void* data) { void CPopup::bfHelper(std::vector<CPopup*> const& nodes, std::function<void(CPopup*, void*)> fn, void* data) {
for (auto const& n : nodes) { for (auto const& n : nodes) {
fn(n, data); fn(n, data);
} }
std::vector<WP<CPopup>> nodes2; std::vector<CPopup*> nodes2;
nodes2.reserve(nodes.size() * 2); nodes2.reserve(nodes.size() * 2);
for (auto const& n : nodes) { for (auto const& n : nodes) {
for (auto const& c : n->m_vChildren) { for (auto const& c : n->m_vChildren) {
nodes2.push_back(c->m_pSelf); nodes2.push_back(c.get());
} }
} }
@@ -318,15 +310,15 @@ void CPopup::bfHelper(std::vector<WP<CPopup>> const& nodes, std::function<void(W
bfHelper(nodes2, fn, data); bfHelper(nodes2, fn, data);
} }
void CPopup::breadthfirst(std::function<void(WP<CPopup>, void*)> fn, void* data) { void CPopup::breadthfirst(std::function<void(CPopup*, void*)> fn, void* data) {
std::vector<WP<CPopup>> popups; std::vector<CPopup*> popups;
popups.push_back(m_pSelf); popups.push_back(this);
bfHelper(popups, fn, data); bfHelper(popups, fn, data);
} }
WP<CPopup> CPopup::at(const Vector2D& globalCoords, bool allowsInput) { CPopup* CPopup::at(const Vector2D& globalCoords, bool allowsInput) {
std::vector<WP<CPopup>> popups; std::vector<CPopup*> popups;
breadthfirst([](WP<CPopup> popup, void* data) { ((std::vector<WP<CPopup>>*)data)->push_back(popup); }, &popups); breadthfirst([](CPopup* popup, void* data) { ((std::vector<CPopup*>*)data)->push_back(popup); }, &popups);
for (auto const& p : popups | std::views::reverse) { for (auto const& p : popups | std::views::reverse) {
if (!p->m_pResource || !p->m_bMapped) if (!p->m_pResource || !p->m_bMapped)
@@ -348,5 +340,5 @@ WP<CPopup> CPopup::at(const Vector2D& globalCoords, bool allowsInput) {
} }
} }
return {}; return nullptr;
} }

View File

@@ -1,9 +1,9 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <memory>
#include "Subsurface.hpp" #include "Subsurface.hpp"
#include "../helpers/signal/Signal.hpp" #include "../helpers/signal/Signal.hpp"
#include "../helpers/memory/Memory.hpp"
class CXDGPopupResource; class CXDGPopupResource;
@@ -14,7 +14,7 @@ class CPopup {
CPopup(PHLLS pOwner); CPopup(PHLLS pOwner);
// real nodes // real nodes
CPopup(SP<CXDGPopupResource> popup, WP<CPopup> pOwner); CPopup(SP<CXDGPopupResource> popup, CPopup* pOwner);
~CPopup(); ~CPopup();
@@ -36,12 +36,11 @@ class CPopup {
bool visible(); bool visible();
// will also loop over this node // will also loop over this node
void breadthfirst(std::function<void(WP<CPopup>, void*)> fn, void* data); void breadthfirst(std::function<void(CPopup*, void*)> fn, void* data);
WP<CPopup> at(const Vector2D& globalCoords, bool allowsInput = false); CPopup* at(const Vector2D& globalCoords, bool allowsInput = false);
// //
SP<CWLSurface> m_pWLSurface; SP<CWLSurface> m_pWLSurface;
WP<CPopup> m_pSelf;
bool m_bMapped = false; bool m_bMapped = false;
private: private:
@@ -50,7 +49,7 @@ class CPopup {
PHLLSREF m_pLayerOwner; PHLLSREF m_pLayerOwner;
// T2 owners // T2 owners
WP<CPopup> m_pParent; CPopup* m_pParent = nullptr;
WP<CXDGPopupResource> m_pResource; WP<CXDGPopupResource> m_pResource;
@@ -62,8 +61,8 @@ class CPopup {
bool m_bInert = false; bool m_bInert = false;
// //
std::vector<SP<CPopup>> m_vChildren; std::vector<SP<CPopup>> m_vChildren;
UP<CSubsurface> m_pSubsurfaceHead; std::unique_ptr<CSubsurface> m_pSubsurfaceHead;
struct { struct {
CHyprSignalListener newPopup; CHyprSignalListener newPopup;
@@ -82,5 +81,5 @@ class CPopup {
Vector2D localToGlobal(const Vector2D& rel); Vector2D localToGlobal(const Vector2D& rel);
Vector2D t1ParentCoords(); Vector2D t1ParentCoords();
static void bfHelper(std::vector<WP<CPopup>> const& nodes, std::function<void(WP<CPopup>, void*)> fn, void* data); static void bfHelper(std::vector<CPopup*> const& nodes, std::function<void(CPopup*, void*)> fn, void* data);
}; };

View File

@@ -1,22 +0,0 @@
#include <re2/re2.h>
#include "../helpers/memory/Memory.hpp"
#include "Rule.hpp"
#include "../debug/Log.hpp"
CRuleRegexContainer::CRuleRegexContainer(const std::string& regex_) {
const bool NEGATIVE = regex_.starts_with("negative:");
negative = NEGATIVE;
regex = makeUnique<RE2>(NEGATIVE ? regex_.substr(9) : regex_);
// TODO: maybe pop an error?
if (!regex->ok())
Debug::log(ERR, "RuleRegexContainer: regex {} failed to parse!", regex_);
}
bool CRuleRegexContainer::passes(const std::string& str) const {
if (!regex)
return false;
return RE2::FullMatch(str, *regex) != negative;
}

View File

@@ -1,21 +0,0 @@
#pragma once
#include <hyprutils/memory/UniquePtr.hpp>
//NOLINTNEXTLINE
namespace re2 {
class RE2;
};
class CRuleRegexContainer {
public:
CRuleRegexContainer() = default;
CRuleRegexContainer(const std::string& regex);
bool passes(const std::string& str) const;
private:
Hyprutils::Memory::CUniquePointer<re2::RE2> regex;
bool negative = false;
};

View File

@@ -4,15 +4,13 @@
#include "../config/ConfigValue.hpp" #include "../config/ConfigValue.hpp"
#include "../protocols/core/Compositor.hpp" #include "../protocols/core/Compositor.hpp"
#include "../protocols/core/Subcompositor.hpp" #include "../protocols/core/Subcompositor.hpp"
#include "../render/Renderer.hpp"
#include "../managers/input/InputManager.hpp"
CSubsurface::CSubsurface(PHLWINDOW pOwner) : m_pWindowParent(pOwner) { CSubsurface::CSubsurface(PHLWINDOW pOwner) : m_pWindowParent(pOwner) {
initSignals(); initSignals();
initExistingSubsurfaces(pOwner->m_pWLSurface->resource()); initExistingSubsurfaces(pOwner->m_pWLSurface->resource());
} }
CSubsurface::CSubsurface(WP<CPopup> pOwner) : m_pPopupParent(pOwner) { CSubsurface::CSubsurface(CPopup* pOwner) : m_pPopupParent(pOwner) {
initSignals(); initSignals();
initExistingSubsurfaces(pOwner->m_pWLSurface->resource()); initExistingSubsurfaces(pOwner->m_pWLSurface->resource());
} }
@@ -24,7 +22,7 @@ CSubsurface::CSubsurface(SP<CWLSubsurfaceResource> pSubsurface, PHLWINDOW pOwner
initExistingSubsurfaces(pSubsurface->surface.lock()); initExistingSubsurfaces(pSubsurface->surface.lock());
} }
CSubsurface::CSubsurface(SP<CWLSubsurfaceResource> pSubsurface, WP<CPopup> pOwner) : m_pSubsurface(pSubsurface), m_pPopupParent(pOwner) { CSubsurface::CSubsurface(SP<CWLSubsurfaceResource> pSubsurface, CPopup* pOwner) : m_pSubsurface(pSubsurface), m_pPopupParent(pOwner) {
m_pWLSurface = CWLSurface::create(); m_pWLSurface = CWLSurface::create();
m_pWLSurface->assign(pSubsurface->surface.lock(), this); m_pWLSurface->assign(pSubsurface->surface.lock(), this);
initSignals(); initSignals();
@@ -101,20 +99,11 @@ void CSubsurface::onCommit() {
checkSiblingDamage(); checkSiblingDamage();
if (m_vLastSize != m_pWLSurface->resource()->current.size) { if (m_vLastSize != m_pWLSurface->resource()->current.size) {
// TODO: fix this CBox box{COORDS, m_vLastSize};
// CBox box{COORDS, m_vLastSize}; g_pHyprRenderer->damageBox(&box);
// g_pHyprRenderer->damageBox(box); m_vLastSize = m_pWLSurface->resource()->current.size;
// m_vLastSize = m_pWLSurface->resource()->current.size; box = {COORDS, m_vLastSize};
// box = {COORDS, m_vLastSize}; g_pHyprRenderer->damageBox(&box);
// g_pHyprRenderer->damageBox(box);
CBox box;
if (m_pPopupParent)
box = m_pPopupParent->m_pWLSurface->getSurfaceBoxGlobal().value_or(CBox{});
else if (m_pWindowParent)
box = m_pWindowParent->getWindowMainSurfaceBox();
g_pHyprRenderer->damageBox(box);
} }
} }
@@ -132,18 +121,16 @@ void CSubsurface::onDestroy() {
} }
void CSubsurface::onNewSubsurface(SP<CWLSubsurfaceResource> pSubsurface) { void CSubsurface::onNewSubsurface(SP<CWLSubsurfaceResource> pSubsurface) {
WP<CSubsurface> PSUBSURFACE; CSubsurface* PSUBSURFACE = nullptr;
if (!m_pWindowParent.expired()) if (!m_pWindowParent.expired())
PSUBSURFACE = m_vChildren.emplace_back(makeUnique<CSubsurface>(pSubsurface, m_pWindowParent.lock())); PSUBSURFACE = m_vChildren.emplace_back(std::make_unique<CSubsurface>(pSubsurface, m_pWindowParent.lock())).get();
else if (m_pPopupParent) else if (m_pPopupParent)
PSUBSURFACE = m_vChildren.emplace_back(makeUnique<CSubsurface>(pSubsurface, m_pPopupParent)); PSUBSURFACE = m_vChildren.emplace_back(std::make_unique<CSubsurface>(pSubsurface, m_pPopupParent)).get();
PSUBSURFACE->m_pSelf = PSUBSURFACE;
ASSERT(PSUBSURFACE); ASSERT(PSUBSURFACE);
PSUBSURFACE->m_pParent = m_pSelf; PSUBSURFACE->m_pParent = this;
} }
void CSubsurface::onMap() { void CSubsurface::onMap() {
@@ -152,7 +139,7 @@ void CSubsurface::onMap() {
const auto COORDS = coordsGlobal(); const auto COORDS = coordsGlobal();
CBox box{COORDS, m_vLastSize}; CBox box{COORDS, m_vLastSize};
box.expand(4); box.expand(4);
g_pHyprRenderer->damageBox(box); g_pHyprRenderer->damageBox(&box);
if (!m_pWindowParent.expired()) if (!m_pWindowParent.expired())
m_pWindowParent->updateSurfaceScaleTransformDetails(); m_pWindowParent->updateSurfaceScaleTransformDetails();
@@ -162,7 +149,7 @@ void CSubsurface::onUnmap() {
const auto COORDS = coordsGlobal(); const auto COORDS = coordsGlobal();
CBox box{COORDS, m_vLastSize}; CBox box{COORDS, m_vLastSize};
box.expand(4); box.expand(4);
g_pHyprRenderer->damageBox(box); g_pHyprRenderer->damageBox(&box);
if (m_pWLSurface->resource() == g_pCompositor->m_pLastFocus) if (m_pWLSurface->resource() == g_pCompositor->m_pLastFocus)
g_pInputManager->releaseAllMouseButtons(); g_pInputManager->releaseAllMouseButtons();
@@ -182,7 +169,7 @@ Vector2D CSubsurface::coordsGlobal() {
Vector2D coords = coordsRelativeToParent(); Vector2D coords = coordsRelativeToParent();
if (!m_pWindowParent.expired()) if (!m_pWindowParent.expired())
coords += m_pWindowParent->m_vRealPosition->value(); coords += m_pWindowParent->m_vRealPosition.value();
else if (m_pPopupParent) else if (m_pPopupParent)
coords += m_pPopupParent->coordsGlobal(); coords += m_pPopupParent->coordsGlobal();

View File

@@ -11,30 +11,28 @@ class CSubsurface {
public: public:
// root dummy nodes // root dummy nodes
CSubsurface(PHLWINDOW pOwner); CSubsurface(PHLWINDOW pOwner);
CSubsurface(WP<CPopup> pOwner); CSubsurface(CPopup* pOwner);
// real nodes // real nodes
CSubsurface(SP<CWLSubsurfaceResource> pSubsurface, PHLWINDOW pOwner); CSubsurface(SP<CWLSubsurfaceResource> pSubsurface, PHLWINDOW pOwner);
CSubsurface(SP<CWLSubsurfaceResource> pSubsurface, WP<CPopup> pOwner); CSubsurface(SP<CWLSubsurfaceResource> pSubsurface, CPopup* pOwner);
~CSubsurface(); ~CSubsurface();
Vector2D coordsRelativeToParent(); Vector2D coordsRelativeToParent();
Vector2D coordsGlobal(); Vector2D coordsGlobal();
Vector2D size(); Vector2D size();
void onCommit(); void onCommit();
void onDestroy(); void onDestroy();
void onNewSubsurface(SP<CWLSubsurfaceResource> pSubsurface); void onNewSubsurface(SP<CWLSubsurfaceResource> pSubsurface);
void onMap(); void onMap();
void onUnmap(); void onUnmap();
bool visible(); bool visible();
void recheckDamageForSubsurfaces(); void recheckDamageForSubsurfaces();
WP<CSubsurface> m_pSelf;
private: private:
struct { struct {
@@ -50,16 +48,16 @@ class CSubsurface {
Vector2D m_vLastSize = {}; Vector2D m_vLastSize = {};
// if nullptr, means it's a dummy node // if nullptr, means it's a dummy node
WP<CSubsurface> m_pParent; CSubsurface* m_pParent = nullptr;
PHLWINDOWREF m_pWindowParent; PHLWINDOWREF m_pWindowParent;
WP<CPopup> m_pPopupParent; CPopup* m_pPopupParent = nullptr;
std::vector<UP<CSubsurface>> m_vChildren; std::vector<std::unique_ptr<CSubsurface>> m_vChildren;
bool m_bInert = false; bool m_bInert = false;
void initSignals(); void initSignals();
void initExistingSubsurfaces(SP<CWLSurfaceResource> pSurface); void initExistingSubsurfaces(SP<CWLSurfaceResource> pSurface);
void checkSiblingDamage(); void checkSiblingDamage();
}; };

View File

@@ -1,9 +1,7 @@
#include "WLSurface.hpp" #include "WLSurface.hpp"
#include "LayerSurface.hpp" #include "../Compositor.hpp"
#include "../desktop/Window.hpp"
#include "../protocols/core/Compositor.hpp" #include "../protocols/core/Compositor.hpp"
#include "../protocols/LayerShell.hpp" #include "../protocols/LayerShell.hpp"
#include "../render/Renderer.hpp"
void CWLSurface::assign(SP<CWLSurfaceResource> pSurface) { void CWLSurface::assign(SP<CWLSurfaceResource> pSurface) {
m_pResource = pSurface; m_pResource = pSurface;
@@ -74,7 +72,7 @@ Vector2D CWLSurface::correctSmallVec() const {
const auto SIZE = getViewporterCorrectedSize(); const auto SIZE = getViewporterCorrectedSize();
const auto O = m_pWindowOwner.lock(); const auto O = m_pWindowOwner.lock();
return Vector2D{(O->m_vReportedSize.x - SIZE.x) / 2, (O->m_vReportedSize.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) * (O->m_vRealSize->value() / O->m_vReportedSize); return Vector2D{(O->m_vReportedSize.x - SIZE.x) / 2, (O->m_vReportedSize.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) * (O->m_vRealSize.value() / O->m_vReportedSize);
} }
Vector2D CWLSurface::correctSmallVecBuf() const { Vector2D CWLSurface::correctSmallVecBuf() const {

View File

@@ -84,11 +84,7 @@ class CWLSurface {
static SP<CWLSurface> fromResource(SP<CWLSurfaceResource> pSurface); static SP<CWLSurface> fromResource(SP<CWLSurfaceResource> pSurface);
// used by the alpha-modifier protocol // used by the alpha-modifier protocol
float m_fAlphaModifier = 1.F; float m_pAlphaModifier = 1.F;
// used by the hyprland-surface protocol
float m_fOverallOpacity = 1.F;
CRegion m_visibleRegion;
struct { struct {
CSignal destroy; CSignal destroy;
@@ -120,5 +116,4 @@ class CWLSurface {
} listeners; } listeners;
friend class CPointerConstraint; friend class CPointerConstraint;
friend class CXxColorManagerV4; };
};

View File

@@ -1,4 +1,3 @@
#include <hyprutils/animation/AnimatedVariable.hpp>
#include <re2/re2.h> #include <re2/re2.h>
#include <any> #include <any>
@@ -12,23 +11,12 @@
#include "../render/decorations/CHyprBorderDecoration.hpp" #include "../render/decorations/CHyprBorderDecoration.hpp"
#include "../config/ConfigValue.hpp" #include "../config/ConfigValue.hpp"
#include "../managers/TokenManager.hpp" #include "../managers/TokenManager.hpp"
#include "../managers/AnimationManager.hpp"
#include "../protocols/XDGShell.hpp" #include "../protocols/XDGShell.hpp"
#include "../protocols/core/Compositor.hpp" #include "../protocols/core/Compositor.hpp"
#include "../xwayland/XWayland.hpp" #include "../xwayland/XWayland.hpp"
#include "../helpers/Color.hpp"
#include "../events/Events.hpp"
#include "../managers/XWaylandManager.hpp"
#include "../render/Renderer.hpp"
#include "../managers/LayoutManager.hpp"
#include "../managers/HookSystemManager.hpp"
#include "../managers/EventManager.hpp"
#include "../managers/input/InputManager.hpp"
#include <hyprutils/string/String.hpp> #include <hyprutils/string/String.hpp>
using namespace Hyprutils::String; using namespace Hyprutils::String;
using namespace Hyprutils::Animation;
PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) { PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
PHLWINDOW pWindow = SP<CWindow>(new CWindow(surface)); PHLWINDOW pWindow = SP<CWindow>(new CWindow(surface));
@@ -36,19 +24,18 @@ PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
pWindow->m_pSelf = pWindow; pWindow->m_pSelf = pWindow;
pWindow->m_bIsX11 = true; pWindow->m_bIsX11 = true;
g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_vRealPosition, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_vRealSize, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_vRealSize.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
g_pAnimationManager->createAnimation(0.f, pWindow->m_fBorderFadeAnimationProgress, g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_BORDER); pWindow->m_fBorderFadeAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_BORDER);
g_pAnimationManager->createAnimation(0.f, pWindow->m_fBorderAngleAnimationProgress, g_pConfigManager->getAnimationPropertyConfig("borderangle"), pWindow, AVARDAMAGE_BORDER); pWindow->m_fBorderAngleAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("borderangle"), pWindow, AVARDAMAGE_BORDER);
g_pAnimationManager->createAnimation(1.f, pWindow->m_fAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_fAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE);
g_pAnimationManager->createAnimation(1.f, pWindow->m_fActiveInactiveAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE);
g_pAnimationManager->createAnimation(CHyprColor(), pWindow->m_cRealShadowColor, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW); pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW);
g_pAnimationManager->createAnimation(0.f, pWindow->m_fDimPercent, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE);
g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingToWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_fMovingToWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE);
g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingFromWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->addWindowDeco(makeUnique<CHyprDropShadowDecoration>(pWindow)); pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow));
pWindow->addWindowDeco(makeUnique<CHyprBorderDecoration>(pWindow)); pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(pWindow));
return pWindow; return pWindow;
} }
@@ -59,19 +46,18 @@ PHLWINDOW CWindow::create(SP<CXDGSurfaceResource> resource) {
pWindow->m_pSelf = pWindow; pWindow->m_pSelf = pWindow;
resource->toplevel->window = pWindow; resource->toplevel->window = pWindow;
g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_vRealPosition, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_vRealSize, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_vRealSize.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
g_pAnimationManager->createAnimation(0.f, pWindow->m_fBorderFadeAnimationProgress, g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_BORDER); pWindow->m_fBorderFadeAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_BORDER);
g_pAnimationManager->createAnimation(0.f, pWindow->m_fBorderAngleAnimationProgress, g_pConfigManager->getAnimationPropertyConfig("borderangle"), pWindow, AVARDAMAGE_BORDER); pWindow->m_fBorderAngleAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("borderangle"), pWindow, AVARDAMAGE_BORDER);
g_pAnimationManager->createAnimation(1.f, pWindow->m_fAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_fAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE);
g_pAnimationManager->createAnimation(1.f, pWindow->m_fActiveInactiveAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE);
g_pAnimationManager->createAnimation(CHyprColor(), pWindow->m_cRealShadowColor, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW); pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW);
g_pAnimationManager->createAnimation(0.f, pWindow->m_fDimPercent, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE);
g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingToWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE); pWindow->m_fMovingToWorkspaceAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE);
g_pAnimationManager->createAnimation(0.f, pWindow->m_fMovingFromWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE);
pWindow->addWindowDeco(makeUnique<CHyprDropShadowDecoration>(pWindow)); pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow));
pWindow->addWindowDeco(makeUnique<CHyprBorderDecoration>(pWindow)); pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(pWindow));
pWindow->m_pWLSurface->assign(pWindow->m_pXDGSurface->surface.lock(), pWindow); pWindow->m_pWLSurface->assign(pWindow->m_pXDGSurface->surface.lock(), pWindow);
@@ -130,8 +116,8 @@ SBoxExtents CWindow::getFullWindowExtents() {
if (m_sWindowData.dimAround.valueOrDefault()) { if (m_sWindowData.dimAround.valueOrDefault()) {
if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR)
return {{m_vRealPosition->value().x - PMONITOR->vecPosition.x, m_vRealPosition->value().y - PMONITOR->vecPosition.y}, return {{m_vRealPosition.value().x - PMONITOR->vecPosition.x, m_vRealPosition.value().y - PMONITOR->vecPosition.y},
{PMONITOR->vecSize.x - (m_vRealPosition->value().x - PMONITOR->vecPosition.x), PMONITOR->vecSize.y - (m_vRealPosition->value().y - PMONITOR->vecPosition.y)}}; {PMONITOR->vecSize.x - (m_vRealPosition.value().x - PMONITOR->vecPosition.x), PMONITOR->vecSize.y - (m_vRealPosition.value().y - PMONITOR->vecPosition.y)}};
} }
SBoxExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}}; SBoxExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}};
@@ -154,7 +140,7 @@ SBoxExtents CWindow::getFullWindowExtents() {
CBox surfaceExtents = {0, 0, 0, 0}; CBox surfaceExtents = {0, 0, 0, 0};
// TODO: this could be better, perhaps make a getFullWindowRegion? // TODO: this could be better, perhaps make a getFullWindowRegion?
m_pPopupHead->breadthfirst( m_pPopupHead->breadthfirst(
[](WP<CPopup> popup, void* data) { [](CPopup* popup, void* data) {
if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource()) if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource())
return; return;
@@ -195,8 +181,8 @@ CBox CWindow::getFullWindowBoundingBox() {
auto maxExtents = getFullWindowExtents(); auto maxExtents = getFullWindowExtents();
CBox finalBox = {m_vRealPosition->value().x - maxExtents.topLeft.x, m_vRealPosition->value().y - maxExtents.topLeft.y, CBox finalBox = {m_vRealPosition.value().x - maxExtents.topLeft.x, m_vRealPosition.value().y - maxExtents.topLeft.y,
m_vRealSize->value().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize->value().y + maxExtents.topLeft.y + maxExtents.bottomRight.y}; m_vRealSize.value().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.value().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
return finalBox; return finalBox;
} }
@@ -250,7 +236,7 @@ CBox CWindow::getWindowBoxUnified(uint64_t properties) {
if (properties & FULL_EXTENTS) if (properties & FULL_EXTENTS)
EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(m_pSelf.lock(), false)); EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(m_pSelf.lock(), false));
CBox box = {m_vRealPosition->value().x, m_vRealPosition->value().y, m_vRealSize->value().x, m_vRealSize->value().y}; CBox box = {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y};
box.addExtents(EXTENTS); box.addExtents(EXTENTS);
return box; return box;
@@ -282,8 +268,6 @@ void CWindow::updateWindowDecos() {
// make a copy because updateWindow can remove decos. // make a copy because updateWindow can remove decos.
std::vector<IHyprWindowDecoration*> decos; std::vector<IHyprWindowDecoration*> decos;
// reserve to avoid reallocations
decos.reserve(m_dWindowDecorations.size());
for (auto const& wd : m_dWindowDecorations) { for (auto const& wd : m_dWindowDecorations) {
decos.push_back(wd.get()); decos.push_back(wd.get());
@@ -296,7 +280,7 @@ void CWindow::updateWindowDecos() {
} }
} }
void CWindow::addWindowDeco(UP<IHyprWindowDecoration> deco) { void CWindow::addWindowDeco(std::unique_ptr<IHyprWindowDecoration> deco) {
m_dWindowDecorations.emplace_back(std::move(deco)); m_dWindowDecorations.emplace_back(std::move(deco));
g_pDecorationPositioner->forceRecalcFor(m_pSelf.lock()); g_pDecorationPositioner->forceRecalcFor(m_pSelf.lock());
updateWindowDecos(); updateWindowDecos();
@@ -422,12 +406,10 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
const auto OLDWORKSPACE = m_pWorkspace; const auto OLDWORKSPACE = m_pWorkspace;
if (OLDWORKSPACE->isVisible()) { m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->monitorID() : -1;
m_fMovingToWorkspaceAlpha->setValueAndWarp(1.F); m_fMovingToWorkspaceAlpha.setValueAndWarp(1.F);
*m_fMovingToWorkspaceAlpha = 0.F; m_fMovingToWorkspaceAlpha = 0.F;
m_fMovingToWorkspaceAlpha->setCallbackOnEnd([this](auto) { m_iMonitorMovedFrom = -1; }); m_fMovingToWorkspaceAlpha.setCallbackOnEnd([this](void* thisptr) { m_iMonitorMovedFrom = -1; });
m_iMonitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->monitorID() : -1;
}
m_pWorkspace = pWorkspace; m_pWorkspace = pWorkspace;
@@ -455,7 +437,7 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
} }
// update xwayland coords // update xwayland coords
sendWindowSize(m_vRealSize->goal()); g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.value());
if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && OLDWORKSPACE->getWindows() == 0 && *PCLOSEONLASTSPECIAL) { if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && OLDWORKSPACE->getWindows() == 0 && *PCLOSEONLASTSPECIAL) {
if (const auto PMONITOR = OLDWORKSPACE->m_pMonitor.lock(); PMONITOR) if (const auto PMONITOR = OLDWORKSPACE->m_pMonitor.lock(); PMONITOR)
@@ -491,6 +473,19 @@ PHLWINDOW CWindow::x11TransientFor() {
return nullptr; return nullptr;
} }
void CWindow::removeDecorationByType(eDecorationType type) {
for (auto const& wd : m_dWindowDecorations) {
if (wd->getDecorationType() == type)
m_vDecosToRemove.push_back(wd.get());
}
updateWindowDecos();
}
void unregisterVar(void* ptr) {
((CBaseAnimatedVariable*)ptr)->unregister();
}
void CWindow::onUnmap() { void CWindow::onUnmap() {
static auto PCLOSEONLASTSPECIAL = CConfigValue<Hyprlang::INT>("misc:close_special_on_empty"); static auto PCLOSEONLASTSPECIAL = CConfigValue<Hyprlang::INT>("misc:close_special_on_empty");
static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking"); static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking");
@@ -509,6 +504,18 @@ void CWindow::onUnmap() {
m_iLastWorkspace = m_pWorkspace->m_iID; m_iLastWorkspace = m_pWorkspace->m_iID;
m_vRealPosition.setCallbackOnEnd(unregisterVar);
m_vRealSize.setCallbackOnEnd(unregisterVar);
m_fBorderFadeAnimationProgress.setCallbackOnEnd(unregisterVar);
m_fBorderAngleAnimationProgress.setCallbackOnEnd(unregisterVar);
m_fActiveInactiveAlpha.setCallbackOnEnd(unregisterVar);
m_fAlpha.setCallbackOnEnd(unregisterVar);
m_cRealShadowColor.setCallbackOnEnd(unregisterVar);
m_fDimPercent.setCallbackOnEnd(unregisterVar);
m_fMovingToWorkspaceAlpha.setCallbackOnEnd(unregisterVar);
m_vRealSize.setCallbackOnBegin(nullptr);
std::erase_if(g_pCompositor->m_vWindowFocusHistory, [&](const auto& other) { return other.expired() || other.lock().get() == this; }); std::erase_if(g_pCompositor->m_vWindowFocusHistory, [&](const auto& other) { return other.expired() || other.lock().get() == this; });
if (*PCLOSEONLASTSPECIAL && m_pWorkspace && m_pWorkspace->getWindows() == 0 && onSpecialWorkspace()) { if (*PCLOSEONLASTSPECIAL && m_pWorkspace && m_pWorkspace->getWindows() == 0 && onSpecialWorkspace()) {
@@ -540,26 +547,30 @@ void CWindow::onUnmap() {
void CWindow::onMap() { void CWindow::onMap() {
// JIC, reset the callbacks. If any are set, we'll make sure they are cleared so we don't accidentally unset them. (In case a window got remapped) // JIC, reset the callbacks. If any are set, we'll make sure they are cleared so we don't accidentally unset them. (In case a window got remapped)
m_vRealPosition->resetAllCallbacks(); m_vRealPosition.resetAllCallbacks();
m_vRealSize->resetAllCallbacks(); m_vRealSize.resetAllCallbacks();
m_fBorderFadeAnimationProgress->resetAllCallbacks(); m_fBorderFadeAnimationProgress.resetAllCallbacks();
m_fBorderAngleAnimationProgress->resetAllCallbacks(); m_fBorderAngleAnimationProgress.resetAllCallbacks();
m_fActiveInactiveAlpha->resetAllCallbacks(); m_fActiveInactiveAlpha.resetAllCallbacks();
m_fAlpha->resetAllCallbacks(); m_fAlpha.resetAllCallbacks();
m_cRealShadowColor->resetAllCallbacks(); m_cRealShadowColor.resetAllCallbacks();
m_fDimPercent->resetAllCallbacks(); m_fDimPercent.resetAllCallbacks();
m_fMovingToWorkspaceAlpha->resetAllCallbacks(); m_fMovingToWorkspaceAlpha.resetAllCallbacks();
m_fMovingFromWorkspaceAlpha->resetAllCallbacks();
m_fMovingFromWorkspaceAlpha->setValueAndWarp(1.F); m_vRealPosition.registerVar();
m_vRealSize.registerVar();
m_fBorderFadeAnimationProgress.registerVar();
m_fBorderAngleAnimationProgress.registerVar();
m_fActiveInactiveAlpha.registerVar();
m_fAlpha.registerVar();
m_cRealShadowColor.registerVar();
m_fDimPercent.registerVar();
m_fMovingToWorkspaceAlpha.registerVar();
if (m_fBorderAngleAnimationProgress->enabled()) { m_fBorderAngleAnimationProgress.setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false);
m_fBorderAngleAnimationProgress->setValueAndWarp(0.f);
m_fBorderAngleAnimationProgress->setCallbackOnEnd([&](WP<CBaseAnimatedVariable> p) { onBorderAngleAnimEnd(p); }, false);
*m_fBorderAngleAnimationProgress = 1.f;
}
m_fMovingFromWorkspaceAlpha->setValueAndWarp(1.F); m_fBorderAngleAnimationProgress.setValueAndWarp(0.f);
m_fBorderAngleAnimationProgress = 1.f;
g_pCompositor->m_vWindowFocusHistory.push_back(m_pSelf); g_pCompositor->m_vWindowFocusHistory.push_back(m_pSelf);
@@ -571,28 +582,24 @@ void CWindow::onMap() {
if (m_bIsX11) if (m_bIsX11)
return; return;
m_pSubsurfaceHead = makeUnique<CSubsurface>(m_pSelf.lock()); m_pSubsurfaceHead = std::make_unique<CSubsurface>(m_pSelf.lock());
m_pSubsurfaceHead->m_pSelf = m_pSubsurfaceHead; m_pPopupHead = std::make_unique<CPopup>(m_pSelf.lock());
m_pPopupHead = makeUnique<CPopup>(m_pSelf.lock());
m_pPopupHead->m_pSelf = m_pPopupHead;
} }
void CWindow::onBorderAngleAnimEnd(WP<CBaseAnimatedVariable> pav) { void CWindow::onBorderAngleAnimEnd(void* ptr) {
const auto PAV = pav.lock(); const auto PANIMVAR = (CAnimatedVariable<float>*)ptr;
if (!PAV)
return;
if (PAV->getStyle() != "loop" || !PAV->enabled()) const std::string STYLE = PANIMVAR->getConfig()->pValues->internalStyle;
return;
const auto PANIMVAR = dynamic_cast<CAnimatedVariable<float>*>(PAV.get()); if (STYLE != "loop" || !PANIMVAR->getConfig()->pValues->internalEnabled)
return;
PANIMVAR->setCallbackOnEnd(nullptr); // we remove the callback here because otherwise setvalueandwarp will recurse this PANIMVAR->setCallbackOnEnd(nullptr); // we remove the callback here because otherwise setvalueandwarp will recurse this
PANIMVAR->setValueAndWarp(0); PANIMVAR->setValueAndWarp(0);
*PANIMVAR = 1.f; *PANIMVAR = 1.f;
PANIMVAR->setCallbackOnEnd([&](WP<CBaseAnimatedVariable> pav) { onBorderAngleAnimEnd(pav); }, false); PANIMVAR->setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false);
} }
void CWindow::setHidden(bool hidden) { void CWindow::setHidden(bool hidden) {
@@ -819,28 +826,27 @@ void CWindow::updateDynamicRules() {
// it is assumed that the point is within the real window box (m_vRealPosition, m_vRealSize) // it is assumed that the point is within the real window box (m_vRealPosition, m_vRealSize)
// otherwise behaviour is undefined // otherwise behaviour is undefined
bool CWindow::isInCurvedCorner(double x, double y) { bool CWindow::isInCurvedCorner(double x, double y) {
const int ROUNDING = rounding(); const int ROUNDING = rounding();
const int ROUNDINGPOWER = roundingPower();
if (getRealBorderSize() >= ROUNDING) if (getRealBorderSize() >= ROUNDING)
return false; return false;
// (x0, y0), (x0, y1), ... are the center point of rounding at each corner // (x0, y0), (x0, y1), ... are the center point of rounding at each corner
double x0 = m_vRealPosition->value().x + ROUNDING; double x0 = m_vRealPosition.value().x + ROUNDING;
double y0 = m_vRealPosition->value().y + ROUNDING; double y0 = m_vRealPosition.value().y + ROUNDING;
double x1 = m_vRealPosition->value().x + m_vRealSize->value().x - ROUNDING; double x1 = m_vRealPosition.value().x + m_vRealSize.value().x - ROUNDING;
double y1 = m_vRealPosition->value().y + m_vRealSize->value().y - ROUNDING; double y1 = m_vRealPosition.value().y + m_vRealSize.value().y - ROUNDING;
if (x < x0 && y < y0) { if (x < x0 && y < y0) {
return std::pow(x0 - x, ROUNDINGPOWER) + std::pow(y0 - y, ROUNDINGPOWER) > std::pow((double)ROUNDING, ROUNDINGPOWER); return Vector2D{x0, y0}.distance(Vector2D{x, y}) > (double)ROUNDING;
} }
if (x > x1 && y < y0) { if (x > x1 && y < y0) {
return std::pow(x - x1, ROUNDINGPOWER) + std::pow(y0 - y, ROUNDINGPOWER) > std::pow((double)ROUNDING, ROUNDINGPOWER); return Vector2D{x1, y0}.distance(Vector2D{x, y}) > (double)ROUNDING;
} }
if (x < x0 && y > y1) { if (x < x0 && y > y1) {
return std::pow(x0 - x, ROUNDINGPOWER) + std::pow(y - y1, ROUNDINGPOWER) > std::pow((double)ROUNDING, ROUNDINGPOWER); return Vector2D{x0, y1}.distance(Vector2D{x, y}) > (double)ROUNDING;
} }
if (x > x1 && y > y1) { if (x > x1 && y > y1) {
return std::pow(x - x1, ROUNDINGPOWER) + std::pow(y - y1, ROUNDINGPOWER) > std::pow((double)ROUNDING, ROUNDINGPOWER); return Vector2D{x1, y1}.distance(Vector2D{x, y}) > (double)ROUNDING;
} }
return false; return false;
@@ -851,7 +857,7 @@ bool CWindow::hasPopupAt(const Vector2D& pos) {
if (m_bIsX11) if (m_bIsX11)
return false; return false;
auto popup = m_pPopupHead->at(pos); CPopup* popup = m_pPopupHead->at(pos);
return popup && popup->m_pWLSurface->resource(); return popup && popup->m_pWLSurface->resource();
} }
@@ -876,7 +882,7 @@ void CWindow::createGroup() {
m_sGroupData.locked = false; m_sGroupData.locked = false;
m_sGroupData.deny = false; m_sGroupData.deny = false;
addWindowDeco(makeUnique<CHyprGroupBarDecoration>(m_pSelf.lock())); addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(m_pSelf.lock()));
if (m_pWorkspace) { if (m_pWorkspace) {
m_pWorkspace->updateWindows(); m_pWorkspace->updateWindows();
@@ -1022,22 +1028,22 @@ void CWindow::setGroupCurrent(PHLWINDOW pWindow) {
const auto WORKSPACE = PCURRENT->m_pWorkspace; const auto WORKSPACE = PCURRENT->m_pWorkspace;
const auto MODE = PCURRENT->m_sFullscreenState.internal; const auto MODE = PCURRENT->m_sFullscreenState.internal;
const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goal();
const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goal();
const auto CURRENTISFOCUS = PCURRENT == g_pCompositor->m_pLastWindow.lock(); const auto CURRENTISFOCUS = PCURRENT == g_pCompositor->m_pLastWindow.lock();
if (FULLSCREEN) if (FULLSCREEN)
g_pCompositor->setWindowFullscreenInternal(PCURRENT, FSMODE_NONE); g_pCompositor->setWindowFullscreenInternal(PCURRENT, FSMODE_NONE);
const auto PWINDOWSIZE = PCURRENT->m_vRealSize->goal();
const auto PWINDOWPOS = PCURRENT->m_vRealPosition->goal();
PCURRENT->setHidden(true); PCURRENT->setHidden(true);
pWindow->setHidden(false); // can remove m_pLastWindow pWindow->setHidden(false); // can remove m_pLastWindow
g_pLayoutManager->getCurrentLayout()->replaceWindowDataWith(PCURRENT, pWindow); g_pLayoutManager->getCurrentLayout()->replaceWindowDataWith(PCURRENT, pWindow);
if (PCURRENT->m_bIsFloating) { if (PCURRENT->m_bIsFloating) {
pWindow->m_vRealPosition->setValueAndWarp(PWINDOWPOS); pWindow->m_vRealPosition.setValueAndWarp(PWINDOWPOS);
pWindow->m_vRealSize->setValueAndWarp(PWINDOWSIZE); pWindow->m_vRealSize.setValueAndWarp(PWINDOWSIZE);
} }
g_pCompositor->updateAllWindowsAnimatedDecorationValues(); g_pCompositor->updateAllWindowsAnimatedDecorationValues();
@@ -1058,7 +1064,7 @@ void CWindow::insertWindowToGroup(PHLWINDOW pWindow) {
const auto ENDAT = m_sGroupData.pNextWindow.lock(); const auto ENDAT = m_sGroupData.pNextWindow.lock();
if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) if (!pWindow->getDecorationByType(DECORATION_GROUPBAR))
pWindow->addWindowDeco(makeUnique<CHyprGroupBarDecoration>(pWindow)); pWindow->addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(pWindow));
if (!pWindow->m_sGroupData.pNextWindow.lock()) { if (!pWindow->m_sGroupData.pNextWindow.lock()) {
BEGINAT->m_sGroupData.pNextWindow = pWindow; BEGINAT->m_sGroupData.pNextWindow = pWindow;
@@ -1119,22 +1125,22 @@ void CWindow::updateGroupOutputs() {
curr->m_pMonitor = m_pMonitor; curr->m_pMonitor = m_pMonitor;
curr->moveToWorkspace(WS); curr->moveToWorkspace(WS);
*curr->m_vRealPosition = m_vRealPosition->goal(); curr->m_vRealPosition = m_vRealPosition.goal();
*curr->m_vRealSize = m_vRealSize->goal(); curr->m_vRealSize = m_vRealSize.goal();
curr = curr->m_sGroupData.pNextWindow.lock(); curr = curr->m_sGroupData.pNextWindow.lock();
} }
} }
Vector2D CWindow::middle() { Vector2D CWindow::middle() {
return m_vRealPosition->goal() + m_vRealSize->goal() / 2.f; return m_vRealPosition.goal() + m_vRealSize.goal() / 2.f;
} }
bool CWindow::opaque() { bool CWindow::opaque() {
if (m_fAlpha->value() != 1.f || m_fActiveInactiveAlpha->value() != 1.f) if (m_fAlpha.value() != 1.f || m_fActiveInactiveAlpha.value() != 1.f)
return false; return false;
if (m_vRealSize->goal().floor() != m_vReportedSize) if (m_vRealSize.goal().floor() != m_vReportedSize)
return false; return false;
const auto PWORKSPACE = m_pWorkspace; const auto PWORKSPACE = m_pWorkspace;
@@ -1142,7 +1148,7 @@ bool CWindow::opaque() {
if (m_pWLSurface->small() && !m_pWLSurface->m_bFillIgnoreSmall) if (m_pWLSurface->small() && !m_pWLSurface->m_bFillIgnoreSmall)
return false; return false;
if (PWORKSPACE->m_fAlpha->value() != 1.f) if (PWORKSPACE->m_fAlpha.value() != 1.f)
return false; return false;
if (m_bIsX11 && m_pXWaylandSurface && m_pXWaylandSurface->surface && m_pXWaylandSurface->surface->current.texture) if (m_bIsX11 && m_pXWaylandSurface && m_pXWaylandSurface->surface && m_pXWaylandSurface->surface->current.texture)
@@ -1160,21 +1166,13 @@ bool CWindow::opaque() {
} }
float CWindow::rounding() { float CWindow::rounding() {
static auto PROUNDING = CConfigValue<Hyprlang::INT>("decoration:rounding"); static auto PROUNDING = CConfigValue<Hyprlang::INT>("decoration:rounding");
static auto PROUNDINGPOWER = CConfigValue<Hyprlang::FLOAT>("decoration:rounding_power");
float roundingPower = m_sWindowData.roundingPower.valueOr(*PROUNDINGPOWER); float rounding = m_sWindowData.rounding.valueOr(*PROUNDING);
float rounding = m_sWindowData.rounding.valueOr(*PROUNDING) * (roundingPower / 2.0); /* Make perceived roundness consistent. */
return m_sWindowData.noRounding.valueOrDefault() ? 0 : rounding; return m_sWindowData.noRounding.valueOrDefault() ? 0 : rounding;
} }
float CWindow::roundingPower() {
static auto PROUNDINGPOWER = CConfigValue<Hyprlang::FLOAT>("decoration:rounding_power");
return m_sWindowData.roundingPower.valueOr(*PROUNDINGPOWER);
}
void CWindow::updateWindowData() { void CWindow::updateWindowData() {
const auto PWORKSPACE = m_pWorkspace; const auto PWORKSPACE = m_pWorkspace;
const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{}; const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{};
@@ -1232,13 +1230,15 @@ void CWindow::setSuspended(bool suspend) {
} }
bool CWindow::visibleOnMonitor(PHLMONITOR pMonitor) { bool CWindow::visibleOnMonitor(PHLMONITOR pMonitor) {
CBox wbox = {m_vRealPosition->value(), m_vRealSize->value()}; CBox wbox = {m_vRealPosition.value(), m_vRealSize.value()};
return !wbox.intersection({pMonitor->vecPosition, pMonitor->vecSize}).empty(); return !wbox.intersection({pMonitor->vecPosition, pMonitor->vecSize}).empty();
} }
void CWindow::setAnimationsToMove() { void CWindow::setAnimationsToMove() {
m_vRealPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsMove")); auto* const PANIMCFG = g_pConfigManager->getAnimationPropertyConfig("windowsMove");
m_vRealPosition.setConfig(PANIMCFG);
m_vRealSize.setConfig(PANIMCFG);
m_bAnimatingIn = false; m_bAnimatingIn = false;
} }
@@ -1259,16 +1259,16 @@ void CWindow::onWorkspaceAnimUpdate() {
return; return;
const auto WINBB = getFullWindowBoundingBox(); const auto WINBB = getFullWindowBoundingBox();
if (PWORKSPACE->m_vRenderOffset->value().x != 0) { if (PWORKSPACE->m_vRenderOffset.value().x != 0) {
const auto PROGRESS = PWORKSPACE->m_vRenderOffset->value().x / PWSMON->vecSize.x; const auto PROGRESS = PWORKSPACE->m_vRenderOffset.value().x / PWSMON->vecSize.x;
if (WINBB.x < PWSMON->vecPosition.x) if (WINBB.x < PWSMON->vecPosition.x)
offset.x += (PWSMON->vecPosition.x - WINBB.x) * PROGRESS; offset.x += (PWSMON->vecPosition.x - WINBB.x) * PROGRESS;
if (WINBB.x + WINBB.width > PWSMON->vecPosition.x + PWSMON->vecSize.x) if (WINBB.x + WINBB.width > PWSMON->vecPosition.x + PWSMON->vecSize.x)
offset.x += (WINBB.x + WINBB.width - PWSMON->vecPosition.x - PWSMON->vecSize.x) * PROGRESS; offset.x += (WINBB.x + WINBB.width - PWSMON->vecPosition.x - PWSMON->vecSize.x) * PROGRESS;
} else if (PWORKSPACE->m_vRenderOffset->value().y != 0) { } else if (PWORKSPACE->m_vRenderOffset.value().y != 0) {
const auto PROGRESS = PWORKSPACE->m_vRenderOffset->value().y / PWSMON->vecSize.y; const auto PROGRESS = PWORKSPACE->m_vRenderOffset.value().y / PWSMON->vecSize.y;
if (WINBB.y < PWSMON->vecPosition.y) if (WINBB.y < PWSMON->vecPosition.y)
offset.y += (PWSMON->vecPosition.y - WINBB.y) * PROGRESS; offset.y += (PWSMON->vecPosition.y - WINBB.y) * PROGRESS;
@@ -1280,20 +1280,12 @@ void CWindow::onWorkspaceAnimUpdate() {
m_vFloatingOffset = offset; m_vFloatingOffset = offset;
} }
void CWindow::onFocusAnimUpdate() {
// borderangle once
if (m_fBorderAngleAnimationProgress->enabled() && !m_fBorderAngleAnimationProgress->isBeingAnimated()) {
m_fBorderAngleAnimationProgress->setValueAndWarp(0.f);
*m_fBorderAngleAnimationProgress = 1.f;
}
}
int CWindow::popupsCount() { int CWindow::popupsCount() {
if (m_bIsX11) if (m_bIsX11)
return 0; return 0;
int no = -1; int no = -1;
m_pPopupHead->breadthfirst([](WP<CPopup> p, void* d) { *((int*)d) += 1; }, &no); m_pPopupHead->breadthfirst([](CPopup* p, void* d) { *((int*)d) += 1; }, &no);
return no; return no;
} }
@@ -1307,13 +1299,13 @@ int CWindow::surfacesCount() {
} }
void CWindow::clampWindowSize(const std::optional<Vector2D> minSize, const std::optional<Vector2D> maxSize) { void CWindow::clampWindowSize(const std::optional<Vector2D> minSize, const std::optional<Vector2D> maxSize) {
const Vector2D REALSIZE = m_vRealSize->goal(); const Vector2D REALSIZE = m_vRealSize.goal();
const Vector2D NEWSIZE = REALSIZE.clamp(minSize.value_or(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), maxSize.value_or(Vector2D{INFINITY, INFINITY})); const Vector2D NEWSIZE = REALSIZE.clamp(minSize.value_or(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), maxSize.value_or(Vector2D{INFINITY, INFINITY}));
const Vector2D DELTA = REALSIZE - NEWSIZE; const Vector2D DELTA = REALSIZE - NEWSIZE;
*m_vRealPosition = m_vRealPosition->goal() + DELTA / 2.0; m_vRealPosition = m_vRealPosition.goal() + DELTA / 2.0;
*m_vRealSize = NEWSIZE; m_vRealSize = NEWSIZE;
sendWindowSize(NEWSIZE); g_pXWaylandManager->setWindowSize(m_pSelf.lock(), NEWSIZE);
} }
bool CWindow::isFullscreen() { bool CWindow::isFullscreen() {
@@ -1405,25 +1397,14 @@ void CWindow::activate(bool force) {
} }
void CWindow::onUpdateState() { void CWindow::onUpdateState() {
std::optional<bool> requestsFS = m_pXDGSurface ? m_pXDGSurface->toplevel->state.requestsFullscreen : m_pXWaylandSurface->state.requestsFullscreen; std::optional<bool> requestsFS = m_pXDGSurface ? m_pXDGSurface->toplevel->state.requestsFullscreen : m_pXWaylandSurface->state.requestsFullscreen;
std::optional<MONITORID> requestsID = m_pXDGSurface ? m_pXDGSurface->toplevel->state.requestsFullscreenMonitor : MONITOR_INVALID; std::optional<bool> requestsMX = m_pXDGSurface ? m_pXDGSurface->toplevel->state.requestsMaximize : m_pXWaylandSurface->state.requestsMaximize;
std::optional<bool> requestsMX = m_pXDGSurface ? m_pXDGSurface->toplevel->state.requestsMaximize : m_pXWaylandSurface->state.requestsMaximize;
if (requestsFS.has_value() && !(m_eSuppressedEvents & SUPPRESS_FULLSCREEN)) { if (requestsFS.has_value() && !(m_eSuppressedEvents & SUPPRESS_FULLSCREEN)) {
if (requestsID.has_value() && (requestsID.value() != MONITOR_INVALID) && !(m_eSuppressedEvents & SUPPRESS_FULLSCREEN_OUTPUT)) {
if (m_bIsMapped) {
const auto monitor = g_pCompositor->getMonitorFromID(requestsID.value());
g_pCompositor->moveWindowToWorkspaceSafe(m_pSelf.lock(), monitor->activeWorkspace);
g_pCompositor->setActiveMonitor(monitor);
}
if (!m_bIsMapped)
m_iWantsInitialFullscreenMonitor = requestsID.value();
}
bool fs = requestsFS.value(); bool fs = requestsFS.value();
if (m_bIsMapped) if (m_bIsMapped) {
g_pCompositor->changeWindowFullscreenModeClient(m_pSelf.lock(), FSMODE_FULLSCREEN, requestsFS.value()); g_pCompositor->changeWindowFullscreenModeClient(m_pSelf.lock(), FSMODE_FULLSCREEN, requestsFS.value());
}
if (!m_bIsMapped) if (!m_bIsMapped)
m_bWantsInitialFullscreen = fs; m_bWantsInitialFullscreen = fs;
@@ -1537,7 +1518,7 @@ void CWindow::onX11Configure(CBox box) {
g_pHyprRenderer->damageWindow(m_pSelf.lock()); g_pHyprRenderer->damageWindow(m_pSelf.lock());
if (!m_bIsFloating || isFullscreen() || g_pInputManager->currentlyDraggedWindow == m_pSelf) { if (!m_bIsFloating || isFullscreen() || g_pInputManager->currentlyDraggedWindow == m_pSelf) {
sendWindowSize(m_vRealSize->goal(), true); g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal(), true);
g_pInputManager->refocus(); g_pInputManager->refocus();
g_pHyprRenderer->damageWindow(m_pSelf.lock()); g_pHyprRenderer->damageWindow(m_pSelf.lock());
return; return;
@@ -1550,21 +1531,21 @@ void CWindow::onX11Configure(CBox box) {
const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords(box.pos()); const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords(box.pos());
m_vRealPosition->setValueAndWarp(LOGICALPOS); m_vRealPosition.setValueAndWarp(LOGICALPOS);
m_vRealSize->setValueAndWarp(box.size()); m_vRealSize.setValueAndWarp(box.size());
static auto PXWLFORCESCALEZERO = CConfigValue<Hyprlang::INT>("xwayland:force_zero_scaling"); static auto PXWLFORCESCALEZERO = CConfigValue<Hyprlang::INT>("xwayland:force_zero_scaling");
if (*PXWLFORCESCALEZERO) { if (*PXWLFORCESCALEZERO) {
if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) { if (const auto PMONITOR = m_pMonitor.lock(); PMONITOR) {
m_vRealSize->setValueAndWarp(m_vRealSize->goal() / PMONITOR->scale); m_vRealSize.setValueAndWarp(m_vRealSize.goal() / PMONITOR->scale);
m_fX11SurfaceScaledBy = PMONITOR->scale; m_fX11SurfaceScaledBy = PMONITOR->scale;
} }
} }
m_vPosition = m_vRealPosition->goal(); m_vPosition = m_vRealPosition.value();
m_vSize = m_vRealSize->goal(); m_vSize = m_vRealSize.value();
sendWindowSize(box.size(), true); m_pXWaylandSurface->configure(box);
m_vPendingReportedSize = box.size(); m_vPendingReportedSize = box.size();
m_vReportedSize = box.size(); m_vReportedSize = box.size();
@@ -1574,7 +1555,7 @@ void CWindow::onX11Configure(CBox box) {
if (!m_pWorkspace || !m_pWorkspace->isVisible()) if (!m_pWorkspace || !m_pWorkspace->isVisible())
return; // further things are only for visible windows return; // further things are only for visible windows
m_pWorkspace = g_pCompositor->getMonitorFromVector(m_vRealPosition->goal() + m_vRealSize->goal() / 2.f)->activeWorkspace; m_pWorkspace = g_pCompositor->getMonitorFromVector(m_vRealPosition.value() + m_vRealSize.value() / 2.f)->activeWorkspace;
g_pCompositor->changeWindowZOrder(m_pSelf.lock(), true); g_pCompositor->changeWindowZOrder(m_pSelf.lock(), true);
@@ -1694,38 +1675,3 @@ Vector2D CWindow::requestedMaxSize() {
return maxSize; return maxSize;
} }
void CWindow::sendWindowSize(Vector2D size, bool force, std::optional<Vector2D> overridePos) {
static auto PXWLFORCESCALEZERO = CConfigValue<Hyprlang::INT>("xwayland:force_zero_scaling");
const auto PMONITOR = m_pMonitor.lock();
size = size.clamp(Vector2D{0, 0}, Vector2D{std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity()});
// calculate pos
// TODO: this should be decoupled from setWindowSize IMO
Vector2D windowPos = overridePos.value_or(m_vRealPosition->goal());
if (m_bIsX11) {
if (const auto XWAYLANDPOS = g_pXWaylandManager->waylandToXWaylandCoords(windowPos); XWAYLANDPOS != Vector2D{})
windowPos = XWAYLANDPOS;
}
if (!force && m_vPendingReportedSize == size && (windowPos == m_vReportedPosition || !m_bIsX11))
return;
m_vReportedPosition = windowPos;
m_vPendingReportedSize = size;
m_fX11SurfaceScaledBy = 1.0f;
if (*PXWLFORCESCALEZERO && m_bIsX11 && PMONITOR) {
size *= PMONITOR->scale;
m_fX11SurfaceScaledBy = PMONITOR->scale;
}
if (m_bIsX11 && m_pXWaylandSurface)
m_pXWaylandSurface->configure({windowPos, size});
else if (m_pXDGSurface && m_pXDGSurface->toplevel)
m_vPendingSizeAcks.emplace_back(m_pXDGSurface->toplevel->setSize(size), size.floor());
}

View File

@@ -2,9 +2,9 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <optional>
#include "../config/ConfigDataValues.hpp" #include "../config/ConfigDataValues.hpp"
#include "../defines.hpp"
#include "../helpers/AnimatedVariable.hpp" #include "../helpers/AnimatedVariable.hpp"
#include "../helpers/math/Math.hpp" #include "../helpers/math/Math.hpp"
#include "../helpers/signal/Signal.hpp" #include "../helpers/signal/Signal.hpp"
@@ -12,7 +12,6 @@
#include "../macros.hpp" #include "../macros.hpp"
#include "../managers/XWaylandManager.hpp" #include "../managers/XWaylandManager.hpp"
#include "../render/decorations/IHyprWindowDecoration.hpp" #include "../render/decorations/IHyprWindowDecoration.hpp"
#include "../render/Transformer.hpp"
#include "DesktopTypes.hpp" #include "DesktopTypes.hpp"
#include "Popup.hpp" #include "Popup.hpp"
#include "Subsurface.hpp" #include "Subsurface.hpp"
@@ -58,7 +57,6 @@ enum eSuppressEvents : uint8_t {
SUPPRESS_MAXIMIZE = 1 << 1, SUPPRESS_MAXIMIZE = 1 << 1,
SUPPRESS_ACTIVATE = 1 << 2, SUPPRESS_ACTIVATE = 1 << 2,
SUPPRESS_ACTIVATE_FOCUSONLY = 1 << 3, SUPPRESS_ACTIVATE_FOCUSONLY = 1 << 3,
SUPPRESS_FULLSCREEN_OUTPUT = 1 << 4,
}; };
class IWindowTransformer; class IWindowTransformer;
@@ -185,7 +183,6 @@ struct SWindowData {
CWindowOverridableVar<bool> renderUnfocused = false; CWindowOverridableVar<bool> renderUnfocused = false;
CWindowOverridableVar<int> rounding; CWindowOverridableVar<int> rounding;
CWindowOverridableVar<float> roundingPower;
CWindowOverridableVar<int> borderSize; CWindowOverridableVar<int> borderSize;
CWindowOverridableVar<float> scrollMouse; CWindowOverridableVar<float> scrollMouse;
@@ -235,8 +232,8 @@ class CWindow {
Vector2D m_vSize = Vector2D(0, 0); Vector2D m_vSize = Vector2D(0, 0);
// this is the real position and size used to draw the thing // this is the real position and size used to draw the thing
PHLANIMVAR<Vector2D> m_vRealPosition; CAnimatedVariable<Vector2D> m_vRealPosition;
PHLANIMVAR<Vector2D> m_vRealSize; CAnimatedVariable<Vector2D> m_vRealSize;
// for not spamming the protocols // for not spamming the protocols
Vector2D m_vReportedPosition; Vector2D m_vReportedPosition;
@@ -290,30 +287,29 @@ class CWindow {
bool m_bNoInitialFocus = false; bool m_bNoInitialFocus = false;
// Fullscreen and Maximize // Fullscreen and Maximize
bool m_bWantsInitialFullscreen = false; bool m_bWantsInitialFullscreen = false;
MONITORID m_iWantsInitialFullscreenMonitor = MONITOR_INVALID;
// bitfield eSuppressEvents // bitfield eSuppressEvents
uint64_t m_eSuppressedEvents = SUPPRESS_NONE; uint64_t m_eSuppressedEvents = SUPPRESS_NONE;
// desktop components // desktop components
UP<CSubsurface> m_pSubsurfaceHead; std::unique_ptr<CSubsurface> m_pSubsurfaceHead;
UP<CPopup> m_pPopupHead; std::unique_ptr<CPopup> m_pPopupHead;
// Animated border // Animated border
CGradientValueData m_cRealBorderColor = {0}; CGradientValueData m_cRealBorderColor = {0};
CGradientValueData m_cRealBorderColorPrevious = {0}; CGradientValueData m_cRealBorderColorPrevious = {0};
PHLANIMVAR<float> m_fBorderFadeAnimationProgress; CAnimatedVariable<float> m_fBorderFadeAnimationProgress;
PHLANIMVAR<float> m_fBorderAngleAnimationProgress; CAnimatedVariable<float> m_fBorderAngleAnimationProgress;
// Fade in-out // Fade in-out
PHLANIMVAR<float> m_fAlpha; CAnimatedVariable<float> m_fAlpha;
bool m_bFadingOut = false; bool m_bFadingOut = false;
bool m_bReadyToDelete = false; bool m_bReadyToDelete = false;
Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in Vector2D m_vOriginalClosedPos; // these will be used for calculations later on in
Vector2D m_vOriginalClosedSize; // drawing the closing animations Vector2D m_vOriginalClosedSize; // drawing the closing animations
SBoxExtents m_eOriginalClosedExtents; SBoxExtents m_eOriginalClosedExtents;
bool m_bAnimatingIn = false; bool m_bAnimatingIn = false;
// For pinned (sticky) windows // For pinned (sticky) windows
bool m_bPinned = false; bool m_bPinned = false;
@@ -329,28 +325,27 @@ class CWindow {
// Window decorations // Window decorations
// TODO: make this a SP. // TODO: make this a SP.
std::vector<UP<IHyprWindowDecoration>> m_dWindowDecorations; std::vector<std::unique_ptr<IHyprWindowDecoration>> m_dWindowDecorations;
std::vector<IHyprWindowDecoration*> m_vDecosToRemove; std::vector<IHyprWindowDecoration*> m_vDecosToRemove;
// Special render data, rules, etc // Special render data, rules, etc
SWindowData m_sWindowData; SWindowData m_sWindowData;
// Transformers // Transformers
std::vector<UP<IWindowTransformer>> m_vTransformers; std::vector<std::unique_ptr<IWindowTransformer>> m_vTransformers;
// for alpha // for alpha
PHLANIMVAR<float> m_fActiveInactiveAlpha; CAnimatedVariable<float> m_fActiveInactiveAlpha;
PHLANIMVAR<float> m_fMovingFromWorkspaceAlpha;
// animated shadow color // animated shadow color
PHLANIMVAR<CHyprColor> m_cRealShadowColor; CAnimatedVariable<CHyprColor> m_cRealShadowColor;
// animated tint // animated tint
PHLANIMVAR<float> m_fDimPercent; CAnimatedVariable<float> m_fDimPercent;
// animate moving to an invisible workspace // animate moving to an invisible workspace
int m_iMonitorMovedFrom = -1; // -1 means not moving int m_iMonitorMovedFrom = -1; // -1 means not moving
PHLANIMVAR<float> m_fMovingToWorkspaceAlpha; CAnimatedVariable<float> m_fMovingToWorkspaceAlpha;
// swallowing // swallowing
PHLWINDOWREF m_pSwallowed; PHLWINDOWREF m_pSwallowed;
@@ -397,13 +392,14 @@ class CWindow {
SBoxExtents getFullWindowExtents(); SBoxExtents getFullWindowExtents();
CBox getWindowBoxUnified(uint64_t props); CBox getWindowBoxUnified(uint64_t props);
CBox getWindowIdealBoundingBoxIgnoreReserved(); CBox getWindowIdealBoundingBoxIgnoreReserved();
void addWindowDeco(UP<IHyprWindowDecoration> deco); void addWindowDeco(std::unique_ptr<IHyprWindowDecoration> deco);
void updateWindowDecos(); void updateWindowDecos();
void removeWindowDeco(IHyprWindowDecoration* deco); void removeWindowDeco(IHyprWindowDecoration* deco);
void uncacheWindowDecos(); void uncacheWindowDecos();
bool checkInputOnDecos(const eInputType, const Vector2D&, std::any = {}); bool checkInputOnDecos(const eInputType, const Vector2D&, std::any = {});
pid_t getPID(); pid_t getPID();
IHyprWindowDecoration* getDecorationByType(eDecorationType); IHyprWindowDecoration* getDecorationByType(eDecorationType);
void removeDecorationByType(eDecorationType);
void updateToplevel(); void updateToplevel();
void updateSurfaceScaleTransformDetails(bool force = false); void updateSurfaceScaleTransformDetails(bool force = false);
void moveToWorkspace(PHLWORKSPACE); void moveToWorkspace(PHLWORKSPACE);
@@ -418,7 +414,6 @@ class CWindow {
Vector2D middle(); Vector2D middle();
bool opaque(); bool opaque();
float rounding(); float rounding();
float roundingPower();
bool canBeTorn(); bool canBeTorn();
void setSuspended(bool suspend); void setSuspended(bool suspend);
bool visibleOnMonitor(PHLMONITOR pMonitor); bool visibleOnMonitor(PHLMONITOR pMonitor);
@@ -435,7 +430,7 @@ class CWindow {
float getScrollTouchpad(); float getScrollTouchpad();
void updateWindowData(); void updateWindowData();
void updateWindowData(const struct SWorkspaceRule&); void updateWindowData(const struct SWorkspaceRule&);
void onBorderAngleAnimEnd(WP<Hyprutils::Animation::CBaseAnimatedVariable> pav); void onBorderAngleAnimEnd(void* ptr);
bool isInCurvedCorner(double x, double y); bool isInCurvedCorner(double x, double y);
bool hasPopupAt(const Vector2D& pos); bool hasPopupAt(const Vector2D& pos);
int popupsCount(); int popupsCount();
@@ -455,7 +450,6 @@ class CWindow {
void switchWithWindowInGroup(PHLWINDOW pWindow); void switchWithWindowInGroup(PHLWINDOW pWindow);
void setAnimationsToMove(); void setAnimationsToMove();
void onWorkspaceAnimUpdate(); void onWorkspaceAnimUpdate();
void onFocusAnimUpdate();
void onUpdateState(); void onUpdateState();
void onUpdateMeta(); void onUpdateMeta();
void onX11Configure(CBox box); void onX11Configure(CBox box);
@@ -469,10 +463,9 @@ class CWindow {
bool isModal(); bool isModal();
Vector2D requestedMinSize(); Vector2D requestedMinSize();
Vector2D requestedMaxSize(); Vector2D requestedMaxSize();
void sendWindowSize(Vector2D size, bool force = false, std::optional<Vector2D> overridePos = std::nullopt);
CBox getWindowMainSurfaceBox() const { CBox getWindowMainSurfaceBox() const {
return {m_vRealPosition->value().x, m_vRealPosition->value().y, m_vRealSize->value().x, m_vRealSize->value().y}; return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y};
} }
// listeners // listeners

View File

@@ -1,15 +1,14 @@
#include "WindowRule.hpp" #include "WindowRule.hpp"
#include <unordered_set> #include <unordered_set>
#include <algorithm> #include <algorithm>
#include <re2/re2.h>
#include "../config/ConfigManager.hpp" #include "../config/ConfigManager.hpp"
static const auto RULES = std::unordered_set<std::string>{ static const auto RULES = std::unordered_set<std::string>{
"float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "renderunfocused", "float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "renderunfocused",
}; };
static const auto RULES_PREFIX = std::unordered_set<std::string>{ static const auto RULES_PREFIX = std::unordered_set<std::string>{
"animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", "move", "opacity", "animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", "move", "opacity",
"plugin:", "prop", "pseudo", "rounding", "roundingpower", "scrollmouse", "scrolltouchpad", "size", "suppressevent", "tag", "workspace", "xray", "plugin:", "prop", "pseudo", "rounding", "scrollmouse", "scrolltouchpad", "size", "suppressevent", "tag", "workspace", "xray",
}; };
CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool isV2, bool isExecRule) : szValue(value), szRule(rule), v2(isV2), execRule(isExecRule) { CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool isV2, bool isExecRule) : szValue(value), szRule(rule), v2(isV2), execRule(isExecRule) {
@@ -88,4 +87,4 @@ CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool
ruleType = RULE_INVALID; ruleType = RULE_INVALID;
} }
} }
} }

View File

@@ -2,7 +2,6 @@
#include <string> #include <string>
#include <cstdint> #include <cstdint>
#include "Rule.hpp"
class CWindowRule { class CWindowRule {
public: public:
@@ -58,11 +57,4 @@ class CWindowRule {
std::string szFullscreenState = ""; // empty means any std::string szFullscreenState = ""; // empty means any
std::string szOnWorkspace = ""; // empty means any std::string szOnWorkspace = ""; // empty means any
std::string szWorkspace = ""; // empty means any std::string szWorkspace = ""; // empty means any
// precompiled regexes
CRuleRegexContainer rTitle;
CRuleRegexContainer rClass;
CRuleRegexContainer rInitialTitle;
CRuleRegexContainer rInitialClass;
CRuleRegexContainer rV1Regex;
}; };

View File

@@ -1,12 +1,7 @@
#include "Workspace.hpp" #include "Workspace.hpp"
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "../config/ConfigValue.hpp" #include "../config/ConfigValue.hpp"
#include "config/ConfigManager.hpp"
#include "managers/AnimationManager.hpp"
#include "../managers/EventManager.hpp"
#include "../managers/HookSystemManager.hpp"
#include <hyprutils/animation/AnimatedVariable.hpp>
#include <hyprutils/string/String.hpp> #include <hyprutils/string/String.hpp>
using namespace Hyprutils::String; using namespace Hyprutils::String;
@@ -24,10 +19,16 @@ CWorkspace::CWorkspace(WORKSPACEID id, PHLMONITOR monitor, std::string name, boo
void CWorkspace::init(PHLWORKSPACE self) { void CWorkspace::init(PHLWORKSPACE self) {
m_pSelf = self; m_pSelf = self;
g_pAnimationManager->createAnimation(Vector2D(0, 0), m_vRenderOffset, m_vRenderOffset.create(m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") :
g_pConfigManager->getAnimationPropertyConfig(m_bIsSpecialWorkspace ? "specialWorkspaceIn" : "workspacesIn"), self, AVARDAMAGE_ENTIRE); g_pConfigManager->getAnimationPropertyConfig("workspacesIn"),
g_pAnimationManager->createAnimation(1.f, m_fAlpha, g_pConfigManager->getAnimationPropertyConfig(m_bIsSpecialWorkspace ? "specialWorkspaceIn" : "workspacesIn"), self, self, AVARDAMAGE_ENTIRE);
AVARDAMAGE_ENTIRE); m_fAlpha.create(AVARTYPE_FLOAT,
m_bIsSpecialWorkspace ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspaceIn") : g_pConfigManager->getAnimationPropertyConfig("workspacesIn"), self,
AVARDAMAGE_ENTIRE);
m_fAlpha.setValueAndWarp(1.f);
m_vRenderOffset.registerVar();
m_fAlpha.registerVar();
const auto RULEFORTHIS = g_pConfigManager->getWorkspaceRuleFor(self); const auto RULEFORTHIS = g_pConfigManager->getWorkspaceRuleFor(self);
if (RULEFORTHIS.defaultName.has_value()) if (RULEFORTHIS.defaultName.has_value())
@@ -54,11 +55,16 @@ void CWorkspace::init(PHLWORKSPACE self) {
EMIT_HOOK_EVENT("createWorkspace", this); EMIT_HOOK_EVENT("createWorkspace", this);
} }
SWorkspaceIDName CWorkspace::getPrevWorkspaceIDName() const { SWorkspaceIDName CWorkspace::getPrevWorkspaceIDName(bool perMonitor) const {
if (perMonitor)
return m_sPrevWorkspacePerMonitor;
return m_sPrevWorkspace; return m_sPrevWorkspace;
} }
CWorkspace::~CWorkspace() { CWorkspace::~CWorkspace() {
m_vRenderOffset.unregister();
Debug::log(LOG, "Destroying workspace ID {}", m_iID); Debug::log(LOG, "Destroying workspace ID {}", m_iID);
// check if g_pHookSystem and g_pEventManager exist, they might be destroyed as in when the compositor is closing. // check if g_pHookSystem and g_pEventManager exist, they might be destroyed as in when the compositor is closing.
@@ -76,15 +82,15 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
if (!instant) { if (!instant) {
const std::string ANIMNAME = std::format("{}{}", m_bIsSpecialWorkspace ? "specialWorkspace" : "workspaces", in ? "In" : "Out"); const std::string ANIMNAME = std::format("{}{}", m_bIsSpecialWorkspace ? "specialWorkspace" : "workspaces", in ? "In" : "Out");
m_fAlpha->setConfig(g_pConfigManager->getAnimationPropertyConfig(ANIMNAME)); m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME);
m_vRenderOffset->setConfig(g_pConfigManager->getAnimationPropertyConfig(ANIMNAME)); m_vRenderOffset.m_pConfig = g_pConfigManager->getAnimationPropertyConfig(ANIMNAME);
} }
const auto ANIMSTYLE = m_fAlpha->getStyle(); const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle;
static auto PWORKSPACEGAP = CConfigValue<Hyprlang::INT>("general:gaps_workspaces"); static auto PWORKSPACEGAP = CConfigValue<Hyprlang::INT>("general:gaps_workspaces");
// set floating windows offset callbacks // set floating windows offset callbacks
m_vRenderOffset->setUpdateCallback([&](auto) { m_vRenderOffset.setUpdateCallback([&](void*) {
for (auto const& w : g_pCompositor->m_vWindows) { for (auto const& w : g_pCompositor->m_vWindows) {
if (!validMapped(w) || w->workspaceID() != m_iID) if (!validMapped(w) || w->workspaceID() != m_iID)
continue; continue;
@@ -104,84 +110,84 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) {
} catch (std::exception& e) { Debug::log(ERR, "Error in startAnim: invalid percentage"); } } catch (std::exception& e) { Debug::log(ERR, "Error in startAnim: invalid percentage"); }
} }
m_fAlpha->setValueAndWarp(1.f); m_fAlpha.setValueAndWarp(1.f);
m_vRenderOffset->setValueAndWarp(Vector2D(0, 0)); m_vRenderOffset.setValueAndWarp(Vector2D(0, 0));
if (ANIMSTYLE.starts_with("slidefadevert")) { if (ANIMSTYLE.starts_with("slidefadevert")) {
if (in) { if (in) {
m_fAlpha->setValueAndWarp(0.f); m_fAlpha.setValueAndWarp(0.f);
m_vRenderOffset->setValueAndWarp(Vector2D(0.0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f))); m_vRenderOffset.setValueAndWarp(Vector2D(0.0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f)));
*m_fAlpha = 1.f; m_fAlpha = 1.f;
*m_vRenderOffset = Vector2D(0, 0); m_vRenderOffset = Vector2D(0, 0);
} else { } else {
m_fAlpha->setValueAndWarp(1.f); m_fAlpha.setValueAndWarp(1.f);
*m_fAlpha = 0.f; m_fAlpha = 0.f;
*m_vRenderOffset = Vector2D(0.0, (left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y) * (movePerc / 100.f)); m_vRenderOffset = Vector2D(0.0, (left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y) * (movePerc / 100.f));
} }
} else { } else {
if (in) { if (in) {
m_fAlpha->setValueAndWarp(0.f); m_fAlpha.setValueAndWarp(0.f);
m_vRenderOffset->setValueAndWarp(Vector2D((left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0)); m_vRenderOffset.setValueAndWarp(Vector2D((left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0));
*m_fAlpha = 1.f; m_fAlpha = 1.f;
*m_vRenderOffset = Vector2D(0, 0); m_vRenderOffset = Vector2D(0, 0);
} else { } else {
m_fAlpha->setValueAndWarp(1.f); m_fAlpha.setValueAndWarp(1.f);
*m_fAlpha = 0.f; m_fAlpha = 0.f;
*m_vRenderOffset = Vector2D((left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0); m_vRenderOffset = Vector2D((left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x) * (movePerc / 100.f), 0.0);
} }
} }
} else if (ANIMSTYLE == "fade") { } else if (ANIMSTYLE == "fade") {
m_vRenderOffset->setValueAndWarp(Vector2D(0, 0)); // fix a bug, if switching from slide -> fade. m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); // fix a bug, if switching from slide -> fade.
if (in) { if (in) {
m_fAlpha->setValueAndWarp(0.f); m_fAlpha.setValueAndWarp(0.f);
*m_fAlpha = 1.f; m_fAlpha = 1.f;
} else { } else {
m_fAlpha->setValueAndWarp(1.f); m_fAlpha.setValueAndWarp(1.f);
*m_fAlpha = 0.f; m_fAlpha = 0.f;
} }
} else if (ANIMSTYLE == "slidevert") { } else if (ANIMSTYLE == "slidevert") {
// fallback is slide // fallback is slide
const auto PMONITOR = m_pMonitor.lock(); const auto PMONITOR = m_pMonitor.lock();
const auto YDISTANCE = PMONITOR->vecSize.y + *PWORKSPACEGAP; const auto YDISTANCE = PMONITOR->vecSize.y + *PWORKSPACEGAP;
m_fAlpha->setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
if (in) { if (in) {
m_vRenderOffset->setValueAndWarp(Vector2D(0.0, left ? YDISTANCE : -YDISTANCE)); m_vRenderOffset.setValueAndWarp(Vector2D(0.0, left ? YDISTANCE : -YDISTANCE));
*m_vRenderOffset = Vector2D(0, 0); m_vRenderOffset = Vector2D(0, 0);
} else { } else {
*m_vRenderOffset = Vector2D(0.0, left ? -YDISTANCE : YDISTANCE); m_vRenderOffset = Vector2D(0.0, left ? -YDISTANCE : YDISTANCE);
} }
} else { } else {
// fallback is slide // fallback is slide
const auto PMONITOR = m_pMonitor.lock(); const auto PMONITOR = m_pMonitor.lock();
const auto XDISTANCE = PMONITOR->vecSize.x + *PWORKSPACEGAP; const auto XDISTANCE = PMONITOR->vecSize.x + *PWORKSPACEGAP;
m_fAlpha->setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide.
if (in) { if (in) {
m_vRenderOffset->setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0.0)); m_vRenderOffset.setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0.0));
*m_vRenderOffset = Vector2D(0, 0); m_vRenderOffset = Vector2D(0, 0);
} else { } else {
*m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0.0); m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0.0);
} }
} }
if (m_bIsSpecialWorkspace) { if (m_bIsSpecialWorkspace) {
// required for open/close animations // required for open/close animations
if (in) { if (in) {
m_fAlpha->setValueAndWarp(0.f); m_fAlpha.setValueAndWarp(0.f);
*m_fAlpha = 1.f; m_fAlpha = 1.f;
} else { } else {
m_fAlpha->setValueAndWarp(1.f); m_fAlpha.setValueAndWarp(1.f);
*m_fAlpha = 0.f; m_fAlpha = 0.f;
} }
} }
if (instant) { if (instant) {
m_vRenderOffset->warp(); m_vRenderOffset.warp();
m_fAlpha->warp(); m_fAlpha.warp();
} }
} }
@@ -215,7 +221,10 @@ void CWorkspace::rememberPrevWorkspace(const PHLWORKSPACE& prev) {
m_sPrevWorkspace.id = prev->m_iID; m_sPrevWorkspace.id = prev->m_iID;
m_sPrevWorkspace.name = prev->m_szName; m_sPrevWorkspace.name = prev->m_szName;
prev->m_pMonitor->addPrevWorkspaceID(prev->m_iID); if (prev->m_pMonitor == m_pMonitor) {
m_sPrevWorkspacePerMonitor.id = prev->m_iID;
m_sPrevWorkspacePerMonitor.name = prev->m_szName;
}
} }
std::string CWorkspace::getConfigName() { std::string CWorkspace::getConfigName() {
@@ -624,7 +633,7 @@ void CWorkspace::forceReportSizesToWindows() {
if (w->m_pWorkspace != m_pSelf || !w->m_bIsMapped || w->isHidden()) if (w->m_pWorkspace != m_pSelf || !w->m_bIsMapped || w->isHidden())
continue; continue;
w->sendWindowSize(w->m_vRealSize->goal(), true); g_pXWaylandManager->setWindowSize(w, w->m_vRealSize.value(), true);
} }
} }

View File

@@ -24,19 +24,22 @@ class CWorkspace {
// Workspaces ID-based have IDs > 0 // Workspaces ID-based have IDs > 0
// and workspaces name-based have IDs starting with -1337 // and workspaces name-based have IDs starting with -1337
WORKSPACEID m_iID = WORKSPACE_INVALID; WORKSPACEID m_iID = WORKSPACE_INVALID;
std::string m_szName = ""; std::string m_szName = "";
PHLMONITORREF m_pMonitor; PHLMONITORREF m_pMonitor;
// Previous workspace ID and name is stored during a workspace change, allowing travel
// to the previous workspace.
SWorkspaceIDName m_sPrevWorkspace, m_sPrevWorkspacePerMonitor;
bool m_bHasFullscreenWindow = false; bool m_bHasFullscreenWindow = false;
eFullscreenMode m_efFullscreenMode = FSMODE_NONE; eFullscreenMode m_efFullscreenMode = FSMODE_NONE;
wl_array m_wlrCoordinateArr; wl_array m_wlrCoordinateArr;
// for animations // for animations
PHLANIMVAR<Vector2D> m_vRenderOffset; CAnimatedVariable<Vector2D> m_vRenderOffset;
PHLANIMVAR<float> m_fAlpha; CAnimatedVariable<float> m_fAlpha;
bool m_bForceRendering = false; bool m_bForceRendering = false;
// allows damage to propagate. // allows damage to propagate.
bool m_bVisible = false; bool m_bVisible = false;
@@ -69,7 +72,7 @@ class CWorkspace {
std::string getConfigName(); std::string getConfigName();
bool matchesStaticSelector(const std::string& selector); bool matchesStaticSelector(const std::string& selector);
void markInert(); void markInert();
SWorkspaceIDName getPrevWorkspaceIDName() const; SWorkspaceIDName getPrevWorkspaceIDName(bool perMonitor) const;
void updateWindowDecos(); void updateWindowDecos();
void updateWindowData(); void updateWindowData();
int getWindows(std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {}); int getWindows(std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
@@ -85,10 +88,7 @@ class CWorkspace {
void updateWindows(); void updateWindows();
private: private:
void init(PHLWORKSPACE self); void init(PHLWORKSPACE self);
// Previous workspace ID and name is stored during a workspace change, allowing travel
// to the previous workspace.
SWorkspaceIDName m_sPrevWorkspace;
SP<HOOK_CALLBACK_FN> m_pFocusedWindowHook; SP<HOOK_CALLBACK_FN> m_pFocusedWindowHook;
bool m_bInert = true; bool m_bInert = true;

View File

@@ -44,10 +44,6 @@ void IKeyboard::clearManuallyAllocd() {
if (xkbKeymapFD >= 0) if (xkbKeymapFD >= 0)
close(xkbKeymapFD); close(xkbKeymapFD);
if (xkbSymState)
xkb_state_unref(xkbSymState);
xkbSymState = nullptr;
xkbKeymap = nullptr; xkbKeymap = nullptr;
xkbState = nullptr; xkbState = nullptr;
xkbStaticState = nullptr; xkbStaticState = nullptr;

View File

@@ -1,5 +1,6 @@
#include "Keyboard.hpp" #include "Keyboard.hpp"
#include "../defines.hpp" #include "../defines.hpp"
#include "../Compositor.hpp"
#include <aquamarine/input/Input.hpp> #include <aquamarine/input/Input.hpp>

View File

@@ -11,7 +11,7 @@ SP<CVirtualPointer> CVirtualPointer::create(SP<CVirtualPointerV1Resource> resour
} }
CVirtualPointer::CVirtualPointer(SP<CVirtualPointerV1Resource> resource) : pointer(resource) { CVirtualPointer::CVirtualPointer(SP<CVirtualPointerV1Resource> resource) : pointer(resource) {
if UNLIKELY (!resource->good()) if (!resource->good())
return; return;
listeners.destroy = pointer->events.destroy.registerListener([this](std::any d) { listeners.destroy = pointer->events.destroy.registerListener([this](std::any d) {

View File

@@ -12,17 +12,10 @@
#include "../protocols/core/Compositor.hpp" #include "../protocols/core/Compositor.hpp"
#include "../protocols/ToplevelExport.hpp" #include "../protocols/ToplevelExport.hpp"
#include "../xwayland/XSurface.hpp" #include "../xwayland/XSurface.hpp"
#include "managers/AnimationManager.hpp"
#include "managers/PointerManager.hpp" #include "managers/PointerManager.hpp"
#include "../desktop/LayerSurface.hpp"
#include "../managers/input/InputManager.hpp"
#include "../managers/LayoutManager.hpp"
#include "../managers/EventManager.hpp"
#include "../managers/AnimationManager.hpp"
#include <hyprutils/string/String.hpp> #include <hyprutils/string/String.hpp>
using namespace Hyprutils::String; using namespace Hyprutils::String;
using namespace Hyprutils::Animation;
// ------------------------------------------------------------ // // ------------------------------------------------------------ //
// __ _______ _ _ _____ ______ _______ // // __ _______ _ _ _____ ______ _______ //
@@ -34,17 +27,15 @@ using namespace Hyprutils::Animation;
// // // //
// ------------------------------------------------------------ // // ------------------------------------------------------------ //
static void setVector2DAnimToMove(WP<CBaseAnimatedVariable> pav) { void setAnimToMove(void* data) {
const auto PAV = pav.lock(); auto* const PANIMCFG = g_pConfigManager->getAnimationPropertyConfig("windowsMove");
if (!PAV)
return;
CAnimatedVariable<Vector2D>* animvar = dynamic_cast<CAnimatedVariable<Vector2D>*>(PAV.get()); CBaseAnimatedVariable* animvar = (CBaseAnimatedVariable*)data;
animvar->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsMove"));
const auto PHLWINDOW = animvar->m_Context.pWindow.lock(); animvar->setConfig(PANIMCFG);
if (PHLWINDOW)
PHLWINDOW->m_bAnimatingIn = false; if (animvar->getWindow() && !animvar->getWindow()->m_vRealPosition.isBeingAnimated() && !animvar->getWindow()->m_vRealSize.isBeingAnimated())
animvar->getWindow()->m_bAnimatingIn = false;
} }
void Events::listener_mapWindow(void* owner, void* data) { void Events::listener_mapWindow(void* owner, void* data) {
@@ -130,13 +121,22 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_bX11ShouldntFocus = PWINDOW->m_bX11ShouldntFocus || (PWINDOW->m_bIsX11 && PWINDOW->isX11OverrideRedirect() && !PWINDOW->m_pXWaylandSurface->wantsFocus()); PWINDOW->m_bX11ShouldntFocus = PWINDOW->m_bX11ShouldntFocus || (PWINDOW->m_bIsX11 && PWINDOW->isX11OverrideRedirect() && !PWINDOW->m_pXWaylandSurface->wantsFocus());
if (PWORKSPACE->m_bDefaultFloating)
PWINDOW->m_bIsFloating = true;
if (PWORKSPACE->m_bDefaultPseudo) {
PWINDOW->m_bIsPseudotiled = true;
CBox desiredGeometry = {0};
g_pXWaylandManager->getGeometryForWindow(PWINDOW, &desiredGeometry);
PWINDOW->m_vPseudoSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
}
// window rules // window rules
PWINDOW->m_vMatchedRules = g_pConfigManager->getMatchingRules(PWINDOW, false); PWINDOW->m_vMatchedRules = g_pConfigManager->getMatchingRules(PWINDOW, false);
std::optional<eFullscreenMode> requestedInternalFSMode, requestedClientFSMode; std::optional<eFullscreenMode> requestedInternalFSMode, requestedClientFSMode;
std::optional<SFullscreenState> requestedFSState; std::optional<SFullscreenState> requestedFSState;
if (PWINDOW->m_bWantsInitialFullscreen || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->fullscreen)) if (PWINDOW->m_bWantsInitialFullscreen || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->fullscreen))
requestedClientFSMode = FSMODE_FULLSCREEN; requestedClientFSMode = FSMODE_FULLSCREEN;
MONITORID requestedFSMonitor = PWINDOW->m_iWantsInitialFullscreenMonitor;
for (auto const& r : PWINDOW->m_vMatchedRules) { for (auto const& r : PWINDOW->m_vMatchedRules) {
switch (r->ruleType) { switch (r->ruleType) {
@@ -171,10 +171,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
PMONITOR = PMONITORFROMID; PMONITOR = PMONITORFROMID;
} }
PWINDOW->m_pWorkspace = PMONITOR->activeSpecialWorkspace ? PMONITOR->activeSpecialWorkspace : PMONITOR->activeWorkspace; PWINDOW->m_pWorkspace = PMONITOR->activeSpecialWorkspace ? PMONITOR->activeSpecialWorkspace : PMONITOR->activeWorkspace;
PWORKSPACE = PWINDOW->m_pWorkspace;
Debug::log(LOG, "Rule monitor, applying to {:mw}", PWINDOW); Debug::log(LOG, "Rule monitor, applying to {:mw}", PWINDOW);
requestedFSMonitor = MONITOR_INVALID;
} catch (std::exception& e) { Debug::log(ERR, "Rule monitor failed, rule: {} -> {} | err: {}", r->szRule, r->szValue, e.what()); } } catch (std::exception& e) { Debug::log(ERR, "Rule monitor failed, rule: {} -> {} | err: {}", r->szRule, r->szValue, e.what()); }
break; break;
} }
@@ -182,10 +180,11 @@ void Events::listener_mapWindow(void* owner, void* data) {
// check if it isnt unset // check if it isnt unset
const auto WORKSPACERQ = r->szRule.substr(r->szRule.find_first_of(' ') + 1); const auto WORKSPACERQ = r->szRule.substr(r->szRule.find_first_of(' ') + 1);
if (WORKSPACERQ == "unset") if (WORKSPACERQ == "unset") {
requestedWorkspace = ""; requestedWorkspace = "";
else } else {
requestedWorkspace = WORKSPACERQ; requestedWorkspace = WORKSPACERQ;
}
const auto JUSTWORKSPACE = WORKSPACERQ.contains(' ') ? WORKSPACERQ.substr(0, WORKSPACERQ.find_first_of(' ')) : WORKSPACERQ; const auto JUSTWORKSPACE = WORKSPACERQ.contains(' ') ? WORKSPACERQ.substr(0, WORKSPACERQ.find_first_of(' ')) : WORKSPACERQ;
@@ -193,7 +192,6 @@ void Events::listener_mapWindow(void* owner, void* data) {
requestedWorkspace = ""; requestedWorkspace = "";
Debug::log(LOG, "Rule workspace matched by {}, {} applied.", PWINDOW, r->szValue); Debug::log(LOG, "Rule workspace matched by {}, {} applied.", PWINDOW, r->szValue);
requestedFSMonitor = MONITOR_INVALID;
break; break;
} }
case CWindowRule::RULE_FLOAT: { case CWindowRule::RULE_FLOAT: {
@@ -235,8 +233,6 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE; PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE;
else if (vars[i] == "activatefocus") else if (vars[i] == "activatefocus")
PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE_FOCUSONLY; PWINDOW->m_eSuppressedEvents |= SUPPRESS_ACTIVATE_FOCUSONLY;
else if (vars[i] == "fullscreenoutput")
PWINDOW->m_eSuppressedEvents |= SUPPRESS_FULLSCREEN_OUTPUT;
else else
Debug::log(ERR, "Error while parsing suppressevent windowrule: unknown event type {}", vars[i]); Debug::log(ERR, "Error while parsing suppressevent windowrule: unknown event type {}", vars[i]);
} }
@@ -347,39 +343,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
PMONITOR = g_pCompositor->m_pLastMonitor.lock(); PMONITOR = g_pCompositor->m_pLastMonitor.lock();
} }
requestedFSMonitor = MONITOR_INVALID;
} else } else
workspaceSilent = false; workspaceSilent = false;
} }
if (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN_OUTPUT)
requestedFSMonitor = MONITOR_INVALID;
else if (requestedFSMonitor != MONITOR_INVALID) {
if (const auto PM = g_pCompositor->getMonitorFromID(requestedFSMonitor); PM)
PWINDOW->m_pMonitor = PM;
const auto PMONITORFROMID = PWINDOW->m_pMonitor.lock();
if (PWINDOW->m_pMonitor != PMONITOR) {
g_pKeybindManager->m_mDispatchers["focusmonitor"](std::to_string(PWINDOW->monitorID()));
PMONITOR = PMONITORFROMID;
}
PWINDOW->m_pWorkspace = PMONITOR->activeSpecialWorkspace ? PMONITOR->activeSpecialWorkspace : PMONITOR->activeWorkspace;
PWORKSPACE = PWINDOW->m_pWorkspace;
Debug::log(LOG, "Requested monitor, applying to {:mw}", PWINDOW);
}
if (PWORKSPACE->m_bDefaultFloating)
PWINDOW->m_bIsFloating = true;
if (PWORKSPACE->m_bDefaultPseudo) {
PWINDOW->m_bIsPseudotiled = true;
CBox desiredGeometry = g_pXWaylandManager->getGeometryForWindow(PWINDOW);
PWINDOW->m_vPseudoSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
}
PWINDOW->updateWindowData(); PWINDOW->updateWindowData();
// Verify window swallowing. Get the swallower before calling onWindowCreated(PWINDOW) because getSwallower() wouldn't get it after if PWINDOW gets auto grouped. // Verify window swallowing. Get the swallower before calling onWindowCreated(PWINDOW) because getSwallower() wouldn't get it after if PWINDOW gets auto grouped.
@@ -411,10 +378,10 @@ void Events::listener_mapWindow(void* owner, void* data) {
const auto MAXSIZE = PWINDOW->requestedMaxSize(); const auto MAXSIZE = PWINDOW->requestedMaxSize();
const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->vecSize.x) : const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->vecSize.x) :
stringToFloatClamp(SIZEXSTR, PWINDOW->m_vRealSize->goal().x, PMONITOR->vecSize.x); stringToFloatClamp(SIZEXSTR, PWINDOW->m_vRealSize.goal().x, PMONITOR->vecSize.x);
const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, PMONITOR->vecSize.y) : const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, PMONITOR->vecSize.y) :
stringToFloatClamp(SIZEYSTR, PWINDOW->m_vRealSize->goal().y, PMONITOR->vecSize.y); stringToFloatClamp(SIZEYSTR, PWINDOW->m_vRealSize.goal().y, PMONITOR->vecSize.y);
Debug::log(LOG, "Rule size, applying to {}", PWINDOW); Debug::log(LOG, "Rule size, applying to {}", PWINDOW);
@@ -451,7 +418,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
(!POSXRAW.contains('%') ? std::stoi(POSXRAW) : std::stof(POSXRAW.substr(0, POSXRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.x); (!POSXRAW.contains('%') ? std::stoi(POSXRAW) : std::stof(POSXRAW.substr(0, POSXRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.x);
if (subtractWindow) if (subtractWindow)
posX -= PWINDOW->m_vRealSize->goal().x; posX -= PWINDOW->m_vRealSize.goal().x;
if (CURSOR) if (CURSOR)
Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!"); Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!");
@@ -463,7 +430,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x; posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x;
} else { } else {
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x + posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->vecPosition.x +
(!POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize->goal().x); (!POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goal().x);
} }
} }
@@ -474,7 +441,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
(!POSYRAW.contains('%') ? std::stoi(POSYRAW) : std::stof(POSYRAW.substr(0, POSYRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.y); (!POSYRAW.contains('%') ? std::stoi(POSYRAW) : std::stof(POSYRAW.substr(0, POSYRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.y);
if (subtractWindow) if (subtractWindow)
posY -= PWINDOW->m_vRealSize->goal().y; posY -= PWINDOW->m_vRealSize.goal().y;
if (CURSOR) if (CURSOR)
Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!"); Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!");
@@ -486,7 +453,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y; posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y;
} else { } else {
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y + posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->vecPosition.y +
(!POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize->goal().y); (!POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PWINDOW->m_vRealSize.goal().y);
} }
} }
@@ -494,15 +461,15 @@ void Events::listener_mapWindow(void* owner, void* data) {
int borderSize = PWINDOW->getRealBorderSize(); int borderSize = PWINDOW->getRealBorderSize();
posX = std::clamp(posX, (int)(PMONITOR->vecReservedTopLeft.x + borderSize), posX = std::clamp(posX, (int)(PMONITOR->vecReservedTopLeft.x + borderSize),
(int)(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PWINDOW->m_vRealSize->goal().x - borderSize)); (int)(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PWINDOW->m_vRealSize.goal().x - borderSize));
posY = std::clamp(posY, (int)(PMONITOR->vecReservedTopLeft.y + borderSize), posY = std::clamp(posY, (int)(PMONITOR->vecReservedTopLeft.y + borderSize),
(int)(PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PWINDOW->m_vRealSize->goal().y - borderSize)); (int)(PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PWINDOW->m_vRealSize.goal().y - borderSize));
} }
Debug::log(LOG, "Rule move, applying to {}", PWINDOW); Debug::log(LOG, "Rule move, applying to {}", PWINDOW);
*PWINDOW->m_vRealPosition = Vector2D(posX, posY) + PMONITOR->vecPosition; PWINDOW->m_vRealPosition = Vector2D(posX, posY) + PMONITOR->vecPosition;
PWINDOW->setHidden(false); PWINDOW->setHidden(false);
} catch (...) { Debug::log(LOG, "Rule move failed, rule: {} -> {}", r->szRule, r->szValue); } } catch (...) { Debug::log(LOG, "Rule move failed, rule: {} -> {}", r->szRule, r->szValue); }
@@ -514,7 +481,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (ARGS[1] == "1") if (ARGS[1] == "1")
RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f; RESERVEDOFFSET = (PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight) / 2.f;
*PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize->goal() / 2.f + RESERVEDOFFSET; PWINDOW->m_vRealPosition = PMONITOR->middle() - PWINDOW->m_vRealSize.goal() / 2.f + RESERVEDOFFSET;
break; break;
} }
@@ -524,7 +491,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
// set the pseudo size to the GOAL of our current size // set the pseudo size to the GOAL of our current size
// because the windows are animated on RealSize // because the windows are animated on RealSize
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize->goal(); PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal();
g_pCompositor->changeWindowZOrder(PWINDOW, true); g_pCompositor->changeWindowZOrder(PWINDOW, true);
} else { } else {
@@ -557,7 +524,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
} }
if (!setPseudo) if (!setPseudo)
PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize->goal() - Vector2D(10, 10); PWINDOW->m_vPseudoSize = PWINDOW->m_vRealSize.goal() - Vector2D(10, 10);
} }
const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_pLastWindow.lock(); const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_pLastWindow.lock();
@@ -587,11 +554,11 @@ void Events::listener_mapWindow(void* owner, void* data) {
(!PWINDOW->isX11OverrideRedirect() || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->wantsFocus())) && !workspaceSilent && (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW) && (!PWINDOW->isX11OverrideRedirect() || (PWINDOW->m_bIsX11 && PWINDOW->m_pXWaylandSurface->wantsFocus())) && !workspaceSilent && (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW) &&
!g_pInputManager->isConstrained()) { !g_pInputManager->isConstrained()) {
g_pCompositor->focusWindow(PWINDOW); g_pCompositor->focusWindow(PWINDOW);
PWINDOW->m_fActiveInactiveAlpha->setValueAndWarp(*PACTIVEALPHA); PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PACTIVEALPHA);
PWINDOW->m_fDimPercent->setValueAndWarp(PWINDOW->m_sWindowData.noDim.valueOrDefault() ? 0.f : *PDIMSTRENGTH); PWINDOW->m_fDimPercent.setValueAndWarp(PWINDOW->m_sWindowData.noDim.valueOrDefault() ? 0.f : *PDIMSTRENGTH);
} else { } else {
PWINDOW->m_fActiveInactiveAlpha->setValueAndWarp(*PINACTIVEALPHA); PWINDOW->m_fActiveInactiveAlpha.setValueAndWarp(*PINACTIVEALPHA);
PWINDOW->m_fDimPercent->setValueAndWarp(0); PWINDOW->m_fDimPercent.setValueAndWarp(0);
} }
if (requestedClientFSMode.has_value() && (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN)) if (requestedClientFSMode.has_value() && (PWINDOW->m_eSuppressedEvents & SUPPRESS_FULLSCREEN))
@@ -604,8 +571,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (PWINDOW->m_pWorkspace->m_bHasFullscreenWindow) if (PWINDOW->m_pWorkspace->m_bHasFullscreenWindow)
g_pCompositor->setWindowFullscreenInternal(PWINDOW->m_pWorkspace->getFullscreenWindow(), FSMODE_NONE); g_pCompositor->setWindowFullscreenInternal(PWINDOW->m_pWorkspace->getFullscreenWindow(), FSMODE_NONE);
PWINDOW->m_vRealPosition->warp(); PWINDOW->m_vRealPosition.warp();
PWINDOW->m_vRealSize->warp(); PWINDOW->m_vRealSize.warp();
if (requestedFSState.has_value()) { if (requestedFSState.has_value()) {
PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_WINDOW_RULE); PWINDOW->m_sWindowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_WINDOW_RULE);
g_pCompositor->setWindowFullscreenState(PWINDOW, requestedFSState.value()); g_pCompositor->setWindowFullscreenState(PWINDOW, requestedFSState.value());
@@ -640,7 +607,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
PWINDOW->m_bFirstMap = false; PWINDOW->m_bFirstMap = false;
Debug::log(LOG, "Map request dispatched, monitor {}, window pos: {:5j}, window size: {:5j}", PMONITOR->szName, PWINDOW->m_vRealPosition->goal(), PWINDOW->m_vRealSize->goal()); Debug::log(LOG, "Map request dispatched, monitor {}, window pos: {:5j}, window size: {:5j}", PMONITOR->szName, PWINDOW->m_vRealPosition.goal(), PWINDOW->m_vRealSize.goal());
auto workspaceID = requestedWorkspace != "" ? requestedWorkspace : PWORKSPACE->m_szName; auto workspaceID = requestedWorkspace != "" ? requestedWorkspace : PWORKSPACE->m_szName;
g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", std::format("{:x},{},{},{}", PWINDOW, workspaceID, PWINDOW->m_szClass, PWINDOW->m_szTitle)}); g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", std::format("{:x},{},{},{}", PWINDOW, workspaceID, PWINDOW->m_szClass, PWINDOW->m_szTitle)});
@@ -653,17 +620,17 @@ void Events::listener_mapWindow(void* owner, void* data) {
// do animations // do animations
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, false); g_pAnimationManager->onWindowPostCreateClose(PWINDOW, false);
PWINDOW->m_fAlpha->setValueAndWarp(0.f); PWINDOW->m_fAlpha.setValueAndWarp(0.f);
*PWINDOW->m_fAlpha = 1.f; PWINDOW->m_fAlpha = 1.f;
PWINDOW->m_vRealPosition->setCallbackOnEnd(setVector2DAnimToMove); PWINDOW->m_vRealPosition.setCallbackOnEnd(setAnimToMove);
PWINDOW->m_vRealSize->setCallbackOnEnd(setVector2DAnimToMove); PWINDOW->m_vRealSize.setCallbackOnEnd(setAnimToMove);
// recalc the values for this window // recalc the values for this window
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW); g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
// avoid this window being visible // avoid this window being visible
if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->isFullscreen() && !PWINDOW->m_bIsFloating) if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->isFullscreen() && !PWINDOW->m_bIsFloating)
PWINDOW->m_fAlpha->setValueAndWarp(0.f); PWINDOW->m_fAlpha.setValueAndWarp(0.f);
g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface->resource(), PMONITOR->scale); g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface->resource(), PMONITOR->scale);
g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface->resource(), PMONITOR->transform); g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface->resource(), PMONITOR->transform);
@@ -679,13 +646,6 @@ void Events::listener_mapWindow(void* owner, void* data) {
if (PMONITOR && PWINDOW->isX11OverrideRedirect()) if (PMONITOR && PWINDOW->isX11OverrideRedirect())
PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale; PWINDOW->m_fX11SurfaceScaledBy = PMONITOR->scale;
// Fix some X11 popups being invisible / having incorrect size on open.
// What the ACTUAL FUCK is going on?????? I HATE X11
if (!PWINDOW->isX11OverrideRedirect() && PWINDOW->m_bIsX11 && PWINDOW->m_bIsFloating) {
PWINDOW->sendWindowSize(PWINDOW->m_vRealSize->goal(), true, PWINDOW->m_vRealPosition->goal() - Vector2D{1, 1});
PWINDOW->sendWindowSize(PWINDOW->m_vRealSize->goal(), true);
}
} }
void Events::listener_unmapWindow(void* owner, void* data) { void Events::listener_unmapWindow(void* owner, void* data) {
@@ -706,8 +666,8 @@ void Events::listener_unmapWindow(void* owner, void* data) {
const auto PMONITOR = PWINDOW->m_pMonitor.lock(); const auto PMONITOR = PWINDOW->m_pMonitor.lock();
if (PMONITOR) { if (PMONITOR) {
PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition->value() - PMONITOR->vecPosition; PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.value() - PMONITOR->vecPosition;
PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize->value(); PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.value();
PWINDOW->m_eOriginalClosedExtents = PWINDOW->getFullWindowExtents(); PWINDOW->m_eOriginalClosedExtents = PWINDOW->getFullWindowExtents();
} }
@@ -720,7 +680,7 @@ void Events::listener_unmapWindow(void* owner, void* data) {
g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE); g_pCompositor->setWindowFullscreenInternal(PWINDOW, FSMODE_NONE);
// Allow the renderer to catch the last frame. // Allow the renderer to catch the last frame.
g_pHyprRenderer->makeWindowSnapshot(PWINDOW); g_pHyprOpenGL->makeWindowSnapshot(PWINDOW);
// swallowing // swallowing
if (valid(PWINDOW->m_pSwallowed)) { if (valid(PWINDOW->m_pSwallowed)) {
@@ -797,12 +757,12 @@ void Events::listener_unmapWindow(void* owner, void* data) {
g_pCompositor->addToFadingOutSafe(PWINDOW); g_pCompositor->addToFadingOutSafe(PWINDOW);
if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in. if (!PWINDOW->m_bX11DoesntWantBorders) // don't animate out if they weren't animated in.
*PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition->value() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.value() + Vector2D(0.01f, 0.01f); // it has to be animated, otherwise onWindowPostCreateClose will ignore it
// anims // anims
g_pAnimationManager->onWindowPostCreateClose(PWINDOW, true); g_pAnimationManager->onWindowPostCreateClose(PWINDOW, true);
*PWINDOW->m_fAlpha = 0.f; PWINDOW->m_fAlpha = 0.f;
// recheck idle inhibitors // recheck idle inhibitors
g_pInputManager->recheckIdleInhibitorStatus(); g_pInputManager->recheckIdleInhibitorStatus();
@@ -852,7 +812,7 @@ void Events::listener_commitWindow(void* owner, void* data) {
g_pSeatManager->isPointerFrameSkipped = false; g_pSeatManager->isPointerFrameSkipped = false;
g_pSeatManager->isPointerFrameCommit = false; g_pSeatManager->isPointerFrameCommit = false;
} else } else
g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface->resource(), PWINDOW->m_vRealPosition->goal().x, PWINDOW->m_vRealPosition->goal().y, g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface->resource(), PWINDOW->m_vRealPosition.goal().x, PWINDOW->m_vRealPosition.goal().y,
PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0); PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0);
if (g_pSeatManager->isPointerFrameSkipped) { if (g_pSeatManager->isPointerFrameSkipped) {
@@ -912,6 +872,15 @@ void Events::listener_destroyWindow(void* owner, void* data) {
PWINDOW->listeners.commit.reset(); PWINDOW->listeners.commit.reset();
} }
void Events::listener_setTitleWindow(void* owner, void* data) {
PHLWINDOW PWINDOW = ((CWindow*)owner)->m_pSelf.lock();
if (!validMapped(PWINDOW))
return;
PWINDOW->onUpdateMeta();
}
void Events::listener_activateX11(void* owner, void* data) { void Events::listener_activateX11(void* owner, void* data) {
PHLWINDOW PWINDOW = ((CWindow*)owner)->m_pSelf.lock(); PHLWINDOW PWINDOW = ((CWindow*)owner)->m_pSelf.lock();
@@ -943,8 +912,8 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
if (!PWINDOW->m_bIsMapped || !PWINDOW->m_pXWaylandSurface || !PWINDOW->m_pXWaylandSurface->overrideRedirect) if (!PWINDOW->m_bIsMapped || !PWINDOW->m_pXWaylandSurface || !PWINDOW->m_pXWaylandSurface->overrideRedirect)
return; return;
const auto POS = PWINDOW->m_vRealPosition->goal(); const auto POS = PWINDOW->m_vRealPosition.goal();
const auto SIZ = PWINDOW->m_vRealSize->goal(); const auto SIZ = PWINDOW->m_vRealSize.goal();
if (PWINDOW->m_pXWaylandSurface->geometry.size() > Vector2D{1, 1}) if (PWINDOW->m_pXWaylandSurface->geometry.size() > Vector2D{1, 1})
PWINDOW->setHidden(false); PWINDOW->setHidden(false);
@@ -952,7 +921,7 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
PWINDOW->setHidden(true); PWINDOW->setHidden(true);
if (PWINDOW->isFullscreen() || !PWINDOW->m_bIsFloating) { if (PWINDOW->isFullscreen() || !PWINDOW->m_bIsFloating) {
PWINDOW->sendWindowSize(PWINDOW->m_vRealSize->goal(), true); g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal(), true);
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
return; return;
} }
@@ -966,27 +935,27 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) {
Debug::log(LOG, "Unmanaged window {} requests geometry update to {:j} {:j}", PWINDOW, LOGICALPOS, PWINDOW->m_pXWaylandSurface->geometry.size()); Debug::log(LOG, "Unmanaged window {} requests geometry update to {:j} {:j}", PWINDOW, LOGICALPOS, PWINDOW->m_pXWaylandSurface->geometry.size());
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
PWINDOW->m_vRealPosition->setValueAndWarp(Vector2D(LOGICALPOS.x, LOGICALPOS.y)); PWINDOW->m_vRealPosition.setValueAndWarp(Vector2D(LOGICALPOS.x, LOGICALPOS.y));
if (abs(std::floor(SIZ.x) - PWINDOW->m_pXWaylandSurface->geometry.w) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_pXWaylandSurface->geometry.h) > 2) if (abs(std::floor(SIZ.x) - PWINDOW->m_pXWaylandSurface->geometry.w) > 2 || abs(std::floor(SIZ.y) - PWINDOW->m_pXWaylandSurface->geometry.h) > 2)
PWINDOW->m_vRealSize->setValueAndWarp(PWINDOW->m_pXWaylandSurface->geometry.size()); PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_pXWaylandSurface->geometry.size());
if (*PXWLFORCESCALEZERO) { if (*PXWLFORCESCALEZERO) {
if (const auto PMONITOR = PWINDOW->m_pMonitor.lock(); PMONITOR) { if (const auto PMONITOR = PWINDOW->m_pMonitor.lock(); PMONITOR) {
PWINDOW->m_vRealSize->setValueAndWarp(PWINDOW->m_vRealSize->goal() / PMONITOR->scale); PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goal() / PMONITOR->scale);
} }
} }
PWINDOW->m_vPosition = PWINDOW->m_vRealPosition->goal(); PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goal();
PWINDOW->m_vSize = PWINDOW->m_vRealSize->goal(); PWINDOW->m_vSize = PWINDOW->m_vRealSize.goal();
PWINDOW->m_pWorkspace = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition->value() + PWINDOW->m_vRealSize->value() / 2.f)->activeWorkspace; PWINDOW->m_pWorkspace = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.value() + PWINDOW->m_vRealSize.value() / 2.f)->activeWorkspace;
g_pCompositor->changeWindowZOrder(PWINDOW, true); g_pCompositor->changeWindowZOrder(PWINDOW, true);
PWINDOW->updateWindowDecos(); PWINDOW->updateWindowDecos();
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
PWINDOW->m_vReportedPosition = PWINDOW->m_vRealPosition->goal(); PWINDOW->m_vReportedPosition = PWINDOW->m_vRealPosition.goal();
PWINDOW->m_vPendingReportedSize = PWINDOW->m_vRealSize->goal(); PWINDOW->m_vPendingReportedSize = PWINDOW->m_vRealSize.goal();
} }
} }

View File

@@ -0,0 +1,92 @@
#include "AnimatedVariable.hpp"
#include "../managers/AnimationManager.hpp"
#include "../config/ConfigManager.hpp"
CBaseAnimatedVariable::CBaseAnimatedVariable(eAnimatedVarType type) : m_Type(type) {
; // dummy var
}
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLWINDOW pWindow, eAVarDamagePolicy policy) {
m_eDamagePolicy = policy;
m_pConfig = pAnimConfig;
m_pWindow = pWindow;
m_bDummy = false;
}
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLLS pLayer, eAVarDamagePolicy policy) {
m_eDamagePolicy = policy;
m_pConfig = pAnimConfig;
m_pLayer = pLayer;
m_bDummy = false;
}
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, PHLWORKSPACE pWorkspace, eAVarDamagePolicy policy) {
m_eDamagePolicy = policy;
m_pConfig = pAnimConfig;
m_pWorkspace = pWorkspace;
m_bDummy = false;
}
void CBaseAnimatedVariable::create(SAnimationPropertyConfig* pAnimConfig, eAVarDamagePolicy policy) {
m_eDamagePolicy = policy;
m_pConfig = pAnimConfig;
m_bDummy = false;
}
CBaseAnimatedVariable::~CBaseAnimatedVariable() {
unregister();
}
void CBaseAnimatedVariable::unregister() {
if (!g_pAnimationManager)
return;
std::erase_if(g_pAnimationManager->m_vAnimatedVariables, [&](const auto& other) { return other == this; });
m_bIsRegistered = false;
disconnectFromActive();
}
void CBaseAnimatedVariable::registerVar() {
if (!m_bIsRegistered)
g_pAnimationManager->m_vAnimatedVariables.push_back(this);
m_bIsRegistered = true;
}
int CBaseAnimatedVariable::getDurationLeftMs() {
return std::max(
(int)(m_pConfig->pValues->internalSpeed * 100) - (int)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - animationBegin).count(), 0);
}
float CBaseAnimatedVariable::getPercent() {
const auto DURATIONPASSED = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - animationBegin).count();
return std::clamp((DURATIONPASSED / 100.f) / m_pConfig->pValues->internalSpeed, 0.f, 1.f);
}
float CBaseAnimatedVariable::getCurveValue() {
if (!m_bIsBeingAnimated)
return 1.f;
const auto SPENT = getPercent();
if (SPENT >= 1.f)
return 1.f;
return g_pAnimationManager->getBezier(m_pConfig->pValues->internalBezier)->getYForPoint(SPENT);
}
void CBaseAnimatedVariable::connectToActive() {
g_pAnimationManager->scheduleTick(); // otherwise the animation manager will never pick this up
if (!m_bIsConnectedToActive)
g_pAnimationManager->m_vActiveAnimatedVariables.push_back(this);
m_bIsConnectedToActive = true;
}
void CBaseAnimatedVariable::disconnectFromActive() {
std::erase_if(g_pAnimationManager->m_vActiveAnimatedVariables, [&](const auto& other) { return other == this; });
m_bIsConnectedToActive = false;
}

View File

@@ -1,18 +1,15 @@
#pragma once #pragma once
#include <hyprutils/animation/AnimatedVariable.hpp> #include <functional>
#include <any>
#include <chrono>
#include <type_traits>
#include "math/Math.hpp"
#include "Color.hpp" #include "Color.hpp"
#include "../defines.hpp" #include "../defines.hpp"
#include "../debug/Log.hpp"
#include "../desktop/DesktopTypes.hpp" #include "../desktop/DesktopTypes.hpp"
enum eAVarDamagePolicy : int8_t {
AVARDAMAGE_NONE = -1,
AVARDAMAGE_ENTIRE = 0,
AVARDAMAGE_BORDER,
AVARDAMAGE_SHADOW
};
enum eAnimatedVarType : int8_t { enum eAnimatedVarType : int8_t {
AVARTYPE_INVALID = -1, AVARTYPE_INVALID = -1,
AVARTYPE_FLOAT, AVARTYPE_FLOAT,
@@ -45,6 +42,20 @@ struct STypeToAnimatedVarType_t<CHyprColor> {
template <class T> template <class T>
inline constexpr eAnimatedVarType typeToeAnimatedVarType = STypeToAnimatedVarType_t<T>::value; inline constexpr eAnimatedVarType typeToeAnimatedVarType = STypeToAnimatedVarType_t<T>::value;
enum eAVarDamagePolicy : int8_t {
AVARDAMAGE_NONE = -1,
AVARDAMAGE_ENTIRE = 0,
AVARDAMAGE_BORDER,
AVARDAMAGE_SHADOW
};
class CAnimationManager;
struct SAnimationPropertyConfig;
class CHyprRenderer;
class CWindow;
class CWorkspace;
class CLayerSurface;
// Utility to define a concept as a list of possible type // Utility to define a concept as a list of possible type
template <class T, class... U> template <class T, class... U>
concept OneOf = (... or std::same_as<T, U>); concept OneOf = (... or std::same_as<T, U>);
@@ -55,19 +66,247 @@ concept OneOf = (... or std::same_as<T, U>);
template <class T> template <class T>
concept Animable = OneOf<T, Vector2D, float, CHyprColor>; concept Animable = OneOf<T, Vector2D, float, CHyprColor>;
struct SAnimationContext { class CBaseAnimatedVariable {
PHLWINDOWREF pWindow; public:
PHLWORKSPACEREF pWorkspace; CBaseAnimatedVariable(eAnimatedVarType type);
PHLLSREF pLayer; void create(SAnimationPropertyConfig* pAnimConfig, PHLWINDOW pWindow, eAVarDamagePolicy policy);
void create(SAnimationPropertyConfig* pAnimConfig, PHLLS pLayer, eAVarDamagePolicy policy);
void create(SAnimationPropertyConfig* pAnimConfig, PHLWORKSPACE pWorkspace, eAVarDamagePolicy policy);
void create(SAnimationPropertyConfig* pAnimConfig, eAVarDamagePolicy policy);
eAVarDamagePolicy eDamagePolicy = AVARDAMAGE_NONE; CBaseAnimatedVariable(const CBaseAnimatedVariable&) = delete;
CBaseAnimatedVariable(CBaseAnimatedVariable&&) = delete;
CBaseAnimatedVariable& operator=(const CBaseAnimatedVariable&) = delete;
CBaseAnimatedVariable& operator=(CBaseAnimatedVariable&&) = delete;
virtual ~CBaseAnimatedVariable();
void unregister();
void registerVar();
virtual void warp(bool endCallback = true) = 0;
//
void setConfig(SAnimationPropertyConfig* pConfig) {
m_pConfig = pConfig;
}
SAnimationPropertyConfig* getConfig() {
return m_pConfig;
}
int getDurationLeftMs();
/* returns the spent (completion) % */
float getPercent();
/* returns the current curve value */
float getCurveValue();
// checks if an animation is in progress
bool isBeingAnimated() const {
return m_bIsBeingAnimated;
}
/* sets a function to be ran when the animation finishes.
if an animation is not running, runs instantly.
if "remove" is set to true, will remove the callback when ran. */
void setCallbackOnEnd(std::function<void(void* thisptr)> func, bool remove = true) {
m_fEndCallback = std::move(func);
m_bRemoveEndAfterRan = remove;
if (!isBeingAnimated())
onAnimationEnd();
}
/* sets a function to be ran when an animation is started.
if "remove" is set to true, will remove the callback when ran. */
void setCallbackOnBegin(std::function<void(void* thisptr)> func, bool remove = true) {
m_fBeginCallback = std::move(func);
m_bRemoveBeginAfterRan = remove;
}
/* Sets the update callback, called every time the value is animated and a step is done
Warning: calling unregisterVar/registerVar in this handler will cause UB */
void setUpdateCallback(std::function<void(void* thisptr)> func) {
m_fUpdateCallback = std::move(func);
}
/* resets all callbacks. Does not call any. */
void resetAllCallbacks() {
m_fBeginCallback = nullptr;
m_fEndCallback = nullptr;
m_fUpdateCallback = nullptr;
m_bRemoveBeginAfterRan = false;
m_bRemoveEndAfterRan = false;
}
PHLWINDOW getWindow() {
return m_pWindow.lock();
}
protected:
PHLWINDOWREF m_pWindow;
PHLWORKSPACEREF m_pWorkspace;
PHLLSREF m_pLayer;
SAnimationPropertyConfig* m_pConfig = nullptr;
bool m_bDummy = true;
bool m_bIsRegistered = false;
bool m_bIsBeingAnimated = false;
std::chrono::steady_clock::time_point animationBegin;
eAVarDamagePolicy m_eDamagePolicy = AVARDAMAGE_NONE;
eAnimatedVarType m_Type;
bool m_bRemoveEndAfterRan = true;
bool m_bRemoveBeginAfterRan = true;
std::function<void(void* thisptr)> m_fEndCallback;
std::function<void(void* thisptr)> m_fBeginCallback;
std::function<void(void* thisptr)> m_fUpdateCallback;
bool m_bIsConnectedToActive = false;
void connectToActive();
void disconnectFromActive();
// methods
void onAnimationEnd() {
m_bIsBeingAnimated = false;
disconnectFromActive();
if (m_fEndCallback) {
// loading m_bRemoveEndAfterRan before calling the callback allows the callback to delete this animation safely if it is false.
auto removeEndCallback = m_bRemoveEndAfterRan;
m_fEndCallback(this);
if (removeEndCallback)
m_fEndCallback = nullptr; // reset
}
}
void onAnimationBegin() {
m_bIsBeingAnimated = true;
connectToActive();
if (m_fBeginCallback) {
m_fBeginCallback(this);
if (m_bRemoveBeginAfterRan)
m_fBeginCallback = nullptr; // reset
}
}
friend class CAnimationManager;
friend class CWorkspace;
friend class CLayerSurface;
friend class CHyprRenderer;
}; };
template <Animable VarType> template <Animable VarType>
using CAnimatedVariable = Hyprutils::Animation::CGenericAnimatedVariable<VarType, SAnimationContext>; class CAnimatedVariable : public CBaseAnimatedVariable {
public:
CAnimatedVariable() : CBaseAnimatedVariable(typeToeAnimatedVarType<VarType>) {
;
} // dummy var
template <Animable VarType> void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, PHLWINDOW pWindow, eAVarDamagePolicy policy) {
using PHLANIMVAR = SP<CAnimatedVariable<VarType>>; create(pAnimConfig, pWindow, policy);
m_Value = value;
m_Goal = value;
}
void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, PHLLS pLayer, eAVarDamagePolicy policy) {
create(pAnimConfig, pLayer, policy);
m_Value = value;
m_Goal = value;
}
void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, PHLWORKSPACE pWorkspace, eAVarDamagePolicy policy) {
create(pAnimConfig, pWorkspace, policy);
m_Value = value;
m_Goal = value;
}
void create(const VarType& value, SAnimationPropertyConfig* pAnimConfig, eAVarDamagePolicy policy) {
create(pAnimConfig, policy);
m_Value = value;
m_Goal = value;
}
template <Animable VarType> using CBaseAnimatedVariable::create;
using PHLANIMVARREF = WP<CAnimatedVariable<VarType>>;
CAnimatedVariable(const CAnimatedVariable&) = delete;
CAnimatedVariable(CAnimatedVariable&&) = delete;
CAnimatedVariable& operator=(const CAnimatedVariable&) = delete;
CAnimatedVariable& operator=(CAnimatedVariable&&) = delete;
~CAnimatedVariable() = default;
// gets the current vector value (real time)
const VarType& value() const {
return m_Value;
}
// gets the goal vector value
const VarType& goal() const {
return m_Goal;
}
CAnimatedVariable& operator=(const VarType& v) {
if (v == m_Goal)
return *this;
m_Goal = v;
animationBegin = std::chrono::steady_clock::now();
m_Begun = m_Value;
onAnimationBegin();
return *this;
}
// Sets the actual stored value, without affecting the goal, but resets the timer
void setValue(const VarType& v) {
if (v == m_Value)
return;
m_Value = v;
animationBegin = std::chrono::steady_clock::now();
m_Begun = m_Value;
onAnimationBegin();
}
// Sets the actual value and goal
void setValueAndWarp(const VarType& v) {
m_Goal = v;
m_bIsBeingAnimated = true;
warp();
}
void warp(bool endCallback = true) override {
if (!m_bIsBeingAnimated)
return;
m_Value = m_Goal;
m_bIsBeingAnimated = false;
if (m_fUpdateCallback)
m_fUpdateCallback(this);
if (endCallback)
onAnimationEnd();
}
private:
VarType m_Value{};
VarType m_Goal{};
VarType m_Begun{};
// owners
friend class CAnimationManager;
friend class CWorkspace;
friend class CLayerSurface;
friend class CHyprRenderer;
};

View File

@@ -0,0 +1,90 @@
#include "BezierCurve.hpp"
#include "../debug/Log.hpp"
#include "../macros.hpp"
#include <chrono>
#include <algorithm>
void CBezierCurve::setup(std::vector<Vector2D>* pVec) {
const auto BEGIN = std::chrono::high_resolution_clock::now();
// Avoid reallocations by reserving enough memory upfront
m_vPoints.resize(pVec->size() + 2);
m_vPoints[0] = Vector2D(0, 0); // Start point
size_t index = 1; // Start after the first element
for (const auto& vec : *pVec) {
if (index < m_vPoints.size() - 1) { // Bounds check to ensure safety
m_vPoints[index] = vec;
++index;
}
}
m_vPoints.back() = Vector2D(1, 1); // End point
RASSERT(m_vPoints.size() == 4, "CBezierCurve only supports cubic beziers! (points num: {})", m_vPoints.size());
// bake BAKEDPOINTS points for faster lookups
// T -> X ( / BAKEDPOINTS )
for (int i = 0; i < BAKEDPOINTS; ++i) {
float const t = (i + 1) / (float)BAKEDPOINTS;
m_aPointsBaked[i] = Vector2D(getXForT(t), getYForT(t));
}
const auto ELAPSEDUS = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - BEGIN).count() / 1000.f;
const auto POINTSSIZE = m_aPointsBaked.size() * sizeof(m_aPointsBaked[0]) / 1000.f;
const auto BEGINCALC = std::chrono::high_resolution_clock::now();
for (int j = 1; j < 10; ++j) {
float i = j / 10.0f;
getYForPoint(i);
}
const auto ELAPSEDCALCAVG = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - BEGINCALC).count() / 1000.f / 10.f;
Debug::log(LOG, "Created a bezier curve, baked {} points, mem usage: {:.2f}kB, time to bake: {:.2f}µs. Estimated average calc time: {:.2f}µs.", BAKEDPOINTS, POINTSSIZE,
ELAPSEDUS, ELAPSEDCALCAVG);
}
float CBezierCurve::getXForT(float const& t) const {
float t2 = t * t;
float t3 = t2 * t;
return 3 * t * (1 - t) * (1 - t) * m_vPoints[1].x + 3 * t2 * (1 - t) * m_vPoints[2].x + t3 * m_vPoints[3].x;
}
float CBezierCurve::getYForT(float const& t) const {
float t2 = t * t;
float t3 = t2 * t;
return 3 * t * (1 - t) * (1 - t) * m_vPoints[1].y + 3 * t2 * (1 - t) * m_vPoints[2].y + t3 * m_vPoints[3].y;
}
// Todo: this probably can be done better and faster
float CBezierCurve::getYForPoint(float const& x) const {
if (x >= 1.f)
return 1.f;
if (x <= 0.f)
return 0.f;
int index = 0;
bool below = true;
for (int step = (BAKEDPOINTS + 1) / 2; step > 0; step /= 2) {
if (below)
index += step;
else
index -= step;
below = m_aPointsBaked[index].x < x;
}
int lowerIndex = index - (!below || index == BAKEDPOINTS - 1);
// in the name of performance i shall make a hack
const auto LOWERPOINT = &m_aPointsBaked[lowerIndex];
const auto UPPERPOINT = &m_aPointsBaked[lowerIndex + 1];
const auto PERCINDELTA = (x - LOWERPOINT->x) / (UPPERPOINT->x - LOWERPOINT->x);
if (std::isnan(PERCINDELTA) || std::isinf(PERCINDELTA)) // can sometimes happen for VERY small x
return 0.f;
return LOWERPOINT->y + (UPPERPOINT->y - LOWERPOINT->y) * PERCINDELTA;
}

View File

@@ -0,0 +1,28 @@
#pragma once
#include <vector>
#include <array>
#include <vector>
#include "math/Math.hpp"
constexpr int BAKEDPOINTS = 255;
constexpr float INVBAKEDPOINTS = 1.f / BAKEDPOINTS;
// an implementation of a cubic bezier curve
// might do better later
class CBezierCurve {
public:
// sets up the bezier curve.
// this EXCLUDES the 0,0 and 1,1 points,
void setup(std::vector<Vector2D>* points);
float getYForT(float const& t) const;
float getXForT(float const& t) const;
float getYForPoint(float const& x) const;
private:
// this INCLUDES the 0,0 and 1,1 points.
std::vector<Vector2D> m_vPoints;
std::array<Vector2D, BAKEDPOINTS> m_aPointsBaked;
};

View File

@@ -43,7 +43,3 @@ Hyprgraphics::CColor::SHSL CHyprColor::asHSL() const {
CHyprColor CHyprColor::stripA() const { CHyprColor CHyprColor::stripA() const {
return {r, g, b, 1.F}; return {r, g, b, 1.F};
} }
CHyprColor CHyprColor::modifyA(float newa) const {
return {r, g, b, newa};
}

View File

@@ -2,6 +2,7 @@
#include <cstdint> #include <cstdint>
#include <hyprgraphics/color/Color.hpp> #include <hyprgraphics/color/Color.hpp>
#include "../debug/Log.hpp"
#include "../macros.hpp" #include "../macros.hpp"
class CHyprColor { class CHyprColor {
@@ -17,7 +18,6 @@ class CHyprColor {
Hyprgraphics::CColor::SOkLab asOkLab() const; Hyprgraphics::CColor::SOkLab asOkLab() const;
Hyprgraphics::CColor::SHSL asHSL() const; Hyprgraphics::CColor::SHSL asHSL() const;
CHyprColor stripA() const; CHyprColor stripA() const;
CHyprColor modifyA(float newa) const;
// //
bool operator==(const CHyprColor& c2) const { bool operator==(const CHyprColor& c2) const {
@@ -45,18 +45,3 @@ class CHyprColor {
private: private:
Hyprgraphics::CColor::SOkLab okLab; // cache for the OkLab representation Hyprgraphics::CColor::SOkLab okLab; // cache for the OkLab representation
}; };
//NOLINTNEXTLINE
namespace Colors {
static const CHyprColor WHITE = CHyprColor(1.F, 1.F, 1.F, 1.F);
static const CHyprColor GREEN = CHyprColor(0.F, 1.F, 0.F, 1.F);
static const CHyprColor BLUE = CHyprColor(0.F, 0.F, 1.F, 1.F);
static const CHyprColor RED = CHyprColor(1.F, 0.F, 0.F, 1.F);
static const CHyprColor ORANGE = CHyprColor(1.F, 0.5F, 0.F, 1.F);
static const CHyprColor YELLOW = CHyprColor(1.F, 1.F, 0.F, 1.F);
static const CHyprColor MAGENTA = CHyprColor(1.F, 0.F, 1.F, 1.F);
static const CHyprColor PURPLE = CHyprColor(0.5F, 0.F, 0.5F, 1.F);
static const CHyprColor LIME = CHyprColor(0.5F, 1.F, 0.1F, 1.F);
static const CHyprColor LIGHT_BLUE = CHyprColor(0.1F, 1.F, 1.F, 1.F);
static const CHyprColor BLACK = CHyprColor(0.F, 0.F, 0.F, 1.F);
};

View File

@@ -3,9 +3,6 @@
#include <algorithm> #include <algorithm>
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "../managers/TokenManager.hpp" #include "../managers/TokenManager.hpp"
#include "Monitor.hpp"
#include "../config/ConfigManager.hpp"
#include "fs/FsUtils.hpp"
#include <optional> #include <optional>
#include <cstring> #include <cstring>
#include <cmath> #include <cmath>
@@ -164,6 +161,26 @@ std::string absolutePath(const std::string& rawpath, const std::string& currentP
return value; return value;
} }
void addWLSignal(wl_signal* pSignal, wl_listener* pListener, void* pOwner, const std::string& ownerString) {
ASSERT(pSignal);
ASSERT(pListener);
wl_signal_add(pSignal, pListener);
Debug::log(LOG, "Registered signal for owner {:x}: {:x} -> {:x} (owner: {})", (uintptr_t)pOwner, (uintptr_t)pSignal, (uintptr_t)pListener, ownerString);
}
void removeWLSignal(wl_listener* pListener) {
wl_list_remove(&pListener->link);
wl_list_init(&pListener->link);
Debug::log(LOG, "Removed listener {:x}", (uintptr_t)pListener);
}
void handleNoop(struct wl_listener* listener, void* data) {
// Do nothing
}
std::string escapeJSONStrings(const std::string& str) { std::string escapeJSONStrings(const std::string& str) {
std::ostringstream oss; std::ostringstream oss;
for (auto const& c : str) { for (auto const& c : str) {
@@ -261,7 +278,7 @@ SWorkspaceIDName getWorkspaceIDNameFromString(const std::string& in) {
if (!valid(PWORKSPACE)) if (!valid(PWORKSPACE))
return {WORKSPACE_INVALID}; return {WORKSPACE_INVALID};
const auto PLASTWORKSPACE = g_pCompositor->getWorkspaceByID(PWORKSPACE->getPrevWorkspaceIDName().id); const auto PLASTWORKSPACE = g_pCompositor->getWorkspaceByID(PWORKSPACE->m_sPrevWorkspace.id);
if (!PLASTWORKSPACE) if (!PLASTWORKSPACE)
return {WORKSPACE_INVALID}; return {WORKSPACE_INVALID};
@@ -611,7 +628,7 @@ void logSystemInfo() {
} }
} catch (...) { GPUINFO = "error"; } } catch (...) { GPUINFO = "error"; }
#else #else
const std::string GPUINFO = execAndGet("lspci -vnn | grep -E '(VGA|Display|3D)'"); const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA");
#endif #endif
Debug::log(LOG, "GPU information:\n{}\n", GPUINFO); Debug::log(LOG, "GPU information:\n{}\n", GPUINFO);
@@ -622,7 +639,7 @@ void logSystemInfo() {
// log etc // log etc
Debug::log(LOG, "os-release:"); Debug::log(LOG, "os-release:");
Debug::log(NONE, "{}", NFsUtils::readFileAsString("/etc/os-release").value_or("error")); Debug::log(NONE, "{}", execAndGet("cat /etc/os-release"));
} }
int64_t getPPIDof(int64_t pid) { int64_t getPPIDof(int64_t pid) {
@@ -914,3 +931,30 @@ float stringToPercentage(const std::string& VALUE, const float REL) {
else else
return std::stof(VALUE); return std::stof(VALUE);
} }
bool executableExistsInPath(const std::string& exe) {
if (!getenv("PATH"))
return false;
static CVarList paths(getenv("PATH"), 0, ':', true);
for (auto& p : paths) {
std::string path = p + std::string{"/"} + exe;
std::error_code ec;
if (!std::filesystem::exists(path, ec) || ec)
continue;
if (!std::filesystem::is_regular_file(path, ec) || ec)
continue;
auto stat = std::filesystem::status(path, ec);
if (ec)
continue;
auto perms = stat.permissions();
return std::filesystem::perms::none != (perms & std::filesystem::perms::others_exec);
}
return false;
}

View File

@@ -1,7 +1,9 @@
#pragma once #pragma once
#include <optional> #include <optional>
#include <string>
#include <wayland-server.h> #include <wayland-server.h>
#include "math/Math.hpp"
#include <vector> #include <vector>
#include <format> #include <format>
#include <expected> #include <expected>
@@ -19,6 +21,8 @@ struct SWorkspaceIDName {
}; };
std::string absolutePath(const std::string&, const std::string&); std::string absolutePath(const std::string&, const std::string&);
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString);
void removeWLSignal(wl_listener*);
std::string escapeJSONStrings(const std::string& str); std::string escapeJSONStrings(const std::string& str);
bool isDirection(const std::string&); bool isDirection(const std::string&);
bool isDirection(const char&); bool isDirection(const char&);
@@ -38,6 +42,7 @@ bool envEnabled(const std::string& env);
int allocateSHMFile(size_t len); int allocateSHMFile(size_t len);
bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr); bool allocateSHMFilePair(size_t size, int* rw_fd_ptr, int* ro_fd_ptr);
float stringToPercentage(const std::string& VALUE, const float REL); float stringToPercentage(const std::string& VALUE, const float REL);
bool executableExistsInPath(const std::string& exe);
template <typename... Args> template <typename... Args>
[[deprecated("use std::format instead")]] std::string getFormat(std::format_string<Args...> fmt, Args&&... args) { [[deprecated("use std::format instead")]] std::string getFormat(std::format_string<Args...> fmt, Args&&... args) {

View File

@@ -1,6 +1,5 @@
#include "Monitor.hpp" #include "Monitor.hpp"
#include "MiscFunctions.hpp" #include "MiscFunctions.hpp"
#include "../macros.hpp"
#include "math/Math.hpp" #include "math/Math.hpp"
#include "sync/SyncReleaser.hpp" #include "sync/SyncReleaser.hpp"
#include "../Compositor.hpp" #include "../Compositor.hpp"
@@ -17,23 +16,15 @@
#include "../managers/PointerManager.hpp" #include "../managers/PointerManager.hpp"
#include "../managers/eventLoop/EventLoopManager.hpp" #include "../managers/eventLoop/EventLoopManager.hpp"
#include "../protocols/core/Compositor.hpp" #include "../protocols/core/Compositor.hpp"
#include "../render/Renderer.hpp"
#include "../managers/EventManager.hpp"
#include "../managers/LayoutManager.hpp"
#include "../managers/input/InputManager.hpp"
#include "sync/SyncTimeline.hpp" #include "sync/SyncTimeline.hpp"
#include "../desktop/LayerSurface.hpp"
#include <aquamarine/output/Output.hpp> #include <aquamarine/output/Output.hpp>
#include "debug/Log.hpp" #include "debug/Log.hpp"
#include "debug/HyprNotificationOverlay.hpp"
#include <hyprutils/string/String.hpp> #include <hyprutils/string/String.hpp>
#include <hyprutils/utils/ScopeGuard.hpp> #include <hyprutils/utils/ScopeGuard.hpp>
#include <cstring>
#include <ranges>
using namespace Hyprutils::String; using namespace Hyprutils::String;
using namespace Hyprutils::Utils; using namespace Hyprutils::Utils;
static int ratHandler(void* data) { int ratHandler(void* data) {
g_pHyprRenderer->renderMonitor(((CMonitor*)data)->self.lock()); g_pHyprRenderer->renderMonitor(((CMonitor*)data)->self.lock());
return 1; return 1;
@@ -51,8 +42,6 @@ void CMonitor::onConnect(bool noRule) {
EMIT_HOOK_EVENT("preMonitorAdded", self.lock()); EMIT_HOOK_EVENT("preMonitorAdded", self.lock());
CScopeGuard x = {[]() { g_pCompositor->arrangeMonitors(); }}; CScopeGuard x = {[]() { g_pCompositor->arrangeMonitors(); }};
g_pEventLoopManager->doLater([] { g_pConfigManager->ensurePersistentWorkspacesPresent(); });
if (output->supportsExplicit) { if (output->supportsExplicit) {
inTimeline = CSyncTimeline::create(output->getBackend()->drmFD()); inTimeline = CSyncTimeline::create(output->getBackend()->drmFD());
outTimeline = CSyncTimeline::create(output->getBackend()->drmFD()); outTimeline = CSyncTimeline::create(output->getBackend()->drmFD());
@@ -96,7 +85,7 @@ void CMonitor::onConnect(bool noRule) {
return; return;
Debug::log(LOG, "Reapplying monitor rule for {} from a state request", szName); Debug::log(LOG, "Reapplying monitor rule for {} from a state request", szName);
applyMonitorRule(&activeMonitorRule, true); g_pHyprRenderer->applyMonitorRule(self.lock(), &activeMonitorRule, true);
return; return;
} }
@@ -110,7 +99,7 @@ void CMonitor::onConnect(bool noRule) {
SMonitorRule rule = activeMonitorRule; SMonitorRule rule = activeMonitorRule;
rule.resolution = SIZE; rule.resolution = SIZE;
applyMonitorRule(&rule); g_pHyprRenderer->applyMonitorRule(self.lock(), &rule);
}); });
tearingState.canTear = output->getBackend()->type() == Aquamarine::AQ_BACKEND_DRM; tearingState.canTear = output->getBackend()->type() == Aquamarine::AQ_BACKEND_DRM;
@@ -183,7 +172,7 @@ void CMonitor::onConnect(bool noRule) {
// set mode, also applies // set mode, also applies
if (!noRule) if (!noRule)
applyMonitorRule(&monitorRule, true); g_pHyprRenderer->applyMonitorRule(self.lock(), &monitorRule, true);
if (!state.commit()) if (!state.commit())
Debug::log(WARN, "state.commit() failed in CMonitor::onCommit"); Debug::log(WARN, "state.commit() failed in CMonitor::onCommit");
@@ -372,392 +361,6 @@ void CMonitor::onDisconnect(bool destroy) {
std::erase_if(g_pCompositor->m_vMonitors, [&](PHLMONITOR& el) { return el.get() == this; }); std::erase_if(g_pCompositor->m_vMonitors, [&](PHLMONITOR& el) { return el.get() == this; });
} }
bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) {
static auto PDISABLESCALECHECKS = CConfigValue<Hyprlang::INT>("debug:disable_scale_checks");
Debug::log(LOG, "Applying monitor rule for {}", szName);
activeMonitorRule = *pMonitorRule;
if (forceSize.has_value())
activeMonitorRule.resolution = forceSize.value();
const auto RULE = &activeMonitorRule;
// if it's disabled, disable and ignore
if (RULE->disabled) {
if (m_bEnabled)
onDisconnect();
events.modeChanged.emit();
return true;
}
// don't touch VR headsets
if (output->nonDesktop)
return true;
if (!m_bEnabled) {
onConnect(true); // enable it.
Debug::log(LOG, "Monitor {} is disabled but is requested to be enabled", szName);
force = true;
}
// Check if the rule isn't already applied
// TODO: clean this up lol
if (!force && DELTALESSTHAN(vecPixelSize.x, RULE->resolution.x, 1) && DELTALESSTHAN(vecPixelSize.y, RULE->resolution.y, 1) &&
DELTALESSTHAN(refreshRate, RULE->refreshRate, 1) && setScale == RULE->scale &&
((DELTALESSTHAN(vecPosition.x, RULE->offset.x, 1) && DELTALESSTHAN(vecPosition.y, RULE->offset.y, 1)) || RULE->offset == Vector2D(-INT32_MAX, -INT32_MAX)) &&
transform == RULE->transform && RULE->enable10bit == enabled10bit && !std::memcmp(&customDrmMode, &RULE->drmMode, sizeof(customDrmMode))) {
Debug::log(LOG, "Not applying a new rule to {} because it's already applied!", szName);
setMirror(RULE->mirrorOf);
return true;
}
bool autoScale = false;
if (RULE->scale > 0.1) {
scale = RULE->scale;
} else {
autoScale = true;
const auto DEFAULTSCALE = getDefaultScale();
scale = DEFAULTSCALE;
}
setScale = scale;
transform = RULE->transform;
// accumulate requested modes in reverse order (cause inesrting at front is inefficient)
std::vector<SP<Aquamarine::SOutputMode>> requestedModes;
std::string requestedStr = "preferred";
// use sortFunc, add best 3 to requestedModes in reverse, since we test in reverse
auto addBest3Modes = [&](auto const& sortFunc) {
auto sortedModes = output->modes;
std::ranges::sort(sortedModes, sortFunc);
if (sortedModes.size() > 3)
sortedModes.erase(sortedModes.begin() + 3, sortedModes.end());
requestedModes.insert(requestedModes.end(), sortedModes.rbegin(), sortedModes.rend());
};
// last fallback is preferred mode, btw this covers resolution == Vector2D()
if (!output->preferredMode())
Debug::log(ERR, "Monitor {} has NO PREFERRED MODE", output->name);
else
requestedModes.push_back(output->preferredMode());
if (RULE->resolution == Vector2D(-1, -1)) {
requestedStr = "highrr";
// sort prioritizing refresh rate 1st and resolution 2nd, then add best 3
addBest3Modes([](auto const& a, auto const& b) {
if (std::round(a->refreshRate) > std::round(b->refreshRate))
return true;
else if (DELTALESSTHAN((float)a->refreshRate, (float)b->refreshRate, 1.F) && a->pixelSize.x > b->pixelSize.x && a->pixelSize.y > b->pixelSize.y)
return true;
return false;
});
} else if (RULE->resolution == Vector2D(-1, -2)) {
requestedStr = "highres";
// sort prioritizing resultion 1st and refresh rate 2nd, then add best 3
addBest3Modes([](auto const& a, auto const& b) {
if (a->pixelSize.x > b->pixelSize.x && a->pixelSize.y > b->pixelSize.y)
return true;
else if (DELTALESSTHAN(a->pixelSize.x, b->pixelSize.x, 1) && DELTALESSTHAN(a->pixelSize.y, b->pixelSize.y, 1) &&
std::round(a->refreshRate) > std::round(b->refreshRate))
return true;
return false;
});
} else if (RULE->resolution != Vector2D()) {
// user requested mode
requestedStr = std::format("{:X0}@{:.2f}Hz", RULE->resolution, RULE->refreshRate);
// sort by closeness to requested, then add best 3
addBest3Modes([&](auto const& a, auto const& b) {
if (abs(a->pixelSize.x - RULE->resolution.x) < abs(b->pixelSize.x - RULE->resolution.x))
return true;
if (a->pixelSize.x == b->pixelSize.x && abs(a->pixelSize.y - RULE->resolution.y) < abs(b->pixelSize.y - RULE->resolution.y))
return true;
if (a->pixelSize == b->pixelSize && abs((a->refreshRate / 1000.f) - RULE->refreshRate) < abs((b->refreshRate / 1000.f) - RULE->refreshRate))
return true;
return false;
});
// if the best mode isnt close to requested, then try requested as custom mode first
if (!requestedModes.empty()) {
auto bestMode = requestedModes.back();
if (!DELTALESSTHAN(bestMode->pixelSize.x, RULE->resolution.x, 1) || !DELTALESSTHAN(bestMode->pixelSize.y, RULE->resolution.y, 1) ||
!DELTALESSTHAN(bestMode->refreshRate / 1000.f, RULE->refreshRate, 1))
requestedModes.push_back(makeShared<Aquamarine::SOutputMode>(Aquamarine::SOutputMode{.pixelSize = RULE->resolution, .refreshRate = RULE->refreshRate * 1000.f}));
}
// then if requested is custom, try custom mode first
if (RULE->drmMode.type == DRM_MODE_TYPE_USERDEF) {
if (output->getBackend()->type() != Aquamarine::eBackendType::AQ_BACKEND_DRM)
Debug::log(ERR, "Tried to set custom modeline on non-DRM output");
else
requestedModes.push_back(makeShared<Aquamarine::SOutputMode>(
Aquamarine::SOutputMode{.pixelSize = {RULE->drmMode.hdisplay, RULE->drmMode.vdisplay}, .refreshRate = RULE->drmMode.vrefresh, .modeInfo = RULE->drmMode}));
}
}
const auto WAS10B = enabled10bit;
const auto OLDRES = vecPixelSize;
bool success = false;
// Needed in case we are switching from a custom modeline to a standard mode
customDrmMode = {};
currentMode = nullptr;
output->state->setFormat(DRM_FORMAT_XRGB8888);
prevDrmFormat = drmFormat;
drmFormat = DRM_FORMAT_XRGB8888;
output->state->resetExplicitFences();
if (Debug::trace) {
Debug::log(TRACE, "Monitor {} requested modes:", szName);
if (requestedModes.empty())
Debug::log(TRACE, "| None");
else {
for (auto const& mode : requestedModes | std::views::reverse) {
Debug::log(TRACE, "| {:X0}@{:.2f}Hz", mode->pixelSize, mode->refreshRate / 1000.f);
}
}
}
for (auto const& mode : requestedModes | std::views::reverse) {
std::string modeStr = std::format("{:X0}@{:.2f}Hz", mode->pixelSize, mode->refreshRate / 1000.f);
if (mode->modeInfo.has_value() && mode->modeInfo->type == DRM_MODE_TYPE_USERDEF) {
output->state->setCustomMode(mode);
if (!state.test()) {
Debug::log(ERR, "Monitor {}: REJECTED custom mode {}!", szName, modeStr);
continue;
}
customDrmMode = mode->modeInfo.value();
} else {
output->state->setMode(mode);
if (!state.test()) {
Debug::log(ERR, "Monitor {}: REJECTED available mode {}!", szName, modeStr);
if (mode->preferred)
Debug::log(ERR, "Monitor {}: REJECTED preferred mode!!!", szName);
continue;
}
customDrmMode = {};
}
refreshRate = mode->refreshRate / 1000.f;
vecSize = mode->pixelSize;
currentMode = mode;
success = true;
if (mode->preferred)
Debug::log(LOG, "Monitor {}: requested {}, using preferred mode {}", szName, requestedStr, modeStr);
else if (mode->modeInfo.has_value() && mode->modeInfo->type == DRM_MODE_TYPE_USERDEF)
Debug::log(LOG, "Monitor {}: requested {}, using custom mode {}", szName, requestedStr, modeStr);
else
Debug::log(LOG, "Monitor {}: requested {}, using available mode {}", szName, requestedStr, modeStr);
break;
}
// try requested as custom mode jic it works
if (!success && RULE->resolution != Vector2D() && RULE->resolution != Vector2D(-1, -1) && RULE->resolution != Vector2D(-1, -2)) {
auto refreshRate = output->getBackend()->type() == Aquamarine::eBackendType::AQ_BACKEND_DRM ? RULE->refreshRate * 1000 : 0;
auto mode = makeShared<Aquamarine::SOutputMode>(Aquamarine::SOutputMode{.pixelSize = RULE->resolution, .refreshRate = refreshRate});
std::string modeStr = std::format("{:X0}@{:.2f}Hz", mode->pixelSize, mode->refreshRate / 1000.f);
output->state->setCustomMode(mode);
if (state.test()) {
Debug::log(LOG, "Monitor {}: requested {}, using custom mode {}", szName, requestedStr, modeStr);
refreshRate = mode->refreshRate / 1000.f;
vecSize = mode->pixelSize;
currentMode = mode;
customDrmMode = {};
success = true;
} else
Debug::log(ERR, "Monitor {}: REJECTED custom mode {}!", szName, modeStr);
}
// try any of the modes if none of the above work
if (!success) {
for (auto const& mode : output->modes) {
output->state->setMode(mode);
if (!state.test())
continue;
auto errorMessage =
std::format("Monitor {} failed to set any requested modes, falling back to mode {:X0}@{:.2f}Hz", szName, mode->pixelSize, mode->refreshRate / 1000.f);
Debug::log(WARN, errorMessage);
g_pHyprNotificationOverlay->addNotification(errorMessage, CHyprColor(0xff0000ff), 5000, ICON_WARNING);
refreshRate = mode->refreshRate / 1000.f;
vecSize = mode->pixelSize;
currentMode = mode;
customDrmMode = {};
success = true;
break;
}
}
if (!success) {
Debug::log(ERR, "Monitor {} has NO FALLBACK MODES, and an INVALID one was requested: {:X0}@{:.2f}Hz", szName, RULE->resolution, RULE->refreshRate);
return true;
}
vrrActive = output->state->state().adaptiveSync // disabled here, will be tested in CConfigManager::ensureVRR()
|| createdByUser; // wayland backend doesn't allow for disabling adaptive_sync
vecPixelSize = vecSize;
// clang-format off
static const std::array<std::vector<std::pair<std::string, uint32_t>>, 2> formats{
std::vector<std::pair<std::string, uint32_t>>{ /* 10-bit */
{"DRM_FORMAT_XRGB2101010", DRM_FORMAT_XRGB2101010}, {"DRM_FORMAT_XBGR2101010", DRM_FORMAT_XBGR2101010}, {"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}
},
std::vector<std::pair<std::string, uint32_t>>{ /* 8-bit */
{"DRM_FORMAT_XRGB8888", DRM_FORMAT_XRGB8888}, {"DRM_FORMAT_XBGR8888", DRM_FORMAT_XBGR8888}
}
};
// clang-format on
bool set10bit = false;
for (auto const& fmt : formats[(int)!RULE->enable10bit]) {
output->state->setFormat(fmt.second);
prevDrmFormat = drmFormat;
drmFormat = fmt.second;
if (!state.test()) {
Debug::log(ERR, "output {} failed basic test on format {}", szName, fmt.first);
} else {
Debug::log(LOG, "output {} succeeded basic test on format {}", szName, fmt.first);
if (RULE->enable10bit && fmt.first.contains("101010"))
set10bit = true;
break;
}
}
enabled10bit = set10bit;
Vector2D logicalSize = vecPixelSize / scale;
if (!*PDISABLESCALECHECKS && (logicalSize.x != std::round(logicalSize.x) || logicalSize.y != std::round(logicalSize.y))) {
// invalid scale, will produce fractional pixels.
// find the nearest valid.
float searchScale = std::round(scale * 120.0);
bool found = false;
double scaleZero = searchScale / 120.0;
Vector2D logicalZero = vecPixelSize / scaleZero;
if (logicalZero == logicalZero.round())
scale = scaleZero;
else {
for (size_t i = 1; i < 90; ++i) {
double scaleUp = (searchScale + i) / 120.0;
double scaleDown = (searchScale - i) / 120.0;
Vector2D logicalUp = vecPixelSize / scaleUp;
Vector2D logicalDown = vecPixelSize / scaleDown;
if (logicalUp == logicalUp.round()) {
found = true;
searchScale = scaleUp;
break;
}
if (logicalDown == logicalDown.round()) {
found = true;
searchScale = scaleDown;
break;
}
}
if (!found) {
if (autoScale)
scale = std::round(scaleZero);
else {
Debug::log(ERR, "Invalid scale passed to monitor, {} failed to find a clean divisor", scale);
g_pConfigManager->addParseError("Invalid scale passed to monitor " + szName + ", failed to find a clean divisor");
scale = getDefaultScale();
}
} else {
if (!autoScale) {
Debug::log(ERR, "Invalid scale passed to monitor, {} found suggestion {}", scale, searchScale);
g_pConfigManager->addParseError(
std::format("Invalid scale passed to monitor {}, failed to find a clean divisor. Suggested nearest scale: {:5f}", szName, searchScale));
scale = getDefaultScale();
} else
scale = searchScale;
}
}
}
output->scheduleFrame();
if (!state.commit())
Debug::log(ERR, "Couldn't commit output named {}", output->name);
Vector2D xfmd = transform % 2 == 1 ? Vector2D{vecPixelSize.y, vecPixelSize.x} : vecPixelSize;
vecSize = (xfmd / scale).round();
vecTransformedSize = xfmd;
if (createdByUser) {
CBox transformedBox = {0, 0, vecTransformedSize.x, vecTransformedSize.y};
transformedBox.transform(wlTransformToHyprutils(invertTransform(transform)), vecTransformedSize.x, vecTransformedSize.y);
vecPixelSize = Vector2D(transformedBox.width, transformedBox.height);
}
updateMatrix();
if (WAS10B != enabled10bit || OLDRES != vecPixelSize)
g_pHyprOpenGL->destroyMonitorResources(self.lock());
g_pCompositor->arrangeMonitors();
damage.setSize(vecTransformedSize);
// Set scale for all surfaces on this monitor, needed for some clients
// but not on unsafe state to avoid crashes
if (!g_pCompositor->m_bUnsafeState) {
for (auto const& w : g_pCompositor->m_vWindows) {
w->updateSurfaceScaleTransformDetails();
}
}
// updato us
g_pHyprRenderer->arrangeLayersForMonitor(ID);
// reload to fix mirrors
g_pConfigManager->m_bWantsMonitorReload = true;
Debug::log(LOG, "Monitor {} data dump: res {:X}@{:.2f}Hz, scale {:.2f}, transform {}, pos {:X}, 10b {}", szName, vecPixelSize, refreshRate, scale, (int)transform, vecPosition,
(int)enabled10bit);
EMIT_HOOK_EVENT("monitorLayoutChanged", nullptr);
events.modeChanged.emit();
return true;
}
void CMonitor::addDamage(const pixman_region32_t* rg) { void CMonitor::addDamage(const pixman_region32_t* rg) {
static auto PZOOMFACTOR = CConfigValue<Hyprlang::FLOAT>("cursor:zoom_factor"); static auto PZOOMFACTOR = CConfigValue<Hyprlang::FLOAT>("cursor:zoom_factor");
if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == self) { if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == self) {
@@ -767,18 +370,18 @@ void CMonitor::addDamage(const pixman_region32_t* rg) {
g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE);
} }
void CMonitor::addDamage(const CRegion& rg) { void CMonitor::addDamage(const CRegion* rg) {
addDamage(const_cast<CRegion*>(&rg)->pixman()); addDamage(const_cast<CRegion*>(rg)->pixman());
} }
void CMonitor::addDamage(const CBox& box) { void CMonitor::addDamage(const CBox* box) {
static auto PZOOMFACTOR = CConfigValue<Hyprlang::FLOAT>("cursor:zoom_factor"); static auto PZOOMFACTOR = CConfigValue<Hyprlang::FLOAT>("cursor:zoom_factor");
if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == self) { if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == self) {
damage.damageEntire(); damage.damageEntire();
g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE);
} }
if (damage.damage(box)) if (damage.damage(*box))
g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE); g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_DAMAGE);
} }
@@ -809,7 +412,7 @@ bool CMonitor::matchesStaticSelector(const std::string& selector) const {
// match by description // match by description
const auto DESCRIPTIONSELECTOR = selector.substr(5); const auto DESCRIPTIONSELECTOR = selector.substr(5);
return szDescription.starts_with(DESCRIPTIONSELECTOR) || szShortDescription.starts_with(DESCRIPTIONSELECTOR); return DESCRIPTIONSELECTOR == szShortDescription || DESCRIPTIONSELECTOR == szDescription;
} else { } else {
// match by selector // match by selector
return szName == selector; return szName == selector;
@@ -927,7 +530,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
setupDefaultWS(RULE); setupDefaultWS(RULE);
applyMonitorRule((SMonitorRule*)&RULE, true); // will apply the offset and stuff g_pHyprRenderer->applyMonitorRule(self.lock(), (SMonitorRule*)&RULE, true); // will apply the offset and stuff
} else { } else {
PHLMONITOR BACKUPMON = nullptr; PHLMONITOR BACKUPMON = nullptr;
for (auto const& m : g_pCompositor->m_vMonitors) { for (auto const& m : g_pCompositor->m_vMonitors) {
@@ -1137,16 +740,16 @@ void CMonitor::setSpecialWorkspace(const PHLWORKSPACE& pWorkspace) {
if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && !w->isX11OverrideRedirect()) { if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && !w->isX11OverrideRedirect()) {
// if it's floating and the middle isnt on the current mon, move it to the center // if it's floating and the middle isnt on the current mon, move it to the center
const auto PMONFROMMIDDLE = g_pCompositor->getMonitorFromVector(MIDDLE); const auto PMONFROMMIDDLE = g_pCompositor->getMonitorFromVector(MIDDLE);
Vector2D pos = w->m_vRealPosition->goal(); Vector2D pos = w->m_vRealPosition.goal();
if (!VECINRECT(MIDDLE, PMONFROMMIDDLE->vecPosition.x, PMONFROMMIDDLE->vecPosition.y, PMONFROMMIDDLE->vecPosition.x + PMONFROMMIDDLE->vecSize.x, if (!VECINRECT(MIDDLE, PMONFROMMIDDLE->vecPosition.x, PMONFROMMIDDLE->vecPosition.y, PMONFROMMIDDLE->vecPosition.x + PMONFROMMIDDLE->vecSize.x,
PMONFROMMIDDLE->vecPosition.y + PMONFROMMIDDLE->vecSize.y)) { PMONFROMMIDDLE->vecPosition.y + PMONFROMMIDDLE->vecSize.y)) {
// not on any monitor, center // not on any monitor, center
pos = middle() / 2.f - w->m_vRealSize->goal() / 2.f; pos = middle() / 2.f - w->m_vRealSize.goal() / 2.f;
} else } else
pos = pos - PMONFROMMIDDLE->vecPosition + vecPosition; pos = pos - PMONFROMMIDDLE->vecPosition + vecPosition;
*w->m_vRealPosition = pos; w->m_vRealPosition = pos;
w->m_vPosition = pos; w->m_vPosition = pos;
} }
} }
} }
@@ -1179,29 +782,6 @@ void CMonitor::moveTo(const Vector2D& pos) {
vecPosition = pos; vecPosition = pos;
} }
SWorkspaceIDName CMonitor::getPrevWorkspaceIDName(const WORKSPACEID id) {
while (!prevWorkSpaces.empty()) {
const int PREVID = prevWorkSpaces.top();
prevWorkSpaces.pop();
if (PREVID == id) // skip same workspace
continue;
// recheck if previous workspace's was moved to another monitor
const auto ws = g_pCompositor->getWorkspaceByID(PREVID);
if (ws && ws->monitorID() == ID)
return {.id = PREVID, .name = ws->m_szName};
}
return {.id = WORKSPACE_INVALID};
}
void CMonitor::addPrevWorkspaceID(const WORKSPACEID id) {
if (!prevWorkSpaces.empty() && prevWorkSpaces.top() == id)
return;
prevWorkSpaces.emplace(id);
}
Vector2D CMonitor::middle() { Vector2D CMonitor::middle() {
return vecPosition + vecSize / 2.f; return vecPosition + vecSize / 2.f;
} }

View File

@@ -1,14 +1,11 @@
#pragma once #pragma once
#include "../defines.hpp" #include "../defines.hpp"
#include <stack>
#include <vector> #include <vector>
#include "../SharedDefs.hpp"
#include "MiscFunctions.hpp"
#include "WLClasses.hpp" #include "WLClasses.hpp"
#include <vector> #include <vector>
#include <array> #include <array>
#include <memory>
#include <xf86drmMode.h> #include <xf86drmMode.h>
#include "Timer.hpp" #include "Timer.hpp"
#include "math/Math.hpp" #include "math/Math.hpp"
@@ -33,7 +30,7 @@ struct SMonitorRule {
Vector2D resolution = Vector2D(1280, 720); Vector2D resolution = Vector2D(1280, 720);
Vector2D offset = Vector2D(0, 0); Vector2D offset = Vector2D(0, 0);
float scale = 1; float scale = 1;
float refreshRate = 60; // Hz float refreshRate = 60;
bool disabled = false; bool disabled = false;
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
std::string mirrorOf = ""; std::string mirrorOf = "";
@@ -92,8 +89,10 @@ class CMonitor {
CDamageRing damage; CDamageRing damage;
SP<Aquamarine::IOutput> output; SP<Aquamarine::IOutput> output;
float refreshRate = 60; // Hz float refreshRate = 60;
int framesToSkip = 0;
int forceFullFrames = 0; int forceFullFrames = 0;
bool noFrameSchedule = false;
bool scheduledRecalc = false; bool scheduledRecalc = false;
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
float xwaylandScale = 1.f; float xwaylandScale = 1.f;
@@ -164,10 +163,9 @@ class CMonitor {
// methods // methods
void onConnect(bool noRule); void onConnect(bool noRule);
void onDisconnect(bool destroy = false); void onDisconnect(bool destroy = false);
bool applyMonitorRule(SMonitorRule* pMonitorRule, bool force = false);
void addDamage(const pixman_region32_t* rg); void addDamage(const pixman_region32_t* rg);
void addDamage(const CRegion& rg); void addDamage(const CRegion* rg);
void addDamage(const CBox& box); void addDamage(const CBox* box);
bool shouldSkipScheduleFrameOnMouseEvent(); bool shouldSkipScheduleFrameOnMouseEvent();
void setMirror(const std::string&); void setMirror(const std::string&);
bool isMirror(); bool isMirror();
@@ -192,7 +190,6 @@ class CMonitor {
bool m_bEnabled = false; bool m_bEnabled = false;
bool m_bRenderingInitPassed = false; bool m_bRenderingInitPassed = false;
WP<CWindow> m_previousFSWindow;
// For the list lookup // For the list lookup
@@ -200,16 +197,11 @@ class CMonitor {
return vecPosition == rhs.vecPosition && vecSize == rhs.vecSize && szName == rhs.szName; return vecPosition == rhs.vecPosition && vecSize == rhs.vecSize && szName == rhs.szName;
} }
// workspace previous per monitor functionality
SWorkspaceIDName getPrevWorkspaceIDName(const WORKSPACEID id);
void addPrevWorkspaceID(const WORKSPACEID id);
private: private:
void setupDefaultWS(const SMonitorRule&); void setupDefaultWS(const SMonitorRule&);
WORKSPACEID findAvailableDefaultWS(); WORKSPACEID findAvailableDefaultWS();
bool doneScheduled = false; bool doneScheduled = false;
std::stack<WORKSPACEID> prevWorkSpaces;
struct { struct {
CHyprSignalListener frame; CHyprSignalListener frame;

View File

@@ -1,7 +1,7 @@
#include "SdDaemon.hpp" #include "SdDaemon.hpp"
#include "memory/Memory.hpp"
#include <memory> #include <memory>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <cerrno> #include <cerrno>

View File

@@ -1,13 +1,14 @@
#pragma once #pragma once
#include "../events/Events.hpp"
#include "../defines.hpp" #include "../defines.hpp"
#include "../desktop/Window.hpp"
#include "../desktop/Subsurface.hpp" #include "../desktop/Subsurface.hpp"
#include "../desktop/Popup.hpp" #include "../desktop/Popup.hpp"
#include "AnimatedVariable.hpp"
#include "../desktop/WLSurface.hpp" #include "../desktop/WLSurface.hpp"
#include "../macros.hpp"
#include "../desktop/DesktopTypes.hpp"
#include "memory/Memory.hpp"
#include "signal/Signal.hpp" #include "signal/Signal.hpp"
#include "math/Math.hpp"
class CMonitor; class CMonitor;
class IPointer; class IPointer;
@@ -16,6 +17,47 @@ class CWLSurfaceResource;
AQUAMARINE_FORWARD(ISwitch); AQUAMARINE_FORWARD(ISwitch);
struct SRenderData {
PHLMONITORREF pMonitor;
timespec* when;
double x, y;
// for iters
void* data = nullptr;
SP<CWLSurfaceResource> surface = nullptr;
double w, h;
// for rounding
bool dontRound = true;
// for fade
float fadeAlpha = 1.f;
// for alpha settings
float alpha = 1.f;
// for decorations (border)
bool decorate = false;
// for custom round values
int rounding = -1; // -1 means not set
// for blurring
bool blur = false;
bool blockBlurOptimization = false;
// only for windows, not popups
bool squishOversized = true;
// for calculating UV
PHLWINDOW pWindow;
bool popup = false;
// counts how many surfaces this pass has rendered
int surfaceCounter = 0;
};
struct SSwipeGesture { struct SSwipeGesture {
PHLWORKSPACE pWorkspaceBegin = nullptr; PHLWORKSPACE pWorkspaceBegin = nullptr;

View File

@@ -14,7 +14,7 @@ CWatchdog::~CWatchdog() {
CWatchdog::CWatchdog() : m_iMainThreadPID(pthread_self()) { CWatchdog::CWatchdog() : m_iMainThreadPID(pthread_self()) {
m_pWatchdog = makeUnique<std::thread>([this] { m_pWatchdog = std::make_unique<std::thread>([this] {
static auto PTIMEOUT = CConfigValue<Hyprlang::INT>("debug:watchdog_timeout"); static auto PTIMEOUT = CConfigValue<Hyprlang::INT>("debug:watchdog_timeout");
m_bWatchdogInitialized = true; m_bWatchdogInitialized = true;

View File

@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "memory/Memory.hpp" #include <memory>
#include <chrono> #include <chrono>
#include <thread> #include <thread>
#include <condition_variable> #include <condition_variable>
@@ -24,11 +24,11 @@ class CWatchdog {
std::atomic<bool> m_bWatching = false; std::atomic<bool> m_bWatching = false;
std::atomic<bool> m_bWillWatch = false; std::atomic<bool> m_bWillWatch = false;
UP<std::thread> m_pWatchdog; std::unique_ptr<std::thread> m_pWatchdog;
std::mutex m_mWatchdogMutex; std::mutex m_mWatchdogMutex;
std::atomic<bool> m_bNotified = false; std::atomic<bool> m_bNotified = false;
std::atomic<bool> m_bExitThread = false; std::atomic<bool> m_bExitThread = false;
std::condition_variable m_cvWatchdogCondition; std::condition_variable m_cvWatchdogCondition;
}; };
inline UP<CWatchdog> g_pWatchdog; inline std::unique_ptr<CWatchdog> g_pWatchdog;

View File

@@ -1,107 +0,0 @@
#include "FsUtils.hpp"
#include "../../debug/Log.hpp"
#include <cstdlib>
#include <filesystem>
#include <hyprutils/string/String.hpp>
#include <hyprutils/string/VarList.hpp>
using namespace Hyprutils::String;
std::optional<std::string> NFsUtils::getDataHome() {
const auto DATA_HOME = getenv("XDG_DATA_HOME");
std::string dataRoot;
if (!DATA_HOME) {
const auto HOME = getenv("HOME");
if (!HOME) {
Debug::log(ERR, "FsUtils::getDataHome: can't get data home: no $HOME or $XDG_DATA_HOME");
return std::nullopt;
}
dataRoot = HOME + std::string{"/.local/share/"};
} else
dataRoot = DATA_HOME + std::string{"/"};
std::error_code ec;
if (!std::filesystem::exists(dataRoot, ec) || ec) {
Debug::log(ERR, "FsUtils::getDataHome: can't get data home: inaccessible / missing");
return std::nullopt;
}
dataRoot += "hyprland/";
if (!std::filesystem::exists(dataRoot, ec) || ec) {
Debug::log(LOG, "FsUtils::getDataHome: no hyprland data home, creating.");
std::filesystem::create_directory(dataRoot, ec);
if (ec) {
Debug::log(ERR, "FsUtils::getDataHome: can't create new data home for hyprland");
return std::nullopt;
}
std::filesystem::permissions(dataRoot, std::filesystem::perms::owner_read | std::filesystem::perms::owner_write | std::filesystem::perms::owner_exec, ec);
if (ec)
Debug::log(WARN, "FsUtils::getDataHome: couldn't set perms on hyprland data store. Proceeding anyways.");
}
if (!std::filesystem::exists(dataRoot, ec) || ec) {
Debug::log(ERR, "FsUtils::getDataHome: no hyprland data home, failed to create.");
return std::nullopt;
}
return dataRoot;
}
std::optional<std::string> NFsUtils::readFileAsString(const std::string& path) {
std::error_code ec;
if (!std::filesystem::exists(path, ec) || ec)
return std::nullopt;
std::ifstream file(path);
if (!file.good())
return std::nullopt;
return trim(std::string((std::istreambuf_iterator<char>(file)), (std::istreambuf_iterator<char>())));
}
bool NFsUtils::writeToFile(const std::string& path, const std::string& content) {
std::ofstream of(path, std::ios::trunc);
if (!of.good()) {
Debug::log(ERR, "CVersionKeeperManager: couldn't open an ofstream for writing the version file.");
return false;
}
of << content;
of.close();
return true;
}
bool NFsUtils::executableExistsInPath(const std::string& exe) {
if (!getenv("PATH"))
return false;
static CVarList paths(getenv("PATH"), 0, ':', true);
for (auto& p : paths) {
std::string path = p + std::string{"/"} + exe;
std::error_code ec;
if (!std::filesystem::exists(path, ec) || ec)
continue;
if (!std::filesystem::is_regular_file(path, ec) || ec)
continue;
auto stat = std::filesystem::status(path, ec);
if (ec)
continue;
auto perms = stat.permissions();
return std::filesystem::perms::none != (perms & std::filesystem::perms::others_exec);
}
return false;
}

View File

@@ -1,15 +0,0 @@
#pragma once
#include <optional>
#include <string>
namespace NFsUtils {
// Returns the path to the hyprland directory in data home.
std::optional<std::string> getDataHome();
std::optional<std::string> readFileAsString(const std::string& path);
// overwrites the file if exists
bool writeToFile(const std::string& path, const std::string& content);
bool executableExistsInPath(const std::string& exe);
};

View File

@@ -7,4 +7,4 @@ using namespace Hyprutils::Memory;
#define SP Hyprutils::Memory::CSharedPointer #define SP Hyprutils::Memory::CSharedPointer
#define WP Hyprutils::Memory::CWeakPointer #define WP Hyprutils::Memory::CWeakPointer
#define UP Hyprutils::Memory::CUniquePointer #define UP std::unique_ptr

View File

@@ -2,16 +2,13 @@
#include "HyprError.hpp" #include "HyprError.hpp"
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "../config/ConfigValue.hpp" #include "../config/ConfigValue.hpp"
#include "../render/pass/TexPassElement.hpp"
#include "../managers/AnimationManager.hpp"
#include "../render/Renderer.hpp"
#include "../managers/HookSystemManager.hpp"
#include <hyprutils/utils/ScopeGuard.hpp> #include <hyprutils/utils/ScopeGuard.hpp>
using namespace Hyprutils::Animation; using namespace Hyprutils::Utils;
CHyprError::CHyprError() { CHyprError::CHyprError() {
g_pAnimationManager->createAnimation(0.f, m_fFadeOpacity, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), AVARDAMAGE_NONE); m_fFadeOpacity.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), AVARDAMAGE_NONE);
m_fFadeOpacity.registerVar();
static auto P = g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) { static auto P = g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) {
if (!m_bIsCreated) if (!m_bIsCreated)
@@ -25,14 +22,16 @@ CHyprError::CHyprError() {
if (!m_bIsCreated) if (!m_bIsCreated)
return; return;
if (m_fFadeOpacity->isBeingAnimated() || m_bMonitorChanged) if (m_fFadeOpacity.isBeingAnimated() || m_bMonitorChanged)
g_pHyprRenderer->damageBox(m_bDamageBox); g_pHyprRenderer->damageBox(&m_bDamageBox);
}); });
m_pTexture = makeShared<CTexture>(); m_pTexture = makeShared<CTexture>();
} }
CHyprError::~CHyprError() = default; CHyprError::~CHyprError() {
m_fFadeOpacity.unregister();
}
void CHyprError::queueCreate(std::string message, const CHyprColor& color) { void CHyprError::queueCreate(std::string message, const CHyprColor& color) {
m_szQueued = message; m_szQueued = message;
@@ -43,10 +42,10 @@ void CHyprError::createQueued() {
if (m_bIsCreated) if (m_bIsCreated)
m_pTexture->destroyTexture(); m_pTexture->destroyTexture();
m_fFadeOpacity->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn")); m_fFadeOpacity.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn"));
m_fFadeOpacity->setValueAndWarp(0.f); m_fFadeOpacity.setValueAndWarp(0.f);
*m_fFadeOpacity = 1.f; m_fFadeOpacity = 1.f;
const auto PMONITOR = g_pCompositor->m_vMonitors.front(); const auto PMONITOR = g_pCompositor->m_vMonitors.front();
@@ -176,8 +175,8 @@ void CHyprError::draw() {
} }
if (m_bQueuedDestroy) { if (m_bQueuedDestroy) {
if (!m_fFadeOpacity->isBeingAnimated()) { if (!m_fFadeOpacity.isBeingAnimated()) {
if (m_fFadeOpacity->value() == 0.f) { if (m_fFadeOpacity.value() == 0.f) {
m_bQueuedDestroy = false; m_bQueuedDestroy = false;
m_pTexture->destroyTexture(); m_pTexture->destroyTexture();
m_bIsCreated = false; m_bIsCreated = false;
@@ -189,8 +188,8 @@ void CHyprError::draw() {
return; return;
} else { } else {
m_fFadeOpacity->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut")); m_fFadeOpacity.setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut"));
*m_fFadeOpacity = 0.f; m_fFadeOpacity = 0.f;
} }
} }
} }
@@ -202,17 +201,12 @@ void CHyprError::draw() {
m_bDamageBox.x = (int)PMONITOR->vecPosition.x; m_bDamageBox.x = (int)PMONITOR->vecPosition.x;
m_bDamageBox.y = (int)PMONITOR->vecPosition.y; m_bDamageBox.y = (int)PMONITOR->vecPosition.y;
if (m_fFadeOpacity->isBeingAnimated() || m_bMonitorChanged) if (m_fFadeOpacity.isBeingAnimated() || m_bMonitorChanged)
g_pHyprRenderer->damageBox(m_bDamageBox); g_pHyprRenderer->damageBox(&m_bDamageBox);
m_bMonitorChanged = false; m_bMonitorChanged = false;
CTexPassElement::SRenderData data; g_pHyprOpenGL->renderTexture(m_pTexture, &monbox, m_fFadeOpacity.value(), 0);
data.tex = m_pTexture;
data.box = monbox;
data.a = m_fFadeOpacity->value();
g_pHyprRenderer->m_sRenderPass.add(makeShared<CTexPassElement>(data));
} }
void CHyprError::destroy() { void CHyprError::destroy() {

View File

@@ -19,17 +19,17 @@ class CHyprError {
float height(); // logical float height(); // logical
private: private:
void createQueued(); void createQueued();
std::string m_szQueued = ""; std::string m_szQueued = "";
CHyprColor m_cQueued; CHyprColor m_cQueued;
bool m_bQueuedDestroy = false; bool m_bQueuedDestroy = false;
bool m_bIsCreated = false; bool m_bIsCreated = false;
SP<CTexture> m_pTexture; SP<CTexture> m_pTexture;
PHLANIMVAR<float> m_fFadeOpacity; CAnimatedVariable<float> m_fFadeOpacity;
CBox m_bDamageBox = {0, 0, 0, 0}; CBox m_bDamageBox = {0, 0, 0, 0};
float m_fLastHeight = 0.F; float m_fLastHeight = 0.F;
bool m_bMonitorChanged = false; bool m_bMonitorChanged = false;
}; };
inline UP<CHyprError> g_pHyprError; // This is a full-screen error. Treat it with respect, and there can only be one at a time. inline std::unique_ptr<CHyprError> g_pHyprError; // This is a full-screen error. Treat it with respect, and there can only be one at a time.

View File

@@ -2,10 +2,6 @@
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "../config/ConfigValue.hpp" #include "../config/ConfigValue.hpp"
#include "../render/decorations/CHyprGroupBarDecoration.hpp" #include "../render/decorations/CHyprGroupBarDecoration.hpp"
#include "../render/Renderer.hpp"
#include "../managers/input/InputManager.hpp"
#include "../managers/LayoutManager.hpp"
#include "../managers/EventManager.hpp"
void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverride, bool verticalOverride) { void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverride, bool verticalOverride) {
if (children[0]) { if (children[0]) {
@@ -42,6 +38,14 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverrid
} }
} }
void SDwindleNodeData::getAllChildrenRecursive(std::vector<SDwindleNodeData*>* pVec) {
if (children[0]) {
children[0]->getAllChildrenRecursive(pVec);
children[1]->getAllChildrenRecursive(pVec);
} else
pVec->push_back(this);
}
int CHyprDwindleLayout::getNodesOnWorkspace(const WORKSPACEID& id) { int CHyprDwindleLayout::getNodesOnWorkspace(const WORKSPACEID& id) {
int no = 0; int no = 0;
for (auto const& n : m_lDwindleNodesData) { for (auto const& n : m_lDwindleNodesData) {
@@ -105,8 +109,8 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
break; break;
} }
} }
} else if (const auto WS = g_pCompositor->getWorkspaceByID(pNode->workspaceID); WS) } else
PMONITOR = WS->m_pMonitor.lock(); PMONITOR = g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_pMonitor.lock();
if (!PMONITOR) { if (!PMONITOR) {
Debug::log(ERR, "Orphaned Node {}!!", pNode); Debug::log(ERR, "Orphaned Node {}!!", pNode);
@@ -196,25 +200,25 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR}; CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR};
wb.round(); // avoid rounding mess wb.round(); // avoid rounding mess
*PWINDOW->m_vRealPosition = wb.pos(); PWINDOW->m_vRealPosition = wb.pos();
*PWINDOW->m_vRealSize = wb.size(); PWINDOW->m_vRealSize = wb.size();
PWINDOW->sendWindowSize(wb.size()); g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
} else { } else {
CBox wb = {calcPos, calcSize}; CBox wb = {calcPos, calcSize};
wb.round(); // avoid rounding mess wb.round(); // avoid rounding mess
*PWINDOW->m_vRealSize = wb.size(); PWINDOW->m_vRealSize = wb.size();
*PWINDOW->m_vRealPosition = wb.pos(); PWINDOW->m_vRealPosition = wb.pos();
PWINDOW->sendWindowSize(wb.size()); g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
} }
if (force) { if (force) {
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
PWINDOW->m_vRealPosition->warp(); PWINDOW->m_vRealPosition.warp();
PWINDOW->m_vRealSize->warp(); PWINDOW->m_vRealSize.warp();
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
} }
@@ -512,8 +516,8 @@ void CHyprDwindleLayout::calculateWorkspace(const PHLWORKSPACE& pWorkspace) {
const auto PFULLWINDOW = pWorkspace->getFullscreenWindow(); const auto PFULLWINDOW = pWorkspace->getFullscreenWindow();
if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) { if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) {
*PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition; PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition;
*PFULLWINDOW->m_vRealSize = PMONITOR->vecSize; PFULLWINDOW->m_vRealSize = PMONITOR->vecSize;
} else if (pWorkspace->m_efFullscreenMode == FSMODE_MAXIMIZED) { } else if (pWorkspace->m_efFullscreenMode == FSMODE_MAXIMIZED) {
SDwindleNodeData fakeNode; SDwindleNodeData fakeNode;
fakeNode.pWindow = PFULLWINDOW; fakeNode.pWindow = PFULLWINDOW;
@@ -558,8 +562,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
const auto PNODE = getNodeFromWindow(PWINDOW); const auto PNODE = getNodeFromWindow(PWINDOW);
if (!PNODE) { if (!PNODE) {
*PWINDOW->m_vRealSize = PWINDOW->m_vRealSize =
(PWINDOW->m_vRealSize->goal() + pixResize) (PWINDOW->m_vRealSize.goal() + pixResize)
.clamp(PWINDOW->m_sWindowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_sWindowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY})); .clamp(PWINDOW->m_sWindowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_sWindowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY}));
PWINDOW->updateWindowDecos(); PWINDOW->updateWindowDecos();
return; return;
@@ -579,7 +583,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
if (!m_PseudoDragFlags.started) { if (!m_PseudoDragFlags.started) {
m_PseudoDragFlags.started = true; m_PseudoDragFlags.started = true;
const auto pseudoSize = PWINDOW->m_vRealSize->goal(); const auto pseudoSize = PWINDOW->m_vRealSize.goal();
const auto mouseOffset = g_pInputManager->getMouseCoordsInternal() - (PNODE->box.pos() + ((PNODE->box.size() / 2) - (pseudoSize / 2))); const auto mouseOffset = g_pInputManager->getMouseCoordsInternal() - (PNODE->box.pos() + ((PNODE->box.size() / 2) - (pseudoSize / 2)));
if (mouseOffset.x > 0 && mouseOffset.x < pseudoSize.x && mouseOffset.y > 0 && mouseOffset.y < pseudoSize.y) { if (mouseOffset.x > 0 && mouseOffset.x < pseudoSize.x && mouseOffset.y > 0 && mouseOffset.y < pseudoSize.y) {
@@ -747,10 +751,10 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFu
// save position and size if floating // save position and size if floating
if (pWindow->m_bIsFloating && CURRENT_EFFECTIVE_MODE == FSMODE_NONE) { if (pWindow->m_bIsFloating && CURRENT_EFFECTIVE_MODE == FSMODE_NONE) {
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize->goal(); pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goal();
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition->goal(); pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goal();
pWindow->m_vPosition = pWindow->m_vRealPosition->goal(); pWindow->m_vPosition = pWindow->m_vRealPosition.goal();
pWindow->m_vSize = pWindow->m_vRealSize->goal(); pWindow->m_vSize = pWindow->m_vRealSize.goal();
} }
if (EFFECTIVE_MODE == FSMODE_NONE) { if (EFFECTIVE_MODE == FSMODE_NONE) {
@@ -760,8 +764,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFu
applyNodeDataToWindow(PNODE); applyNodeDataToWindow(PNODE);
else { else {
// get back its' dimensions from position and size // get back its' dimensions from position and size
*pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition; pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition;
*pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; pWindow->m_vRealSize = pWindow->m_vLastFloatingSize;
pWindow->unsetWindowData(PRIORITY_LAYOUT); pWindow->unsetWindowData(PRIORITY_LAYOUT);
pWindow->updateWindowData(); pWindow->updateWindowData();
@@ -769,8 +773,8 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFu
} else { } else {
// apply new pos and size being monitors' box // apply new pos and size being monitors' box
if (EFFECTIVE_MODE == FSMODE_FULLSCREEN) { if (EFFECTIVE_MODE == FSMODE_FULLSCREEN) {
*pWindow->m_vRealPosition = PMONITOR->vecPosition; pWindow->m_vRealPosition = PMONITOR->vecPosition;
*pWindow->m_vRealSize = PMONITOR->vecSize; pWindow->m_vRealSize = PMONITOR->vecSize;
} else { } else {
// This is a massive hack. // This is a massive hack.
// We make a fake "only" node and apply // We make a fake "only" node and apply
@@ -800,6 +804,15 @@ void CHyprDwindleLayout::recalculateWindow(PHLWINDOW pWindow) {
PNODE->recalcSizePosRecursive(); PNODE->recalcSizePosRecursive();
} }
static void addToVectorRecursive(std::vector<SDwindleNodeData*>* pVec, std::vector<SDwindleNodeData*>* pParents, SDwindleNodeData* node) {
if (node->isNode) {
pParents->emplace_back(node);
addToVectorRecursive(pVec, pParents, node->children[0]);
addToVectorRecursive(pVec, pParents, node->children[1]);
} else
pVec->emplace_back(node);
}
SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(PHLWINDOW pWindow) { SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(PHLWINDOW pWindow) {
// window should be valid, insallah // window should be valid, insallah
SWindowRenderLayoutHints hints; SWindowRenderLayoutHints hints;
@@ -847,15 +860,6 @@ void CHyprDwindleLayout::moveWindowTo(PHLWINDOW pWindow, const std::string& dir,
pWindow->m_pMonitor = PMONITORFOCAL; pWindow->m_pMonitor = PMONITORFOCAL;
} }
pWindow->updateGroupOutputs();
if (!pWindow->m_sGroupData.pNextWindow.expired()) {
PHLWINDOW next = pWindow->m_sGroupData.pNextWindow.lock();
while (next != pWindow) {
next->updateToplevel();
next = next->m_sGroupData.pNextWindow.lock();
}
}
onWindowCreatedTiling(pWindow); onWindowCreatedTiling(pWindow);
m_vOverrideFocalPoint.reset(); m_vOverrideFocalPoint.reset();

View File

@@ -39,6 +39,7 @@ struct SDwindleNodeData {
} }
void recalcSizePosRecursive(bool force = false, bool horizontalOverride = false, bool verticalOverride = false); void recalcSizePosRecursive(bool force = false, bool horizontalOverride = false, bool verticalOverride = false);
void getAllChildrenRecursive(std::vector<SDwindleNodeData*>*);
CHyprDwindleLayout* layout = nullptr; CHyprDwindleLayout* layout = nullptr;
}; };

View File

@@ -7,14 +7,10 @@
#include "../protocols/XDGShell.hpp" #include "../protocols/XDGShell.hpp"
#include "../protocols/core/Compositor.hpp" #include "../protocols/core/Compositor.hpp"
#include "../xwayland/XSurface.hpp" #include "../xwayland/XSurface.hpp"
#include "../render/Renderer.hpp"
#include "../managers/input/InputManager.hpp"
#include "../managers/LayoutManager.hpp"
#include "../managers/EventManager.hpp"
#include "../managers/HookSystemManager.hpp"
void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) { void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) {
CBox desiredGeometry = g_pXWaylandManager->getGeometryForWindow(pWindow); CBox desiredGeometry = {};
g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) { if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
const auto PMONITOR = pWindow->m_pMonitor.lock(); const auto PMONITOR = pWindow->m_pMonitor.lock();
@@ -90,8 +86,9 @@ void IHyprLayout::onWindowRemovedFloating(PHLWINDOW pWindow) {
void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) {
CBox desiredGeometry = g_pXWaylandManager->getGeometryForWindow(pWindow); CBox desiredGeometry = {0};
const auto PMONITOR = pWindow->m_pMonitor.lock(); g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry);
const auto PMONITOR = pWindow->m_pMonitor.lock();
if (pWindow->m_bIsX11) { if (pWindow->m_bIsX11) {
Vector2D xy = {desiredGeometry.x, desiredGeometry.y}; Vector2D xy = {desiredGeometry.x, desiredGeometry.y};
@@ -109,7 +106,7 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) {
if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) { if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) {
const auto PWINDOWSURFACE = pWindow->m_pWLSurface->resource(); const auto PWINDOWSURFACE = pWindow->m_pWLSurface->resource();
*pWindow->m_vRealSize = PWINDOWSURFACE->current.size; pWindow->m_vRealSize = PWINDOWSURFACE->current.size;
if ((desiredGeometry.width <= 1 || desiredGeometry.height <= 1) && pWindow->m_bIsX11 && if ((desiredGeometry.width <= 1 || desiredGeometry.height <= 1) && pWindow->m_bIsX11 &&
pWindow->isX11OverrideRedirect()) { // XDG windows should be fine. TODO: check for weird atoms? pWindow->isX11OverrideRedirect()) { // XDG windows should be fine. TODO: check for weird atoms?
@@ -118,23 +115,23 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) {
} }
// reject any windows with size <= 5x5 // reject any windows with size <= 5x5
if (pWindow->m_vRealSize->goal().x <= 5 || pWindow->m_vRealSize->goal().y <= 5) if (pWindow->m_vRealSize.goal().x <= 5 || pWindow->m_vRealSize.goal().y <= 5)
*pWindow->m_vRealSize = PMONITOR->vecSize / 2.f; pWindow->m_vRealSize = PMONITOR->vecSize / 2.f;
if (pWindow->m_bIsX11 && pWindow->isX11OverrideRedirect()) { if (pWindow->m_bIsX11 && pWindow->isX11OverrideRedirect()) {
if (pWindow->m_pXWaylandSurface->geometry.x != 0 && pWindow->m_pXWaylandSurface->geometry.y != 0) if (pWindow->m_pXWaylandSurface->geometry.x != 0 && pWindow->m_pXWaylandSurface->geometry.y != 0)
*pWindow->m_vRealPosition = g_pXWaylandManager->xwaylandToWaylandCoords(pWindow->m_pXWaylandSurface->geometry.pos()); pWindow->m_vRealPosition = g_pXWaylandManager->xwaylandToWaylandCoords(pWindow->m_pXWaylandSurface->geometry.pos());
else else
*pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize->goal().x) / 2.f, pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goal().x) / 2.f,
PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize->goal().y) / 2.f); PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goal().y) / 2.f);
} else { } else {
*pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize->goal().x) / 2.f, pWindow->m_vRealPosition = Vector2D(PMONITOR->vecPosition.x + (PMONITOR->vecSize.x - pWindow->m_vRealSize.goal().x) / 2.f,
PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize->goal().y) / 2.f); PMONITOR->vecPosition.y + (PMONITOR->vecSize.y - pWindow->m_vRealSize.goal().y) / 2.f);
} }
} else { } else {
// we respect the size. // we respect the size.
*pWindow->m_vRealSize = Vector2D(desiredGeometry.width, desiredGeometry.height); pWindow->m_vRealSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
// check if it's on the correct monitor! // check if it's on the correct monitor!
Vector2D middlePoint = Vector2D(desiredGeometry.x, desiredGeometry.y) + Vector2D(desiredGeometry.width, desiredGeometry.height) / 2.f; Vector2D middlePoint = Vector2D(desiredGeometry.x, desiredGeometry.y) + Vector2D(desiredGeometry.width, desiredGeometry.height) / 2.f;
@@ -153,35 +150,35 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) {
if ((desiredGeometry.x == 0 && desiredGeometry.y == 0) || !visible || !pWindow->m_bIsX11) { if ((desiredGeometry.x == 0 && desiredGeometry.y == 0) || !visible || !pWindow->m_bIsX11) {
// if the pos isn't set, fall back to the center placement if it's not a child, otherwise middle of parent if available // if the pos isn't set, fall back to the center placement if it's not a child, otherwise middle of parent if available
if (!pWindow->m_bIsX11 && pWindow->m_pXDGSurface->toplevel->parent && validMapped(pWindow->m_pXDGSurface->toplevel->parent->window)) if (!pWindow->m_bIsX11 && pWindow->m_pXDGSurface->toplevel->parent && validMapped(pWindow->m_pXDGSurface->toplevel->parent->window))
*pWindow->m_vRealPosition = pWindow->m_pXDGSurface->toplevel->parent->window->m_vRealPosition->goal() + pWindow->m_vRealPosition = pWindow->m_pXDGSurface->toplevel->parent->window->m_vRealPosition.goal() +
pWindow->m_pXDGSurface->toplevel->parent->window->m_vRealSize->goal() / 2.F - desiredGeometry.size() / 2.F; pWindow->m_pXDGSurface->toplevel->parent->window->m_vRealSize.goal() / 2.F - desiredGeometry.size() / 2.F;
else else
*pWindow->m_vRealPosition = PMONITOR->vecPosition + PMONITOR->vecSize / 2.F - desiredGeometry.size() / 2.F; pWindow->m_vRealPosition = PMONITOR->vecPosition + PMONITOR->vecSize / 2.F - desiredGeometry.size() / 2.F;
} else { } else {
// if it is, we respect where it wants to put itself, but apply monitor offset if outside // if it is, we respect where it wants to put itself, but apply monitor offset if outside
// most of these are popups // most of these are popups
if (const auto POPENMON = g_pCompositor->getMonitorFromVector(middlePoint); POPENMON->ID != PMONITOR->ID) if (const auto POPENMON = g_pCompositor->getMonitorFromVector(middlePoint); POPENMON->ID != PMONITOR->ID)
*pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y) - POPENMON->vecPosition + PMONITOR->vecPosition; pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y) - POPENMON->vecPosition + PMONITOR->vecPosition;
else else
*pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y); pWindow->m_vRealPosition = Vector2D(desiredGeometry.x, desiredGeometry.y);
} }
} }
if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11) if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11)
*pWindow->m_vRealSize = pWindow->m_vRealSize->goal() / PMONITOR->scale; pWindow->m_vRealSize = pWindow->m_vRealSize.goal() / PMONITOR->scale;
if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->isX11OverrideRedirect())) { if (pWindow->m_bX11DoesntWantBorders || (pWindow->m_bIsX11 && pWindow->isX11OverrideRedirect())) {
pWindow->m_vRealPosition->warp(); pWindow->m_vRealPosition.warp();
pWindow->m_vRealSize->warp(); pWindow->m_vRealSize.warp();
} }
if (!pWindow->isX11OverrideRedirect()) { if (!pWindow->isX11OverrideRedirect()) {
pWindow->sendWindowSize(pWindow->m_vRealSize->goal()); g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal());
g_pCompositor->changeWindowZOrder(pWindow, true); g_pCompositor->changeWindowZOrder(pWindow, true);
} else { } else {
pWindow->m_vPendingReportedSize = pWindow->m_vRealSize->goal(); pWindow->m_vPendingReportedSize = pWindow->m_vRealSize.goal();
pWindow->m_vReportedSize = pWindow->m_vPendingReportedSize; pWindow->m_vReportedSize = pWindow->m_vPendingReportedSize;
} }
} }
@@ -208,12 +205,11 @@ bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) {
(*USECURRPOS ? OPENINGON : OPENINGON->getGroupTail())->insertWindowToGroup(pWindow); (*USECURRPOS ? OPENINGON : OPENINGON->getGroupTail())->insertWindowToGroup(pWindow);
OPENINGON->setGroupCurrent(pWindow); OPENINGON->setGroupCurrent(pWindow);
pWindow->applyGroupRules();
pWindow->updateWindowDecos(); pWindow->updateWindowDecos();
recalculateWindow(pWindow); recalculateWindow(pWindow);
if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) if (!pWindow->getDecorationByType(DECORATION_GROUPBAR))
pWindow->addWindowDeco(makeUnique<CHyprGroupBarDecoration>(pWindow)); pWindow->addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(pWindow));
return true; return true;
} }
@@ -253,18 +249,18 @@ void IHyprLayout::onBeginDragWindow() {
if (!DRAGGINGWINDOW->m_bIsFloating) { if (!DRAGGINGWINDOW->m_bIsFloating) {
if (g_pInputManager->dragMode == MBIND_MOVE) { if (g_pInputManager->dragMode == MBIND_MOVE) {
DRAGGINGWINDOW->m_vLastFloatingSize = (DRAGGINGWINDOW->m_vRealSize->goal() * 0.8489).clamp(Vector2D{5, 5}, Vector2D{}).floor(); DRAGGINGWINDOW->m_vLastFloatingSize = (DRAGGINGWINDOW->m_vRealSize.goal() * 0.8489).clamp(Vector2D{5, 5}, Vector2D{}).floor();
changeWindowFloatingMode(DRAGGINGWINDOW); changeWindowFloatingMode(DRAGGINGWINDOW);
DRAGGINGWINDOW->m_bIsFloating = true; DRAGGINGWINDOW->m_bIsFloating = true;
DRAGGINGWINDOW->m_bDraggingTiled = true; DRAGGINGWINDOW->m_bDraggingTiled = true;
*DRAGGINGWINDOW->m_vRealPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_vRealSize->goal() / 2.f; DRAGGINGWINDOW->m_vRealPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_vRealSize.goal() / 2.f;
} }
} }
m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal(); m_vBeginDragXY = g_pInputManager->getMouseCoordsInternal();
m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition->goal(); m_vBeginDragPositionXY = DRAGGINGWINDOW->m_vRealPosition.goal();
m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize->goal(); m_vBeginDragSizeXY = DRAGGINGWINDOW->m_vRealSize.goal();
m_vLastDragXY = m_vBeginDragXY; m_vLastDragXY = m_vBeginDragXY;
// get the grab corner // get the grab corner
@@ -351,10 +347,10 @@ void IHyprLayout::onEndDragWindow() {
if (DRAGGINGWINDOW->m_sGroupData.pNextWindow) { if (DRAGGINGWINDOW->m_sGroupData.pNextWindow) {
PHLWINDOW next = DRAGGINGWINDOW->m_sGroupData.pNextWindow.lock(); PHLWINDOW next = DRAGGINGWINDOW->m_sGroupData.pNextWindow.lock();
while (next != DRAGGINGWINDOW) { while (next != DRAGGINGWINDOW) {
next->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of group members next->m_bIsFloating = pWindow->m_bIsFloating; // match the floating state of group members
*next->m_vRealSize = pWindow->m_vRealSize->goal(); // match the size of group members next->m_vRealSize = pWindow->m_vRealSize.goal(); // match the size of group members
*next->m_vRealPosition = pWindow->m_vRealPosition->goal(); // match the position of group members next->m_vRealPosition = pWindow->m_vRealPosition.goal(); // match the position of group members
next = next->m_sGroupData.pNextWindow.lock(); next = next->m_sGroupData.pNextWindow.lock();
} }
} }
@@ -363,16 +359,15 @@ void IHyprLayout::onEndDragWindow() {
DRAGGINGWINDOW->m_bDraggingTiled = false; DRAGGINGWINDOW->m_bDraggingTiled = false;
if (pWindow->m_bIsFloating) if (pWindow->m_bIsFloating)
DRAGGINGWINDOW->sendWindowSize(DRAGGINGWINDOW->m_vRealSize->goal()); // match the size of the window g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, pWindow->m_vRealSize.goal()); // match the size of the window
static auto USECURRPOS = CConfigValue<Hyprlang::INT>("group:insert_after_current"); static auto USECURRPOS = CConfigValue<Hyprlang::INT>("group:insert_after_current");
(*USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW); (*USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW);
pWindow->setGroupCurrent(DRAGGINGWINDOW); pWindow->setGroupCurrent(DRAGGINGWINDOW);
DRAGGINGWINDOW->applyGroupRules();
DRAGGINGWINDOW->updateWindowDecos(); DRAGGINGWINDOW->updateWindowDecos();
if (!DRAGGINGWINDOW->getDecorationByType(DECORATION_GROUPBAR)) if (!DRAGGINGWINDOW->getDecorationByType(DECORATION_GROUPBAR))
DRAGGINGWINDOW->addWindowDeco(makeUnique<CHyprGroupBarDecoration>(DRAGGINGWINDOW)); DRAGGINGWINDOW->addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(DRAGGINGWINDOW));
} }
} }
} }
@@ -424,13 +419,11 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA
SRange sourceY = {sourcePos.y, sourcePos.y + sourceSize.y}; SRange sourceY = {sourcePos.y, sourcePos.y + sourceSize.y};
if (*SNAPWINDOWGAP) { if (*SNAPWINDOWGAP) {
const double GAPSIZE = *SNAPWINDOWGAP; const double GAPSIZE = *SNAPWINDOWGAP;
const auto WSID = DRAGGINGWINDOW->workspaceID(); const auto WSID = DRAGGINGWINDOW->workspaceID();
const bool HASFULLSCREEN = DRAGGINGWINDOW->m_pWorkspace && DRAGGINGWINDOW->m_pWorkspace->m_bHasFullscreenWindow;
for (auto& other : g_pCompositor->m_vWindows) { for (auto& other : g_pCompositor->m_vWindows) {
if ((HASFULLSCREEN && !other->m_bCreatedOverFullscreen) || other == DRAGGINGWINDOW || other->workspaceID() != WSID || !other->m_bIsMapped || other->m_bFadingOut || if (other == DRAGGINGWINDOW || other->workspaceID() != WSID || !other->m_bIsMapped || other->m_bFadingOut || other->isX11OverrideRedirect())
other->isX11OverrideRedirect())
continue; continue;
const int OTHERBORDERSIZE = other->getRealBorderSize(); const int OTHERBORDERSIZE = other->getRealBorderSize();
@@ -462,22 +455,22 @@ static void performSnap(Vector2D& sourcePos, Vector2D& sourceSize, PHLWINDOW DRA
// corner snapping // corner snapping
const double BORDERDIFF = OTHERBORDERSIZE - DRAGGINGBORDERSIZE; const double BORDERDIFF = OTHERBORDERSIZE - DRAGGINGBORDERSIZE;
if (sourceX.start == SURFBX.end || SURFBX.start == sourceX.end) { if (snaps & (SNAP_LEFT | SNAP_RIGHT)) {
const SRange SURFY = {SURF.y - BORDERDIFF, SURF.y + SURF.h + BORDERDIFF}; const SRange SURFY = {SURF.y - BORDERDIFF, SURF.y + SURF.h + BORDERDIFF};
if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && !(snaps & SNAP_UP) && canSnap(sourceY.start, SURFY.start, GAPSIZE)) { if (CORNER & (CORNER_TOPLEFT | CORNER_TOPRIGHT) && canSnap(sourceY.start, SURFY.start, GAPSIZE)) {
SNAP(sourceY.start, sourceY.end, SURFY.start); SNAP(sourceY.start, sourceY.end, SURFY.start);
snaps |= SNAP_UP; snaps |= SNAP_UP;
} else if (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && !(snaps & SNAP_DOWN) && canSnap(sourceY.end, SURFY.end, GAPSIZE)) { } else if (CORNER & (CORNER_BOTTOMLEFT | CORNER_BOTTOMRIGHT) && canSnap(sourceY.end, SURFY.end, GAPSIZE)) {
SNAP(sourceY.end, sourceY.start, SURFY.end); SNAP(sourceY.end, sourceY.start, SURFY.end);
snaps |= SNAP_DOWN; snaps |= SNAP_DOWN;
} }
} }
if (sourceY.start == SURFBY.end || SURFBY.start == sourceY.end) { if (snaps & (SNAP_UP | SNAP_DOWN)) {
const SRange SURFX = {SURF.x - BORDERDIFF, SURF.x + SURF.w + BORDERDIFF}; const SRange SURFX = {SURF.x - BORDERDIFF, SURF.x + SURF.w + BORDERDIFF};
if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && !(snaps & SNAP_LEFT) && canSnap(sourceX.start, SURFX.start, GAPSIZE)) { if (CORNER & (CORNER_TOPLEFT | CORNER_BOTTOMLEFT) && canSnap(sourceX.start, SURFX.start, GAPSIZE)) {
SNAP(sourceX.start, sourceX.end, SURFX.start); SNAP(sourceX.start, sourceX.end, SURFX.start);
snaps |= SNAP_LEFT; snaps |= SNAP_LEFT;
} else if (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && !(snaps & SNAP_RIGHT) && canSnap(sourceX.end, SURFX.end, GAPSIZE)) { } else if (CORNER & (CORNER_TOPRIGHT | CORNER_BOTTOMRIGHT) && canSnap(sourceX.end, SURFX.end, GAPSIZE)) {
SNAP(sourceX.end, sourceX.start, SURFX.end); SNAP(sourceX.end, sourceX.start, SURFX.end);
snaps |= SNAP_RIGHT; snaps |= SNAP_RIGHT;
} }
@@ -596,7 +589,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
if (g_pInputManager->dragMode == MBIND_MOVE) { if (g_pInputManager->dragMode == MBIND_MOVE) {
Vector2D newPos = m_vBeginDragPositionXY + DELTA; Vector2D newPos = m_vBeginDragPositionXY + DELTA;
Vector2D newSize = DRAGGINGWINDOW->m_vRealSize->goal(); Vector2D newSize = DRAGGINGWINDOW->m_vRealSize.goal();
if (*SNAPENABLED && !DRAGGINGWINDOW->m_bDraggingTiled) if (*SNAPENABLED && !DRAGGINGWINDOW->m_bDraggingTiled)
performSnap(newPos, newSize, DRAGGINGWINDOW, MBIND_MOVE, -1, m_vBeginDragSizeXY); performSnap(newPos, newSize, DRAGGINGWINDOW, MBIND_MOVE, -1, m_vBeginDragSizeXY);
@@ -605,11 +598,11 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
wb.round(); wb.round();
if (*PANIMATEMOUSE) if (*PANIMATEMOUSE)
*DRAGGINGWINDOW->m_vRealPosition = wb.pos(); DRAGGINGWINDOW->m_vRealPosition = wb.pos();
else else
DRAGGINGWINDOW->m_vRealPosition->setValueAndWarp(wb.pos()); DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos());
DRAGGINGWINDOW->sendWindowSize(DRAGGINGWINDOW->m_vRealSize->goal()); g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goal());
} else if (g_pInputManager->dragMode == MBIND_RESIZE || g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) { } else if (g_pInputManager->dragMode == MBIND_RESIZE || g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) {
if (DRAGGINGWINDOW->m_bIsFloating) { if (DRAGGINGWINDOW->m_bIsFloating) {
@@ -674,21 +667,21 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
wb.round(); wb.round();
if (*PANIMATE) { if (*PANIMATE) {
*DRAGGINGWINDOW->m_vRealSize = wb.size(); DRAGGINGWINDOW->m_vRealSize = wb.size();
*DRAGGINGWINDOW->m_vRealPosition = wb.pos(); DRAGGINGWINDOW->m_vRealPosition = wb.pos();
} else { } else {
DRAGGINGWINDOW->m_vRealSize->setValueAndWarp(wb.size()); DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(wb.size());
DRAGGINGWINDOW->m_vRealPosition->setValueAndWarp(wb.pos()); DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos());
} }
DRAGGINGWINDOW->sendWindowSize(DRAGGINGWINDOW->m_vRealSize->goal()); g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goal());
} else { } else {
resizeActiveWindow(TICKDELTA, m_eGrabbedCorner, DRAGGINGWINDOW); resizeActiveWindow(TICKDELTA, m_eGrabbedCorner, DRAGGINGWINDOW);
} }
} }
// get middle point // get middle point
Vector2D middle = DRAGGINGWINDOW->m_vRealPosition->value() + DRAGGINGWINDOW->m_vRealSize->value() / 2.f; Vector2D middle = DRAGGINGWINDOW->m_vRealPosition.value() + DRAGGINGWINDOW->m_vRealSize.value() / 2.f;
// and check its monitor // and check its monitor
const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle); const auto PMONITOR = g_pCompositor->getMonitorFromVector(middle);
@@ -715,8 +708,6 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) {
pWindow->m_bPinned = false; pWindow->m_bPinned = false;
g_pHyprRenderer->damageWindow(pWindow, true);
const auto TILED = isWindowTiled(pWindow); const auto TILED = isWindowTiled(pWindow);
// event // event
@@ -724,7 +715,7 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) {
EMIT_HOOK_EVENT("changeFloatingMode", pWindow); EMIT_HOOK_EVENT("changeFloatingMode", pWindow);
if (!TILED) { if (!TILED) {
const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition->value() + pWindow->m_vRealSize->value() / 2.f); const auto PNEWMON = g_pCompositor->getMonitorFromVector(pWindow->m_vRealPosition.value() + pWindow->m_vRealSize.value() / 2.f);
pWindow->m_pMonitor = PNEWMON; pWindow->m_pMonitor = PNEWMON;
pWindow->moveToWorkspace(PNEWMON->activeSpecialWorkspace ? PNEWMON->activeSpecialWorkspace : PNEWMON->activeWorkspace); pWindow->moveToWorkspace(PNEWMON->activeSpecialWorkspace ? PNEWMON->activeSpecialWorkspace : PNEWMON->activeWorkspace);
pWindow->updateGroupOutputs(); pWindow->updateGroupOutputs();
@@ -735,12 +726,12 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) {
g_pCompositor->setWindowFullscreenInternal(PWORKSPACE->getFullscreenWindow(), FSMODE_NONE); g_pCompositor->setWindowFullscreenInternal(PWORKSPACE->getFullscreenWindow(), FSMODE_NONE);
// save real pos cuz the func applies the default 5,5 mid // save real pos cuz the func applies the default 5,5 mid
const auto PSAVEDPOS = pWindow->m_vRealPosition->goal(); const auto PSAVEDPOS = pWindow->m_vRealPosition.goal();
const auto PSAVEDSIZE = pWindow->m_vRealSize->goal(); const auto PSAVEDSIZE = pWindow->m_vRealSize.goal();
// if the window is pseudo, update its size // if the window is pseudo, update its size
if (!pWindow->m_bDraggingTiled) if (!pWindow->m_bDraggingTiled)
pWindow->m_vPseudoSize = pWindow->m_vRealSize->goal(); pWindow->m_vPseudoSize = pWindow->m_vRealSize.goal();
pWindow->m_vLastFloatingSize = PSAVEDSIZE; pWindow->m_vLastFloatingSize = PSAVEDSIZE;
@@ -749,8 +740,8 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) {
onWindowCreatedTiling(pWindow); onWindowCreatedTiling(pWindow);
pWindow->m_vRealPosition->setValue(PSAVEDPOS); pWindow->m_vRealPosition.setValue(PSAVEDPOS);
pWindow->m_vRealSize->setValue(PSAVEDSIZE); pWindow->m_vRealSize.setValue(PSAVEDSIZE);
// fix pseudo leaving artifacts // fix pseudo leaving artifacts
g_pHyprRenderer->damageMonitor(pWindow->m_pMonitor.lock()); g_pHyprRenderer->damageMonitor(pWindow->m_pMonitor.lock());
@@ -762,16 +753,16 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) {
g_pCompositor->changeWindowZOrder(pWindow, true); g_pCompositor->changeWindowZOrder(pWindow, true);
CBox wb = {pWindow->m_vRealPosition->goal() + (pWindow->m_vRealSize->goal() - pWindow->m_vLastFloatingSize) / 2.f, pWindow->m_vLastFloatingSize}; CBox wb = {pWindow->m_vRealPosition.goal() + (pWindow->m_vRealSize.goal() - pWindow->m_vLastFloatingSize) / 2.f, pWindow->m_vLastFloatingSize};
wb.round(); wb.round();
if (!(pWindow->m_bIsFloating && pWindow->m_bIsPseudotiled) && DELTALESSTHAN(pWindow->m_vRealSize->value().x, pWindow->m_vLastFloatingSize.x, 10) && if (!(pWindow->m_bIsFloating && pWindow->m_bIsPseudotiled) && DELTALESSTHAN(pWindow->m_vRealSize.value().x, pWindow->m_vLastFloatingSize.x, 10) &&
DELTALESSTHAN(pWindow->m_vRealSize->value().y, pWindow->m_vLastFloatingSize.y, 10)) { DELTALESSTHAN(pWindow->m_vRealSize.value().y, pWindow->m_vLastFloatingSize.y, 10)) {
wb = {wb.pos() + Vector2D{10, 10}, wb.size() - Vector2D{20, 20}}; wb = {wb.pos() + Vector2D{10, 10}, wb.size() - Vector2D{20, 20}};
} }
*pWindow->m_vRealPosition = wb.pos(); pWindow->m_vRealPosition = wb.pos();
*pWindow->m_vRealSize = wb.size(); pWindow->m_vRealSize = wb.size();
pWindow->m_vSize = wb.pos(); pWindow->m_vSize = wb.pos();
pWindow->m_vPosition = wb.size(); pWindow->m_vPosition = wb.size();
@@ -786,9 +777,8 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) {
} }
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow); g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
pWindow->updateToplevel(); pWindow->updateToplevel();
pWindow->sendWindowSize(pWindow->m_vRealSize->goal());
g_pHyprRenderer->damageWindow(pWindow);
} }
void IHyprLayout::moveActiveWindow(const Vector2D& delta, PHLWINDOW pWindow) { void IHyprLayout::moveActiveWindow(const Vector2D& delta, PHLWINDOW pWindow) {
@@ -804,7 +794,7 @@ void IHyprLayout::moveActiveWindow(const Vector2D& delta, PHLWINDOW pWindow) {
PWINDOW->setAnimationsToMove(); PWINDOW->setAnimationsToMove();
*PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition->goal() + delta; PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goal() + delta;
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
} }

View File

@@ -8,7 +8,7 @@ class CGradientValueData;
struct SWindowRenderLayoutHints { struct SWindowRenderLayoutHints {
bool isBorderGradient = false; bool isBorderGradient = false;
CGradientValueData* borderGradient = nullptr; CGradientValueData* borderGradient;
}; };
struct SLayoutMessageHeader { struct SLayoutMessageHeader {

View File

@@ -4,10 +4,6 @@
#include "config/ConfigDataValues.hpp" #include "config/ConfigDataValues.hpp"
#include <ranges> #include <ranges>
#include "../config/ConfigValue.hpp" #include "../config/ConfigValue.hpp"
#include "../render/Renderer.hpp"
#include "../managers/input/InputManager.hpp"
#include "../managers/LayoutManager.hpp"
#include "../managers/EventManager.hpp"
SMasterNodeData* CHyprMasterLayout::getNodeFromWindow(PHLWINDOW pWindow) { SMasterNodeData* CHyprMasterLayout::getNodeFromWindow(PHLWINDOW pWindow) {
for (auto& nd : m_lMasterNodesData) { for (auto& nd : m_lMasterNodesData) {
@@ -305,8 +301,8 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
const auto PFULLWINDOW = pWorkspace->getFullscreenWindow(); const auto PFULLWINDOW = pWorkspace->getFullscreenWindow();
if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) { if (pWorkspace->m_efFullscreenMode == FSMODE_FULLSCREEN) {
*PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition; PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition;
*PFULLWINDOW->m_vRealSize = PMONITOR->vecSize; PFULLWINDOW->m_vRealSize = PMONITOR->vecSize;
} else if (pWorkspace->m_efFullscreenMode == FSMODE_MAXIMIZED) { } else if (pWorkspace->m_efFullscreenMode == FSMODE_MAXIMIZED) {
SMasterNodeData fakeNode; SMasterNodeData fakeNode;
fakeNode.pWindow = PFULLWINDOW; fakeNode.pWindow = PFULLWINDOW;
@@ -329,12 +325,11 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
if (!PMASTERNODE) if (!PMASTERNODE)
return; return;
eOrientation orientation = getDynamicOrientation(pWorkspace); eOrientation orientation = getDynamicOrientation(pWorkspace);
bool centerMasterWindow = false; bool centerMasterWindow = false;
static auto SLAVECOUNTFORCENTER = CConfigValue<Hyprlang::INT>("master:slave_count_for_center_master"); static auto ALWAYSCENTER = CConfigValue<Hyprlang::INT>("master:always_center_master");
static auto CMSLAVESONRIGHT = CConfigValue<Hyprlang::INT>("master:center_master_slaves_on_right"); static auto PIGNORERESERVED = CConfigValue<Hyprlang::INT>("master:center_ignores_reserved");
static auto PIGNORERESERVED = CConfigValue<Hyprlang::INT>("master:center_ignores_reserved"); static auto PSMARTRESIZING = CConfigValue<Hyprlang::INT>("master:smart_resizing");
static auto PSMARTRESIZING = CConfigValue<Hyprlang::INT>("master:smart_resizing");
const auto MASTERS = getMastersOnWorkspace(pWorkspace->m_iID); const auto MASTERS = getMastersOnWorkspace(pWorkspace->m_iID);
const auto WINDOWS = getNodesOnWorkspace(pWorkspace->m_iID); const auto WINDOWS = getNodesOnWorkspace(pWorkspace->m_iID);
@@ -343,13 +338,10 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
const auto WSPOS = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; const auto WSPOS = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
if (orientation == ORIENTATION_CENTER) { if (orientation == ORIENTATION_CENTER) {
if (STACKWINDOWS >= *SLAVECOUNTFORCENTER) { if (STACKWINDOWS >= 2 || (*ALWAYSCENTER == 1)) {
centerMasterWindow = true; centerMasterWindow = true;
} else { } else {
if (*CMSLAVESONRIGHT) orientation = ORIENTATION_LEFT;
orientation = ORIENTATION_LEFT;
else
orientation = ORIENTATION_RIGHT;
} }
} }
@@ -523,20 +515,15 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
float nextY = 0; float nextY = 0;
float nextYL = 0; float nextYL = 0;
float nextYR = 0; float nextYR = 0;
bool onRight = *CMSLAVESONRIGHT; bool onRight = true;
int slavesLeftL = 1 + (slavesLeft - 1) / 2;
int slavesLeftR = slavesLeft - slavesLeftL;
if (*CMSLAVESONRIGHT) { int slavesLeftR = 1 + (slavesLeft - 1) / 2;
slavesLeftR = 1 + (slavesLeft - 1) / 2; int slavesLeftL = slavesLeft - slavesLeftR;
slavesLeftL = slavesLeft - slavesLeftR;
}
const float slaveAverageHeightL = WSSIZE.y / slavesLeftL; const float slaveAverageHeightL = WSSIZE.y / slavesLeftL;
const float slaveAverageHeightR = WSSIZE.y / slavesLeftR; const float slaveAverageHeightR = WSSIZE.y / slavesLeftR;
float slaveAccumulatedHeightL = 0; float slaveAccumulatedHeightL = 0;
float slaveAccumulatedHeightR = 0; float slaveAccumulatedHeightR = 0;
if (*PSMARTRESIZING) { if (*PSMARTRESIZING) {
for (auto const& nd : m_lMasterNodesData) { for (auto const& nd : m_lMasterNodesData) {
if (nd.workspaceID != pWorkspace->m_iID || nd.isMaster) if (nd.workspaceID != pWorkspace->m_iID || nd.isMaster)
@@ -549,8 +536,7 @@ void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
} }
onRight = !onRight; onRight = !onRight;
} }
onRight = true;
onRight = *CMSLAVESONRIGHT;
} }
for (auto& nd : m_lMasterNodesData) { for (auto& nd : m_lMasterNodesData) {
@@ -676,25 +662,25 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR}; CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR};
wb.round(); // avoid rounding mess wb.round(); // avoid rounding mess
*PWINDOW->m_vRealPosition = wb.pos(); PWINDOW->m_vRealPosition = wb.pos();
*PWINDOW->m_vRealSize = wb.size(); PWINDOW->m_vRealSize = wb.size();
PWINDOW->sendWindowSize(wb.size()); g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
} else { } else {
CBox wb = {calcPos, calcSize}; CBox wb = {calcPos, calcSize};
wb.round(); // avoid rounding mess wb.round(); // avoid rounding mess
*PWINDOW->m_vRealPosition = wb.pos(); PWINDOW->m_vRealPosition = wb.pos();
*PWINDOW->m_vRealSize = wb.size(); PWINDOW->m_vRealSize = wb.size();
PWINDOW->sendWindowSize(wb.size()); g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
} }
if (m_bForceWarps && !*PANIMATE) { if (m_bForceWarps && !*PANIMATE) {
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
PWINDOW->m_vRealPosition->warp(); PWINDOW->m_vRealPosition.warp();
PWINDOW->m_vRealSize->warp(); PWINDOW->m_vRealSize.warp();
g_pHyprRenderer->damageWindow(PWINDOW); g_pHyprRenderer->damageWindow(PWINDOW);
} }
@@ -715,16 +701,20 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne
const auto PNODE = getNodeFromWindow(PWINDOW); const auto PNODE = getNodeFromWindow(PWINDOW);
if (!PNODE) { if (!PNODE) {
*PWINDOW->m_vRealSize = PWINDOW->m_vRealSize =
(PWINDOW->m_vRealSize->goal() + pixResize) (PWINDOW->m_vRealSize.goal() + pixResize)
.clamp(PWINDOW->m_sWindowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_sWindowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY})); .clamp(PWINDOW->m_sWindowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_sWindowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY}));
PWINDOW->updateWindowDecos(); PWINDOW->updateWindowDecos();
return; return;
} }
const auto PMONITOR = PWINDOW->m_pMonitor.lock(); const auto PMONITOR = PWINDOW->m_pMonitor.lock();
static auto SLAVECOUNTFORCENTER = CConfigValue<Hyprlang::INT>("master:slave_count_for_center_master"); static auto ALWAYSCENTER = CConfigValue<Hyprlang::INT>("master:always_center_master");
static auto PSMARTRESIZING = CConfigValue<Hyprlang::INT>("master:smart_resizing"); static auto PSMARTRESIZING = CConfigValue<Hyprlang::INT>("master:smart_resizing");
eOrientation orientation = getDynamicOrientation(PWINDOW->m_pWorkspace);
bool centered = orientation == ORIENTATION_CENTER && (*ALWAYSCENTER == 1);
double delta = 0;
const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_vPosition.y + PWINDOW->m_vSize.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y); const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_vPosition.y + PWINDOW->m_vSize.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
const bool DISPLAYRIGHT = STICKS(PWINDOW->m_vPosition.x + PWINDOW->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x); const bool DISPLAYRIGHT = STICKS(PWINDOW->m_vPosition.x + PWINDOW->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
@@ -739,10 +729,6 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne
const auto WINDOWS = getNodesOnWorkspace(PNODE->workspaceID); const auto WINDOWS = getNodesOnWorkspace(PNODE->workspaceID);
const auto STACKWINDOWS = WINDOWS - MASTERS; const auto STACKWINDOWS = WINDOWS - MASTERS;
eOrientation orientation = getDynamicOrientation(PWINDOW->m_pWorkspace);
bool centered = orientation == ORIENTATION_CENTER && (STACKWINDOWS >= *SLAVECOUNTFORCENTER);
double delta = 0;
if (getNodesOnWorkspace(PWINDOW->workspaceID()) == 1 && !centered) if (getNodesOnWorkspace(PWINDOW->workspaceID()) == 1 && !centered)
return; return;
@@ -755,7 +741,7 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne
case ORIENTATION_TOP: delta = pixResize.y / PMONITOR->vecSize.y; break; case ORIENTATION_TOP: delta = pixResize.y / PMONITOR->vecSize.y; break;
case ORIENTATION_CENTER: case ORIENTATION_CENTER:
delta = pixResize.x / PMONITOR->vecSize.x; delta = pixResize.x / PMONITOR->vecSize.x;
if (STACKWINDOWS >= *SLAVECOUNTFORCENTER) { if (WINDOWS > 2 || *ALWAYSCENTER) {
if (!NONE || !PNODE->isMaster) if (!NONE || !PNODE->isMaster)
delta *= 2; delta *= 2;
if ((!PNODE->isMaster && DISPLAYLEFT) || (PNODE->isMaster && LEFT && *PSMARTRESIZING)) if ((!PNODE->isMaster && DISPLAYLEFT) || (PNODE->isMaster && LEFT && *PSMARTRESIZING))
@@ -856,10 +842,10 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFul
// save position and size if floating // save position and size if floating
if (pWindow->m_bIsFloating && CURRENT_EFFECTIVE_MODE == FSMODE_NONE) { if (pWindow->m_bIsFloating && CURRENT_EFFECTIVE_MODE == FSMODE_NONE) {
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize->goal(); pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goal();
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition->goal(); pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goal();
pWindow->m_vPosition = pWindow->m_vRealPosition->goal(); pWindow->m_vPosition = pWindow->m_vRealPosition.goal();
pWindow->m_vSize = pWindow->m_vRealSize->goal(); pWindow->m_vSize = pWindow->m_vRealSize.goal();
} }
if (EFFECTIVE_MODE == FSMODE_NONE) { if (EFFECTIVE_MODE == FSMODE_NONE) {
@@ -869,8 +855,8 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFul
applyNodeDataToWindow(PNODE); applyNodeDataToWindow(PNODE);
else { else {
// get back its' dimensions from position and size // get back its' dimensions from position and size
*pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition; pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition;
*pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; pWindow->m_vRealSize = pWindow->m_vLastFloatingSize;
pWindow->unsetWindowData(PRIORITY_LAYOUT); pWindow->unsetWindowData(PRIORITY_LAYOUT);
pWindow->updateWindowData(); pWindow->updateWindowData();
@@ -878,8 +864,8 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFul
} else { } else {
// apply new pos and size being monitors' box // apply new pos and size being monitors' box
if (EFFECTIVE_MODE == FSMODE_FULLSCREEN) { if (EFFECTIVE_MODE == FSMODE_FULLSCREEN) {
*pWindow->m_vRealPosition = PMONITOR->vecPosition; pWindow->m_vRealPosition = PMONITOR->vecPosition;
*pWindow->m_vRealSize = PMONITOR->vecSize; pWindow->m_vRealSize = PMONITOR->vecSize;
} else { } else {
// This is a massive hack. // This is a massive hack.
// We make a fake "only" node and apply // We make a fake "only" node and apply
@@ -945,15 +931,6 @@ void CHyprMasterLayout::moveWindowTo(PHLWINDOW pWindow, const std::string& dir,
if (silent) if (silent)
g_pCompositor->focusWindow(PWINDOW2); g_pCompositor->focusWindow(PWINDOW2);
} }
pWindow->updateGroupOutputs();
if (!pWindow->m_sGroupData.pNextWindow.expired()) {
PHLWINDOW next = pWindow->m_sGroupData.pNextWindow.lock();
while (next != pWindow) {
next->updateToplevel();
next = next->m_sGroupData.pNextWindow.lock();
}
}
} }
void CHyprMasterLayout::switchWindows(PHLWINDOW pWindow, PHLWINDOW pWindow2) { void CHyprMasterLayout::switchWindows(PHLWINDOW pWindow, PHLWINDOW pWindow2) {
@@ -1001,7 +978,7 @@ void CHyprMasterLayout::alterSplitRatio(PHLWINDOW pWindow, float ratio, bool exa
recalculateMonitor(pWindow->monitorID()); recalculateMonitor(pWindow->monitorID());
} }
PHLWINDOW CHyprMasterLayout::getNextWindow(PHLWINDOW pWindow, bool next, bool loop) { PHLWINDOW CHyprMasterLayout::getNextWindow(PHLWINDOW pWindow, bool next) {
if (!isWindowTiled(pWindow)) if (!isWindowTiled(pWindow))
return nullptr; return nullptr;
@@ -1020,13 +997,6 @@ PHLWINDOW CHyprMasterLayout::getNextWindow(PHLWINDOW pWindow, bool next, bool lo
CANDIDATE = CANDIDATE =
std::find_if(nodes.begin(), nodes.end(), [&](const auto& other) { return other != *PNODE && ISMASTER != other.isMaster && other.workspaceID == PNODE->workspaceID; }); std::find_if(nodes.begin(), nodes.end(), [&](const auto& other) { return other != *PNODE && ISMASTER != other.isMaster && other.workspaceID == PNODE->workspaceID; });
if (CANDIDATE != nodes.end() && !loop) {
if (CANDIDATE->isMaster && next)
return nullptr;
if (!CANDIDATE->isMaster && ISMASTER && !next)
return nullptr;
}
return CANDIDATE == nodes.end() ? nullptr : CANDIDATE->pWindow.lock(); return CANDIDATE == nodes.end() ? nullptr : CANDIDATE->pWindow.lock();
} }
@@ -1140,8 +1110,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
if (!PWINDOW) if (!PWINDOW)
return 0; return 0;
const bool NOLOOP = vars.size() >= 2 && vars[1] == "noloop"; const auto PNEXTWINDOW = getNextWindow(PWINDOW, true);
const auto PNEXTWINDOW = getNextWindow(PWINDOW, true, !NOLOOP);
switchToWindow(PNEXTWINDOW); switchToWindow(PNEXTWINDOW);
} else if (command == "cycleprev") { } else if (command == "cycleprev") {
const auto PWINDOW = header.pWindow; const auto PWINDOW = header.pWindow;
@@ -1149,8 +1118,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
if (!PWINDOW) if (!PWINDOW)
return 0; return 0;
const bool NOLOOP = vars.size() >= 2 && vars[1] == "noloop"; const auto PPREVWINDOW = getNextWindow(PWINDOW, false);
const auto PPREVWINDOW = getNextWindow(PWINDOW, false, !NOLOOP);
switchToWindow(PPREVWINDOW); switchToWindow(PPREVWINDOW);
} else if (command == "swapnext") { } else if (command == "swapnext") {
if (!validMapped(header.pWindow)) if (!validMapped(header.pWindow))
@@ -1161,8 +1129,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
return 0; return 0;
} }
const bool NOLOOP = vars.size() >= 2 && vars[1] == "noloop"; const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, true);
const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, true, !NOLOOP);
if (PWINDOWTOSWAPWITH) { if (PWINDOWTOSWAPWITH) {
g_pCompositor->setWindowFullscreenInternal(header.pWindow, FSMODE_NONE); g_pCompositor->setWindowFullscreenInternal(header.pWindow, FSMODE_NONE);
@@ -1178,8 +1145,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
return 0; return 0;
} }
const bool NOLOOP = vars.size() >= 2 && vars[1] == "noloop"; const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, false);
const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, false, !NOLOOP);
if (PWINDOWTOSWAPWITH) { if (PWINDOWTOSWAPWITH) {
g_pCompositor->setWindowFullscreenClient(header.pWindow, FSMODE_NONE); g_pCompositor->setWindowFullscreenClient(header.pWindow, FSMODE_NONE);

View File

@@ -2,7 +2,7 @@
#include "IHyprLayout.hpp" #include "IHyprLayout.hpp"
#include "../desktop/DesktopTypes.hpp" #include "../desktop/DesktopTypes.hpp"
#include "../helpers/varlist/VarList.hpp" #include "../config/ConfigManager.hpp"
#include <vector> #include <vector>
#include <list> #include <list>
#include <vector> #include <vector>
@@ -87,7 +87,7 @@ class CHyprMasterLayout : public IHyprLayout {
SMasterNodeData* getMasterNodeOnWorkspace(const WORKSPACEID&); SMasterNodeData* getMasterNodeOnWorkspace(const WORKSPACEID&);
SMasterWorkspaceData* getMasterWorkspaceData(const WORKSPACEID&); SMasterWorkspaceData* getMasterWorkspaceData(const WORKSPACEID&);
void calculateWorkspace(PHLWORKSPACE); void calculateWorkspace(PHLWORKSPACE);
PHLWINDOW getNextWindow(PHLWINDOW, bool, bool); PHLWINDOW getNextWindow(PHLWINDOW, bool);
int getMastersOnWorkspace(const WORKSPACEID&); int getMastersOnWorkspace(const WORKSPACEID&);
friend struct SMasterNodeData; friend struct SMasterNodeData;

View File

@@ -2,11 +2,9 @@
#include <cmath> #include <cmath>
#include <csignal> #include <csignal>
#include <print>
#include <utility> #include <utility>
#include "helpers/memory/Memory.hpp" #include "helpers/memory/Memory.hpp"
#include "debug/Log.hpp"
#ifndef NDEBUG #ifndef NDEBUG
#ifdef HYPRLAND_DEBUG #ifdef HYPRLAND_DEBUG
@@ -51,7 +49,7 @@
Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n{}\n\nat: line {} in {}", \ Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n{}\n\nat: line {} in {}", \
std::format(reason, ##__VA_ARGS__), __LINE__, \ std::format(reason, ##__VA_ARGS__), __LINE__, \
([]() constexpr -> std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })()); \ ([]() constexpr -> std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })()); \
std::print("Assertion failed! See the log in /tmp/hypr/hyprland.log for more info."); \ printf("Assertion failed! See the log in /tmp/hypr/hyprland.log for more info."); \
raise(SIGABRT); \ raise(SIGABRT); \
} }
@@ -114,6 +112,3 @@
namespace Aquamarine { \ namespace Aquamarine { \
class name; \ class name; \
} }
#define UNLIKELY(expr) (expr) [[unlikely]]
#define LIKELY(expr) (expr) [[likely]]

View File

@@ -18,7 +18,7 @@ using namespace Hyprutils::String;
#include <string> #include <string>
#include <filesystem> #include <filesystem>
static void help() { void help() {
std::println("usage: Hyprland [arg [...]].\n"); std::println("usage: Hyprland [arg [...]].\n");
std::println(R"(Arguments: std::println(R"(Arguments:
--help -h - Show this message again --help -h - Show this message again
@@ -27,7 +27,6 @@ static void help() {
--wayland-fd FD - Sets the Wayland socket fd (for Wayland socket handover) --wayland-fd FD - Sets the Wayland socket fd (for Wayland socket handover)
--systeminfo - Prints system infos --systeminfo - Prints system infos
--i-am-really-stupid - Omits root user privileges check (why would you do that?) --i-am-really-stupid - Omits root user privileges check (why would you do that?)
--verify-config - Do not run Hyprland, only print if the config has any errors
--version -v - Print this binary's version)"); --version -v - Print this binary's version)");
} }
@@ -50,7 +49,7 @@ int main(int argc, char** argv) {
std::string configPath; std::string configPath;
std::string socketName; std::string socketName;
int socketFd = -1; int socketFd = -1;
bool ignoreSudo = false, verifyConfig = false; bool ignoreSudo = false;
std::vector<std::string> args{argv + 1, argv + argc}; std::vector<std::string> args{argv + 1, argv + argc};
@@ -125,9 +124,6 @@ int main(int argc, char** argv) {
} else if (*it == "--systeminfo") { } else if (*it == "--systeminfo") {
std::println("{}", systemInfoRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, "")); std::println("{}", systemInfoRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, ""));
return 0; return 0;
} else if (*it == "--verify-config") {
verifyConfig = true;
continue;
} else { } else {
std::println(stderr, "[ ERROR ] Unknown option '{}' !", *it); std::println(stderr, "[ ERROR ] Unknown option '{}' !", *it);
help(); help();
@@ -142,8 +138,9 @@ int main(int argc, char** argv) {
" Hint: Use the --i-am-really-stupid flag to omit that check."); " Hint: Use the --i-am-really-stupid flag to omit that check.");
return 1; return 1;
} else if (ignoreSudo && NInit::isSudo()) } else if (ignoreSudo && NInit::isSudo()) {
std::println("Superuser privileges check is omitted. I hope you know what you're doing."); std::println("Superuser privileges check is omitted. I hope you know what you're doing.");
}
if (socketName.empty() ^ (socketFd == -1)) { if (socketName.empty() ^ (socketFd == -1)) {
std::println(stderr, std::println(stderr,
@@ -153,13 +150,12 @@ int main(int argc, char** argv) {
return 1; return 1;
} }
if (!verifyConfig) std::println("Welcome to Hyprland!");
std::println("Welcome to Hyprland!");
// let's init the compositor. // let's init the compositor.
// it initializes basic Wayland stuff in the constructor. // it initializes basic Wayland stuff in the constructor.
try { try {
g_pCompositor = makeUnique<CCompositor>(verifyConfig); g_pCompositor = std::make_unique<CCompositor>();
g_pCompositor->explicitConfigPath = configPath; g_pCompositor->explicitConfigPath = configPath;
} catch (const std::exception& e) { } catch (const std::exception& e) {
std::println(stderr, "Hyprland threw in ctor: {}\nCannot continue.", e.what()); std::println(stderr, "Hyprland threw in ctor: {}\nCannot continue.", e.what());
@@ -168,9 +164,6 @@ int main(int argc, char** argv) {
g_pCompositor->initServer(socketName, socketFd); g_pCompositor->initServer(socketName, socketFd);
if (verifyConfig)
return !g_pConfigManager->m_bLastConfigVerificationWasSuccessful;
if (!envEnabled("HYPRLAND_NO_RT")) if (!envEnabled("HYPRLAND_NO_RT"))
NInit::gainRealTime(); NInit::gainRealTime();
@@ -181,8 +174,6 @@ int main(int argc, char** argv) {
g_pCompositor->cleanup(); g_pCompositor->cleanup();
g_pCompositor.reset();
Debug::log(LOG, "Hyprland has reached the end."); Debug::log(LOG, "Hyprland has reached the end.");
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@@ -1,22 +1,16 @@
#include "AnimationManager.hpp" #include "AnimationManager.hpp"
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include "HookSystemManager.hpp" #include "HookSystemManager.hpp"
#include "../config/ConfigManager.hpp" #include "macros.hpp"
#include "../desktop/DesktopTypes.hpp"
#include "../helpers/AnimatedVariable.hpp"
#include "../macros.hpp"
#include "../config/ConfigValue.hpp" #include "../config/ConfigValue.hpp"
#include "../desktop/Window.hpp" #include "../desktop/Window.hpp"
#include "../desktop/LayerSurface.hpp" #include "../desktop/LayerSurface.hpp"
#include "eventLoop/EventLoopManager.hpp" #include "eventLoop/EventLoopManager.hpp"
#include "../helpers/varlist/VarList.hpp" #include "../helpers/varlist/VarList.hpp"
#include "../render/Renderer.hpp"
#include <hyprgraphics/color/Color.hpp> #include <hyprgraphics/color/Color.hpp>
#include <hyprutils/animation/AnimatedVariable.hpp>
#include <hyprutils/animation/AnimationManager.hpp>
static int wlTick(SP<CEventLoopTimer> self, void* data) { int wlTick(SP<CEventLoopTimer> self, void* data) {
if (g_pAnimationManager) if (g_pAnimationManager)
g_pAnimationManager->onTicked(); g_pAnimationManager->onTicked();
@@ -32,247 +26,318 @@ static int wlTick(SP<CEventLoopTimer> self, void* data) {
return 0; return 0;
} }
CHyprAnimationManager::CHyprAnimationManager() { CAnimationManager::CAnimationManager() {
std::vector<Vector2D> points = {Vector2D(0.0, 0.75), Vector2D(0.15, 1.0)};
m_mBezierCurves["default"].setup(&points);
m_pAnimationTimer = SP<CEventLoopTimer>(new CEventLoopTimer(std::chrono::microseconds(500), wlTick, nullptr)); m_pAnimationTimer = SP<CEventLoopTimer>(new CEventLoopTimer(std::chrono::microseconds(500), wlTick, nullptr));
if (g_pEventLoopManager) // null in --verify-config mode g_pEventLoopManager->addTimer(m_pAnimationTimer);
g_pEventLoopManager->addTimer(m_pAnimationTimer);
addBezierWithName("linear", Vector2D(0.0, 0.0), Vector2D(1.0, 1.0));
} }
template <Animable VarType> void CAnimationManager::removeAllBeziers() {
static void updateVariable(CAnimatedVariable<VarType>& av, const float POINTY, bool warp = false) { m_mBezierCurves.clear();
if (warp || av.value() == av.goal()) {
av.warp();
return;
}
const auto DELTA = av.goal() - av.begun(); // add the default one
av.value() = av.begun() + DELTA * POINTY; std::vector<Vector2D> points = {Vector2D(0.0, 0.75), Vector2D(0.15, 1.0)};
m_mBezierCurves["default"].setup(&points);
} }
static void updateColorVariable(CAnimatedVariable<CHyprColor>& av, const float POINTY, bool warp) { void CAnimationManager::addBezierWithName(std::string name, const Vector2D& p1, const Vector2D& p2) {
if (warp || av.value() == av.goal()) { std::vector points = {p1, p2};
av.warp(); m_mBezierCurves[name].setup(&points);
return;
}
// convert both to OkLab, then lerp that, and convert back.
// This is not as fast as just lerping rgb, but it's WAY more precise...
// Use the CHyprColor cache for OkLab
const auto& L1 = av.begun().asOkLab();
const auto& L2 = av.goal().asOkLab();
static const auto lerp = [](const float one, const float two, const float progress) -> float { return one + (two - one) * progress; };
const Hyprgraphics::CColor lerped = Hyprgraphics::CColor::SOkLab{
.l = lerp(L1.l, L2.l, POINTY),
.a = lerp(L1.a, L2.a, POINTY),
.b = lerp(L1.b, L2.b, POINTY),
};
av.value() = {lerped, lerp(av.begun().a, av.goal().a, POINTY)};
} }
template <Animable VarType> void CAnimationManager::onTicked() {
static void handleUpdate(CAnimatedVariable<VarType>& av, bool warp) { m_bTickScheduled = false;
PHLWINDOW PWINDOW = av.m_Context.pWindow.lock();
PHLWORKSPACE PWORKSPACE = av.m_Context.pWorkspace.lock();
PHLLS PLAYER = av.m_Context.pLayer.lock();
PHLMONITOR PMONITOR = nullptr;
bool animationsDisabled = warp;
if (PWINDOW) {
if (av.m_Context.eDamagePolicy == AVARDAMAGE_ENTIRE)
g_pHyprRenderer->damageWindow(PWINDOW);
else if (av.m_Context.eDamagePolicy == AVARDAMAGE_BORDER) {
const auto PDECO = PWINDOW->getDecorationByType(DECORATION_BORDER);
PDECO->damageEntire();
} else if (av.m_Context.eDamagePolicy == AVARDAMAGE_SHADOW) {
const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW);
PDECO->damageEntire();
}
PMONITOR = PWINDOW->m_pMonitor.lock();
if (!PMONITOR)
return;
animationsDisabled = PWINDOW->m_sWindowData.noAnim.valueOr(animationsDisabled);
} else if (PWORKSPACE) {
PMONITOR = PWORKSPACE->m_pMonitor.lock();
if (!PMONITOR)
return;
// dont damage the whole monitor on workspace change, unless it's a special workspace, because dim/blur etc
if (PWORKSPACE->m_bIsSpecialWorkspace)
g_pHyprRenderer->damageMonitor(PMONITOR);
// TODO: just make this into a damn callback already vax...
for (auto const& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped || w->isHidden() || w->m_pWorkspace != PWORKSPACE)
continue;
if (w->m_bIsFloating && !w->m_bPinned) {
// still doing the full damage hack for floating because sometimes when the window
// goes through multiple monitors the last rendered frame is missing damage somehow??
const CBox windowBoxNoOffset = w->getFullWindowBoundingBox();
const CBox monitorBox = {PMONITOR->vecPosition, PMONITOR->vecSize};
if (windowBoxNoOffset.intersection(monitorBox) != windowBoxNoOffset) // on edges between multiple monitors
g_pHyprRenderer->damageWindow(w, true);
}
if (PWORKSPACE->m_bIsSpecialWorkspace)
g_pHyprRenderer->damageWindow(w, true); // hack for special too because it can cross multiple monitors
}
// damage any workspace window that is on any monitor
for (auto const& w : g_pCompositor->m_vWindows) {
if (!validMapped(w) || w->m_pWorkspace != PWORKSPACE || w->m_bPinned)
continue;
g_pHyprRenderer->damageWindow(w);
}
} else if (PLAYER) {
// "some fucking layers miss 1 pixel???" -- vaxry
CBox expandBox = CBox{PLAYER->realPosition->value(), PLAYER->realSize->value()};
expandBox.expand(5);
g_pHyprRenderer->damageBox(expandBox);
PMONITOR = g_pCompositor->getMonitorFromVector(PLAYER->realPosition->goal() + PLAYER->realSize->goal() / 2.F);
if (!PMONITOR)
return;
animationsDisabled = animationsDisabled || PLAYER->noAnimations;
}
const auto SPENT = av.getPercent();
const auto PBEZIER = g_pAnimationManager->getBezier(av.getBezierName());
const auto POINTY = PBEZIER->getYForPoint(SPENT);
const bool WARP = animationsDisabled || SPENT >= 1.f;
if constexpr (std::same_as<VarType, CHyprColor>)
updateColorVariable(av, POINTY, WARP);
else
updateVariable<VarType>(av, POINTY, WARP);
av.onUpdate();
switch (av.m_Context.eDamagePolicy) {
case AVARDAMAGE_ENTIRE: {
if (PWINDOW) {
PWINDOW->updateWindowDecos();
g_pHyprRenderer->damageWindow(PWINDOW);
} else if (PWORKSPACE) {
for (auto const& w : g_pCompositor->m_vWindows) {
if (!validMapped(w) || w->m_pWorkspace != PWORKSPACE)
continue;
w->updateWindowDecos();
// damage any workspace window that is on any monitor
if (!w->m_bPinned)
g_pHyprRenderer->damageWindow(w);
}
} else if (PLAYER) {
if (PLAYER->layer <= 1)
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR);
// some fucking layers miss 1 pixel???
CBox expandBox = CBox{PLAYER->realPosition->value(), PLAYER->realSize->value()};
expandBox.expand(5);
g_pHyprRenderer->damageBox(expandBox);
}
break;
}
case AVARDAMAGE_BORDER: {
RASSERT(PWINDOW, "Tried to AVARDAMAGE_BORDER a non-window AVAR!");
const auto PDECO = PWINDOW->getDecorationByType(DECORATION_BORDER);
PDECO->damageEntire();
break;
}
case AVARDAMAGE_SHADOW: {
RASSERT(PWINDOW, "Tried to AVARDAMAGE_SHADOW a non-window AVAR!");
const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW);
PDECO->damageEntire();
break;
}
default: {
break;
}
}
// manually schedule a frame
if (PMONITOR)
g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_ANIMATION);
} }
void CHyprAnimationManager::tick() { void CAnimationManager::tick() {
static std::chrono::time_point lastTick = std::chrono::high_resolution_clock::now(); static std::chrono::time_point lastTick = std::chrono::high_resolution_clock::now();
m_fLastTickTime = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - lastTick).count() / 1000.0; m_fLastTickTime = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - lastTick).count() / 1000.0;
lastTick = std::chrono::high_resolution_clock::now(); lastTick = std::chrono::high_resolution_clock::now();
if (m_vActiveAnimatedVariables.empty())
return;
bool animGlobalDisabled = false;
static auto PANIMENABLED = CConfigValue<Hyprlang::INT>("animations:enabled"); static auto PANIMENABLED = CConfigValue<Hyprlang::INT>("animations:enabled");
for (size_t i = 0; i < m_vActiveAnimatedVariables.size(); i++) { if (!*PANIMENABLED)
const auto PAV = m_vActiveAnimatedVariables[i].lock(); animGlobalDisabled = true;
if (!PAV)
static auto* const PSHADOWSENABLED = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("decoration:shadow:enabled");
const auto DEFAULTBEZIER = m_mBezierCurves.find("default");
std::vector<CBaseAnimatedVariable*> animationEndedVars;
for (auto const& av : m_vActiveAnimatedVariables) {
if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW && !*PSHADOWSENABLED) {
av->warp(false);
animationEndedVars.push_back(av);
continue; continue;
}
// for disabled anims just warp // get the spent % (0 - 1)
bool warp = !*PANIMENABLED || !PAV->enabled(); const float SPENT = av->getPercent();
switch (PAV->m_Type) { // window stuff
PHLWINDOW PWINDOW = av->m_pWindow.lock();
PHLWORKSPACE PWORKSPACE = av->m_pWorkspace.lock();
PHLLS PLAYER = av->m_pLayer.lock();
PHLMONITOR PMONITOR = nullptr;
bool animationsDisabled = animGlobalDisabled;
if (PWINDOW) {
if (av->m_eDamagePolicy == AVARDAMAGE_ENTIRE) {
g_pHyprRenderer->damageWindow(PWINDOW);
} else if (av->m_eDamagePolicy == AVARDAMAGE_BORDER) {
const auto PDECO = PWINDOW->getDecorationByType(DECORATION_BORDER);
PDECO->damageEntire();
} else if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW) {
const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW);
PDECO->damageEntire();
}
PMONITOR = PWINDOW->m_pMonitor.lock();
if (!PMONITOR)
continue;
animationsDisabled = PWINDOW->m_sWindowData.noAnim.valueOr(animationsDisabled);
} else if (PWORKSPACE) {
PMONITOR = PWORKSPACE->m_pMonitor.lock();
if (!PMONITOR)
continue;
// dont damage the whole monitor on workspace change, unless it's a special workspace, because dim/blur etc
if (PWORKSPACE->m_bIsSpecialWorkspace)
g_pHyprRenderer->damageMonitor(PMONITOR);
// TODO: just make this into a damn callback already vax...
for (auto const& w : g_pCompositor->m_vWindows) {
if (!w->m_bIsMapped || w->isHidden() || w->m_pWorkspace != PWORKSPACE)
continue;
if (w->m_bIsFloating && !w->m_bPinned) {
// still doing the full damage hack for floating because sometimes when the window
// goes through multiple monitors the last rendered frame is missing damage somehow??
const CBox windowBoxNoOffset = w->getFullWindowBoundingBox();
const CBox monitorBox = {PMONITOR->vecPosition, PMONITOR->vecSize};
if (windowBoxNoOffset.intersection(monitorBox) != windowBoxNoOffset) // on edges between multiple monitors
g_pHyprRenderer->damageWindow(w, true);
}
if (PWORKSPACE->m_bIsSpecialWorkspace)
g_pHyprRenderer->damageWindow(w, true); // hack for special too because it can cross multiple monitors
}
// damage any workspace window that is on any monitor
for (auto const& w : g_pCompositor->m_vWindows) {
if (!validMapped(w) || w->m_pWorkspace != PWORKSPACE || w->m_bPinned)
continue;
g_pHyprRenderer->damageWindow(w);
}
} else if (PLAYER) {
// "some fucking layers miss 1 pixel???" -- vaxry
CBox expandBox = CBox{PLAYER->realPosition.value(), PLAYER->realSize.value()};
expandBox.expand(5);
g_pHyprRenderer->damageBox(&expandBox);
PMONITOR = g_pCompositor->getMonitorFromVector(PLAYER->realPosition.goal() + PLAYER->realSize.goal() / 2.F);
if (!PMONITOR)
continue;
animationsDisabled = animationsDisabled || PLAYER->noAnimations;
}
const bool VISIBLE = PWINDOW && PWINDOW->m_pWorkspace ? PWINDOW->m_pWorkspace->isVisible() : true;
// beziers are with a switch unforto
// TODO: maybe do something cleaner
static const auto updateVariable = [this]<Animable T>(CAnimatedVariable<T>& av, const float SPENT, const CBezierCurve& DEFAULTBEZIER, const bool DISABLED) {
// for disabled anims just warp
if (av.m_pConfig->pValues->internalEnabled == 0 || DISABLED) {
av.warp(false);
return;
}
if (SPENT >= 1.f || av.m_Begun == av.m_Goal) {
av.warp(false);
return;
}
const auto BEZIER = m_mBezierCurves.find(av.m_pConfig->pValues->internalBezier);
const auto POINTY = BEZIER != m_mBezierCurves.end() ? BEZIER->second.getYForPoint(SPENT) : DEFAULTBEZIER.getYForPoint(SPENT);
const auto DELTA = av.m_Goal - av.m_Begun;
if (BEZIER != m_mBezierCurves.end())
av.m_Value = av.m_Begun + DELTA * POINTY;
else
av.m_Value = av.m_Begun + DELTA * POINTY;
};
static const auto updateColorVariable = [this](CAnimatedVariable<CHyprColor>& av, const float SPENT, const CBezierCurve& DEFAULTBEZIER, const bool DISABLED) {
// for disabled anims just warp
if (av.m_pConfig->pValues->internalEnabled == 0 || DISABLED) {
av.warp(false);
return;
}
if (SPENT >= 1.f || av.m_Begun == av.m_Goal) {
av.warp(false);
return;
}
const auto BEZIER = m_mBezierCurves.find(av.m_pConfig->pValues->internalBezier);
const auto POINTY = BEZIER != m_mBezierCurves.end() ? BEZIER->second.getYForPoint(SPENT) : DEFAULTBEZIER.getYForPoint(SPENT);
// convert both to OkLab, then lerp that, and convert back.
// This is not as fast as just lerping rgb, but it's WAY more precise...
// Use the CHyprColor cache for OkLab
const auto& L1 = av.m_Begun.asOkLab();
const auto& L2 = av.m_Goal.asOkLab();
static const auto lerp = [](const float one, const float two, const float progress) -> float { return one + (two - one) * progress; };
const Hyprgraphics::CColor lerped = Hyprgraphics::CColor::SOkLab{
.l = lerp(L1.l, L2.l, POINTY),
.a = lerp(L1.a, L2.a, POINTY),
.b = lerp(L1.b, L2.b, POINTY),
};
av.m_Value = {lerped, lerp(av.m_Begun.a, av.m_Goal.a, POINTY)};
return;
};
switch (av->m_Type) {
case AVARTYPE_FLOAT: { case AVARTYPE_FLOAT: {
auto pTypedAV = dynamic_cast<CAnimatedVariable<float>*>(PAV.get()); auto typedAv = dynamic_cast<CAnimatedVariable<float>*>(av);
RASSERT(pTypedAV, "Failed to upcast animated float"); updateVariable(*typedAv, SPENT, DEFAULTBEZIER->second, animationsDisabled);
handleUpdate(*pTypedAV, warp); break;
} break; }
case AVARTYPE_VECTOR: { case AVARTYPE_VECTOR: {
auto pTypedAV = dynamic_cast<CAnimatedVariable<Vector2D>*>(PAV.get()); auto typedAv = dynamic_cast<CAnimatedVariable<Vector2D>*>(av);
RASSERT(pTypedAV, "Failed to upcast animated Vector2D"); updateVariable(*typedAv, SPENT, DEFAULTBEZIER->second, animationsDisabled);
handleUpdate(*pTypedAV, warp); break;
} break; }
case AVARTYPE_COLOR: { case AVARTYPE_COLOR: {
auto pTypedAV = dynamic_cast<CAnimatedVariable<CHyprColor>*>(PAV.get()); auto typedAv = dynamic_cast<CAnimatedVariable<CHyprColor>*>(av);
RASSERT(pTypedAV, "Failed to upcast animated CHyprColor"); updateColorVariable(*typedAv, SPENT, DEFAULTBEZIER->second, animationsDisabled);
handleUpdate(*pTypedAV, warp); break;
} break; }
default: UNREACHABLE(); default: UNREACHABLE();
} }
// set size and pos if valid, but only if damage policy entire (dont if border for example)
if (validMapped(PWINDOW) && av->m_eDamagePolicy == AVARDAMAGE_ENTIRE && !PWINDOW->isX11OverrideRedirect())
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal());
// check if we did not finish animating. If so, trigger onAnimationEnd.
if (!av->isBeingAnimated())
animationEndedVars.push_back(av);
// lastly, handle damage, but only if whatever we are animating is visible.
if (!VISIBLE)
continue;
if (av->m_fUpdateCallback)
av->m_fUpdateCallback(av);
switch (av->m_eDamagePolicy) {
case AVARDAMAGE_ENTIRE: {
if (PWINDOW) {
PWINDOW->updateWindowDecos();
g_pHyprRenderer->damageWindow(PWINDOW);
} else if (PWORKSPACE) {
for (auto const& w : g_pCompositor->m_vWindows) {
if (!validMapped(w) || w->m_pWorkspace != PWORKSPACE)
continue;
w->updateWindowDecos();
// damage any workspace window that is on any monitor
if (!w->m_bPinned)
g_pHyprRenderer->damageWindow(w);
}
} else if (PLAYER) {
if (PLAYER->layer <= 1)
g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR);
// some fucking layers miss 1 pixel???
CBox expandBox = CBox{PLAYER->realPosition.value(), PLAYER->realSize.value()};
expandBox.expand(5);
g_pHyprRenderer->damageBox(&expandBox);
}
break;
}
case AVARDAMAGE_BORDER: {
RASSERT(PWINDOW, "Tried to AVARDAMAGE_BORDER a non-window AVAR!");
const auto PDECO = PWINDOW->getDecorationByType(DECORATION_BORDER);
PDECO->damageEntire();
break;
}
case AVARDAMAGE_SHADOW: {
RASSERT(PWINDOW, "Tried to AVARDAMAGE_SHADOW a non-window AVAR!");
const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW);
PDECO->damageEntire();
break;
}
default: {
break;
}
}
// manually schedule a frame
if (PMONITOR)
g_pCompositor->scheduleFrameForMonitor(PMONITOR, Aquamarine::IOutput::AQ_SCHEDULE_ANIMATION);
} }
tickDone(); // do it here, because if this alters the animation vars vec we would be in trouble above.
for (auto const& ave : animationEndedVars) {
ave->onAnimationEnd();
}
} }
void CHyprAnimationManager::scheduleTick() { bool CAnimationManager::deltaSmallToFlip(const Vector2D& a, const Vector2D& b) {
if (m_bTickScheduled) return std::abs(a.x - b.x) < 0.5f && std::abs(a.y - b.y) < 0.5f;
return; }
m_bTickScheduled = true; bool CAnimationManager::deltaSmallToFlip(const CHyprColor& a, const CHyprColor& b) {
return std::abs(a.r - b.r) < 0.5f && std::abs(a.g - b.g) < 0.5f && std::abs(a.b - b.b) < 0.5f && std::abs(a.a - b.a) < 0.5f;
}
const auto PMOSTHZ = g_pHyprRenderer->m_pMostHzMonitor; bool CAnimationManager::deltaSmallToFlip(const float& a, const float& b) {
return std::abs(a - b) < 0.5f;
}
if (!PMOSTHZ) { bool CAnimationManager::deltazero(const Vector2D& a, const Vector2D& b) {
m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(16)); return a.x == b.x && a.y == b.y;
return; }
bool CAnimationManager::deltazero(const float& a, const float& b) {
return a == b;
}
bool CAnimationManager::deltazero(const CHyprColor& a, const CHyprColor& b) {
return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a;
}
bool CAnimationManager::bezierExists(const std::string& bezier) {
for (auto const& [bc, bz] : m_mBezierCurves) {
if (bc == bezier)
return true;
} }
float refreshDelayMs = std::floor(1000.f / PMOSTHZ->refreshRate); return false;
const float SINCEPRES = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - PMOSTHZ->lastPresentationTimer.chrono()).count() / 1000.f;
const auto TOPRES = std::clamp(refreshDelayMs - SINCEPRES, 1.1f, 1000.f); // we can't send 0, that will disarm it
m_pAnimationTimer->updateTimeout(std::chrono::milliseconds((int)std::floor(TOPRES)));
}
void CHyprAnimationManager::onTicked() {
m_bTickScheduled = false;
} }
// //
@@ -280,24 +345,24 @@ void CHyprAnimationManager::onTicked() {
// //
// //
void CHyprAnimationManager::animationPopin(PHLWINDOW pWindow, bool close, float minPerc) { void CAnimationManager::animationPopin(PHLWINDOW pWindow, bool close, float minPerc) {
const auto GOALPOS = pWindow->m_vRealPosition->goal(); const auto GOALPOS = pWindow->m_vRealPosition.goal();
const auto GOALSIZE = pWindow->m_vRealSize->goal(); const auto GOALSIZE = pWindow->m_vRealSize.goal();
if (!close) { if (!close) {
pWindow->m_vRealSize->setValue((GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y})); pWindow->m_vRealSize.setValue((GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y}));
pWindow->m_vRealPosition->setValue(GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize->value() / 2.f); pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize.m_Value / 2.f);
} else { } else {
*pWindow->m_vRealSize = (GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y}); pWindow->m_vRealSize = (GOALSIZE * minPerc).clamp({5, 5}, {GOALSIZE.x, GOALSIZE.y});
*pWindow->m_vRealPosition = GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize->goal() / 2.f; pWindow->m_vRealPosition = GOALPOS + GOALSIZE / 2.f - pWindow->m_vRealSize.m_Goal / 2.f;
} }
} }
void CHyprAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, bool close) { void CAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force, bool close) {
pWindow->m_vRealSize->warp(false); // size we preserve in slide pWindow->m_vRealSize.warp(false); // size we preserve in slide
const auto GOALPOS = pWindow->m_vRealPosition->goal(); const auto GOALPOS = pWindow->m_vRealPosition.goal();
const auto GOALSIZE = pWindow->m_vRealSize->goal(); const auto GOALSIZE = pWindow->m_vRealSize.goal();
const auto PMONITOR = pWindow->m_pMonitor.lock(); const auto PMONITOR = pWindow->m_pMonitor.lock();
@@ -317,9 +382,9 @@ void CHyprAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force,
posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y); posOffset = Vector2D(GOALPOS.x, PMONITOR->vecPosition.y - GOALSIZE.y);
if (!close) if (!close)
pWindow->m_vRealPosition->setValue(posOffset); pWindow->m_vRealPosition.setValue(posOffset);
else else
*pWindow->m_vRealPosition = posOffset; pWindow->m_vRealPosition = posOffset;
return; return;
} }
@@ -352,33 +417,33 @@ void CHyprAnimationManager::animationSlide(PHLWINDOW pWindow, std::string force,
} }
if (!close) if (!close)
pWindow->m_vRealPosition->setValue(posOffset); pWindow->m_vRealPosition.setValue(posOffset);
else else
*pWindow->m_vRealPosition = posOffset; pWindow->m_vRealPosition = posOffset;
} }
void CHyprAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) { void CAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool close) {
if (!close) { if (!close) {
pWindow->m_vRealPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsIn")); pWindow->m_vRealPosition.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsIn");
pWindow->m_vRealSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsIn")); pWindow->m_vRealSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsIn");
pWindow->m_fAlpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeIn")); pWindow->m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeIn");
} else { } else {
pWindow->m_vRealPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsOut")); pWindow->m_vRealPosition.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsOut");
pWindow->m_vRealSize->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsOut")); pWindow->m_vRealSize.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("windowsOut");
pWindow->m_fAlpha->setConfig(g_pConfigManager->getAnimationPropertyConfig("fadeOut")); pWindow->m_fAlpha.m_pConfig = g_pConfigManager->getAnimationPropertyConfig("fadeOut");
} }
std::string ANIMSTYLE = pWindow->m_vRealPosition->getStyle(); auto ANIMSTYLE = pWindow->m_vRealPosition.m_pConfig->pValues->internalStyle;
transform(ANIMSTYLE.begin(), ANIMSTYLE.end(), ANIMSTYLE.begin(), ::tolower); transform(ANIMSTYLE.begin(), ANIMSTYLE.end(), ANIMSTYLE.begin(), ::tolower);
CVarList animList(ANIMSTYLE, 0, 's'); CVarList animList(ANIMSTYLE, 0, 's');
// if the window is not being animated, that means the layout set a fixed size for it, don't animate. // if the window is not being animated, that means the layout set a fixed size for it, don't animate.
if (!pWindow->m_vRealPosition->isBeingAnimated() && !pWindow->m_vRealSize->isBeingAnimated()) if (!pWindow->m_vRealPosition.isBeingAnimated() && !pWindow->m_vRealSize.isBeingAnimated())
return; return;
// if the animation is disabled and we are leaving, ignore the anim to prevent the snapshot being fucked // if the animation is disabled and we are leaving, ignore the anim to prevent the snapshot being fucked
if (!pWindow->m_vRealPosition->enabled()) if (!pWindow->m_vRealPosition.m_pConfig->pValues->internalEnabled)
return; return;
if (pWindow->m_sWindowData.animationStyle.hasValue()) { if (pWindow->m_sWindowData.animationStyle.hasValue()) {
@@ -423,7 +488,7 @@ void CHyprAnimationManager::onWindowPostCreateClose(PHLWINDOW pWindow, bool clos
} }
} }
std::string CHyprAnimationManager::styleValidInConfigVar(const std::string& config, const std::string& style) { std::string CAnimationManager::styleValidInConfigVar(const std::string& config, const std::string& style) {
if (config.starts_with("window")) { if (config.starts_with("window")) {
if (style.starts_with("slide")) if (style.starts_with("slide"))
return ""; return "";
@@ -497,3 +562,39 @@ std::string CHyprAnimationManager::styleValidInConfigVar(const std::string& conf
return ""; return "";
} }
CBezierCurve* CAnimationManager::getBezier(const std::string& name) {
const auto BEZIER = std::find_if(m_mBezierCurves.begin(), m_mBezierCurves.end(), [&](const auto& other) { return other.first == name; });
return BEZIER == m_mBezierCurves.end() ? &m_mBezierCurves["default"] : &BEZIER->second;
}
std::unordered_map<std::string, CBezierCurve> CAnimationManager::getAllBeziers() {
return m_mBezierCurves;
}
bool CAnimationManager::shouldTickForNext() {
return !m_vActiveAnimatedVariables.empty();
}
void CAnimationManager::scheduleTick() {
if (m_bTickScheduled)
return;
m_bTickScheduled = true;
const auto PMOSTHZ = g_pHyprRenderer->m_pMostHzMonitor;
if (!PMOSTHZ) {
m_pAnimationTimer->updateTimeout(std::chrono::milliseconds(16));
return;
}
float refreshDelayMs = std::floor(1000.f / PMOSTHZ->refreshRate);
const float SINCEPRES = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - PMOSTHZ->lastPresentationTimer.chrono()).count() / 1000.f;
const auto TOPRES = std::clamp(refreshDelayMs - SINCEPRES, 1.1f, 1000.f); // we can't send 0, that will disarm it
m_pAnimationTimer->updateTimeout(std::chrono::milliseconds((int)std::floor(TOPRES)));
}

View File

@@ -1,64 +1,57 @@
#pragma once #pragma once
#include <hyprutils/animation/AnimationManager.hpp>
#include <hyprutils/animation/AnimatedVariable.hpp>
#include "../defines.hpp" #include "../defines.hpp"
#include <list>
#include <unordered_map>
#include "../helpers/AnimatedVariable.hpp" #include "../helpers/AnimatedVariable.hpp"
#include "../desktop/DesktopTypes.hpp" #include "../helpers/BezierCurve.hpp"
#include "../helpers/Timer.hpp"
#include "eventLoop/EventLoopTimer.hpp" #include "eventLoop/EventLoopTimer.hpp"
class CHyprAnimationManager : public Hyprutils::Animation::CAnimationManager { class CWindow;
class CAnimationManager {
public: public:
CHyprAnimationManager(); CAnimationManager();
void tick(); void tick();
virtual void scheduleTick(); bool shouldTickForNext();
virtual void onTicked(); void onTicked();
void scheduleTick();
void addBezierWithName(std::string, const Vector2D&, const Vector2D&);
void removeAllBeziers();
using SAnimationPropertyConfig = Hyprutils::Animation::SAnimationPropertyConfig; void onWindowPostCreateClose(PHLWINDOW, bool close = false);
template <Animable VarType>
void createAnimation(const VarType& v, PHLANIMVAR<VarType>& pav, SP<SAnimationPropertyConfig> pConfig, eAVarDamagePolicy policy) {
constexpr const eAnimatedVarType EAVTYPE = typeToeAnimatedVarType<VarType>;
const auto PAV = makeShared<CAnimatedVariable<VarType>>();
PAV->create(EAVTYPE, static_cast<Hyprutils::Animation::CAnimationManager*>(this), PAV, v); bool bezierExists(const std::string&);
PAV->setConfig(pConfig); CBezierCurve* getBezier(const std::string&);
PAV->m_Context.eDamagePolicy = policy;
pav = std::move(PAV); std::string styleValidInConfigVar(const std::string&, const std::string&);
}
template <Animable VarType> std::unordered_map<std::string, CBezierCurve> getAllBeziers();
void createAnimation(const VarType& v, PHLANIMVAR<VarType>& pav, SP<SAnimationPropertyConfig> pConfig, PHLWINDOW pWindow, eAVarDamagePolicy policy) {
createAnimation(v, pav, pConfig, policy);
pav->m_Context.pWindow = pWindow;
}
template <Animable VarType>
void createAnimation(const VarType& v, PHLANIMVAR<VarType>& pav, SP<SAnimationPropertyConfig> pConfig, PHLWORKSPACE pWorkspace, eAVarDamagePolicy policy) {
createAnimation(v, pav, pConfig, policy);
pav->m_Context.pWorkspace = pWorkspace;
}
template <Animable VarType>
void createAnimation(const VarType& v, PHLANIMVAR<VarType>& pav, SP<SAnimationPropertyConfig> pConfig, PHLLS pLayer, eAVarDamagePolicy policy) {
createAnimation(v, pav, pConfig, policy);
pav->m_Context.pLayer = pLayer;
}
void onWindowPostCreateClose(PHLWINDOW, bool close = false); std::vector<CBaseAnimatedVariable*> m_vAnimatedVariables;
std::vector<CBaseAnimatedVariable*> m_vActiveAnimatedVariables;
std::string styleValidInConfigVar(const std::string&, const std::string&); SP<CEventLoopTimer> m_pAnimationTimer;
SP<CEventLoopTimer> m_pAnimationTimer; float m_fLastTickTime; // in ms
float m_fLastTickTime; // in ms
private: private:
bool m_bTickScheduled = false; bool deltaSmallToFlip(const Vector2D& a, const Vector2D& b);
bool deltaSmallToFlip(const CHyprColor& a, const CHyprColor& b);
bool deltaSmallToFlip(const float& a, const float& b);
bool deltazero(const Vector2D& a, const Vector2D& b);
bool deltazero(const CHyprColor& a, const CHyprColor& b);
bool deltazero(const float& a, const float& b);
std::unordered_map<std::string, CBezierCurve> m_mBezierCurves;
bool m_bTickScheduled = false;
// Anim stuff // Anim stuff
void animationPopin(PHLWINDOW, bool close = false, float minPerc = 0.f); void animationPopin(PHLWINDOW, bool close = false, float minPerc = 0.f);
void animationSlide(PHLWINDOW, std::string force = "", bool close = false); void animationSlide(PHLWINDOW, std::string force = "", bool close = false);
}; };
inline UP<CHyprAnimationManager> g_pAnimationManager; inline std::unique_ptr<CAnimationManager> g_pAnimationManager;

View File

@@ -3,7 +3,6 @@
#include "../config/ConfigValue.hpp" #include "../config/ConfigValue.hpp"
#include "PointerManager.hpp" #include "PointerManager.hpp"
#include "../xwayland/XWayland.hpp" #include "../xwayland/XWayland.hpp"
#include "../managers/HookSystemManager.hpp"
static int cursorAnimTimer(SP<CEventLoopTimer> self, void* data) { static int cursorAnimTimer(SP<CEventLoopTimer> self, void* data) {
const auto cursorMgr = reinterpret_cast<CCursorManager*>(data); const auto cursorMgr = reinterpret_cast<CCursorManager*>(data);
@@ -64,8 +63,8 @@ void CCursorBuffer::endDataPtr() {
} }
CCursorManager::CCursorManager() { CCursorManager::CCursorManager() {
m_pHyprcursor = makeUnique<Hyprcursor::CHyprcursorManager>(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), hcLogger); m_pHyprcursor = std::make_unique<Hyprcursor::CHyprcursorManager>(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), hcLogger);
m_pXcursor = makeUnique<CXCursorManager>(); m_pXcursor = std::make_unique<CXCursorManager>();
static auto PUSEHYPRCURSOR = CConfigValue<Hyprlang::INT>("cursor:enable_hyprcursor"); static auto PUSEHYPRCURSOR = CConfigValue<Hyprlang::INT>("cursor:enable_hyprcursor");
if (m_pHyprcursor->valid() && *PUSEHYPRCURSOR) { if (m_pHyprcursor->valid() && *PUSEHYPRCURSOR) {
@@ -323,7 +322,7 @@ bool CCursorManager::changeTheme(const std::string& name, const int size) {
m_szTheme = name.empty() ? "" : name; m_szTheme = name.empty() ? "" : name;
m_iSize = size; m_iSize = size;
m_pHyprcursor = makeUnique<Hyprcursor::CHyprcursorManager>(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), options); m_pHyprcursor = std::make_unique<Hyprcursor::CHyprcursorManager>(m_szTheme.empty() ? nullptr : m_szTheme.c_str(), options);
if (!m_pHyprcursor->valid()) { if (!m_pHyprcursor->valid()) {
Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to XCursor.", m_szTheme); Debug::log(ERR, "Hyprcursor failed loading theme \"{}\", falling back to XCursor.", m_szTheme);
m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize, m_fCursorScale); m_pXcursor->loadTheme(m_szTheme.empty() ? xcursor_theme : m_szTheme, m_iSize, m_fCursorScale);

View File

@@ -2,6 +2,7 @@
#include <string> #include <string>
#include <hyprcursor/hyprcursor.hpp> #include <hyprcursor/hyprcursor.hpp>
#include <memory>
#include "../includes.hpp" #include "../includes.hpp"
#include "../helpers/math/Math.hpp" #include "../helpers/math/Math.hpp"
#include "../helpers/memory/Memory.hpp" #include "../helpers/memory/Memory.hpp"
@@ -57,22 +58,22 @@ class CCursorManager {
void tickAnimatedCursor(); void tickAnimatedCursor();
private: private:
bool m_bOurBufferConnected = false; bool m_bOurBufferConnected = false;
std::vector<SP<CCursorBuffer>> m_vCursorBuffers; std::vector<SP<CCursorBuffer>> m_vCursorBuffers;
UP<Hyprcursor::CHyprcursorManager> m_pHyprcursor; std::unique_ptr<Hyprcursor::CHyprcursorManager> m_pHyprcursor;
UP<CXCursorManager> m_pXcursor; std::unique_ptr<CXCursorManager> m_pXcursor;
SP<SXCursors> m_currentXcursor; SP<SXCursors> m_currentXcursor;
std::string m_szTheme = ""; std::string m_szTheme = "";
int m_iSize = 0; int m_iSize = 0;
float m_fCursorScale = 1.0; float m_fCursorScale = 1.0;
Hyprcursor::SCursorStyleInfo m_sCurrentStyleInfo; Hyprcursor::SCursorStyleInfo m_sCurrentStyleInfo;
SP<CEventLoopTimer> m_pAnimationTimer; SP<CEventLoopTimer> m_pAnimationTimer;
int m_iCurrentAnimationFrame = 0; int m_iCurrentAnimationFrame = 0;
Hyprcursor::SCursorShapeData m_sCurrentCursorShapeData; Hyprcursor::SCursorShapeData m_sCurrentCursorShapeData;
}; };
inline UP<CCursorManager> g_pCursorManager; inline std::unique_ptr<CCursorManager> g_pCursorManager;

View File

@@ -1,114 +0,0 @@
#include "DonationNagManager.hpp"
#include "../debug/Log.hpp"
#include "VersionKeeperManager.hpp"
#include "eventLoop/EventLoopManager.hpp"
#include "../config/ConfigValue.hpp"
#include <chrono>
#include <format>
#include "../helpers/fs/FsUtils.hpp"
#include <hyprutils/os/Process.hpp>
using namespace Hyprutils::OS;
constexpr const char* LAST_NAG_FILE_NAME = "lastNag";
constexpr uint64_t DAY_IN_SECONDS = 3600ULL * 24;
constexpr uint64_t MONTH_IN_SECONDS = DAY_IN_SECONDS * 30;
struct SNagDatePoint {
// Counted from 1, as in Jan 1st is 1, 1
// No month-boundaries because I am lazy
uint8_t month = 0, dayStart = 0, dayEnd = 0;
};
// clang-format off
const std::vector<SNagDatePoint> NAG_DATE_POINTS = {
SNagDatePoint {
7, 20, 31,
},
SNagDatePoint {
12, 1, 28
},
};
// clang-format on
CDonationNagManager::CDonationNagManager() {
static auto PNONAG = CConfigValue<Hyprlang::INT>("ecosystem:no_donation_nag");
if (g_pVersionKeeperMgr->fired() || *PNONAG)
return;
const auto DATAROOT = NFsUtils::getDataHome();
if (!DATAROOT)
return;
const auto EPOCH = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
const auto LASTNAGSTR = NFsUtils::readFileAsString(*DATAROOT + "/" + LAST_NAG_FILE_NAME);
if (!LASTNAGSTR) {
const auto EPOCHSTR = std::format("{}", EPOCH);
NFsUtils::writeToFile(*DATAROOT + "/" + LAST_NAG_FILE_NAME, EPOCHSTR);
return;
}
uint64_t LAST_EPOCH = 0;
try {
LAST_EPOCH = std::stoull(*LASTNAGSTR);
} catch (std::exception& e) {
Debug::log(ERR, "DonationNag: Last epoch invalid? Failed to parse \"{}\". Setting to today.", *LASTNAGSTR);
const auto EPOCHSTR = std::format("{}", EPOCH);
NFsUtils::writeToFile(*DATAROOT + "/" + LAST_NAG_FILE_NAME, EPOCHSTR);
return;
}
// don't nag if the last nag was less than a month ago. This is
// mostly for first-time nags, as other nags happen in specific time frames shorter than a month
if (EPOCH - LAST_EPOCH < MONTH_IN_SECONDS) {
Debug::log(LOG, "DonationNag: last nag was {} days ago, too early for a nag.", (int)std::round((EPOCH - LAST_EPOCH) / (double)MONTH_IN_SECONDS));
return;
}
if (!NFsUtils::executableExistsInPath("hyprland-donate-screen")) {
Debug::log(ERR, "DonationNag: executable doesn't exist, skipping.");
return;
}
auto tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
auto local = *localtime(&tt);
const auto MONTH = local.tm_mon + 1;
const auto DAY = local.tm_mday;
for (const auto& nagPoint : NAG_DATE_POINTS) {
if (MONTH != nagPoint.month)
continue;
if (DAY < nagPoint.dayStart || DAY > nagPoint.dayEnd)
continue;
Debug::log(LOG, "DonationNag: hit nag month {} days {}-{}, it's {} today, nagging", MONTH, nagPoint.dayStart, nagPoint.dayEnd, DAY);
m_bFired = true;
const auto EPOCHSTR = std::format("{}", EPOCH);
NFsUtils::writeToFile(*DATAROOT + "/" + LAST_NAG_FILE_NAME, EPOCHSTR);
g_pEventLoopManager->doLater([] {
CProcess proc("hyprland-donate-screen", {});
proc.runAsync();
});
break;
}
if (!m_bFired)
Debug::log(LOG, "DonationNag: didn't hit any nagging periods");
}
bool CDonationNagManager::fired() {
return m_bFired;
}

View File

@@ -1,16 +0,0 @@
#pragma once
#include "../helpers/memory/Memory.hpp"
class CDonationNagManager {
public:
CDonationNagManager();
// whether the donation nag was shown this boot.
bool fired();
private:
bool m_bFired = false;
};
inline UP<CDonationNagManager> g_pDonationNagManager;

View File

@@ -42,4 +42,4 @@ class CEventManager {
std::vector<SClient> m_vClients; std::vector<SClient> m_vClients;
}; };
inline UP<CEventManager> g_pEventManager; inline std::unique_ptr<CEventManager> g_pEventManager;

Some files were not shown because too many files have changed in this diff Show More