Compare commits

..

6 Commits

Author SHA1 Message Date
Vaxry
85917a40b0 more 2024-08-24 20:58:21 +02:00
Vaxry
d3e26652d6 better 2024-08-24 20:54:05 +02:00
Vaxry
276652b44e fix pure fade 2024-08-24 20:53:27 +02:00
Vaxry
746f804568 oops 2024-08-24 20:42:16 +02:00
Vaxry
00319c01d4 def 0% 2024-08-24 20:31:14 +02:00
Vaxry
b509273759 implement ws scaling 2024-08-24 20:29:31 +02:00
404 changed files with 11041 additions and 21451 deletions

View File

@@ -1,101 +0,0 @@
WarningsAsErrors: '*'
HeaderFilterRegex: '.*\.hpp'
FormatStyle: file
Checks: >
-*,
bugprone-*,
-bugprone-easily-swappable-parameters,
-bugprone-forward-declararion-namespace,
-bugprone-forward-declararion-namespace,
-bugprone-macro-parentheses,
-bugprone-narrowing-conversions,
-bugprone-branch-clone,
-bugprone-assignment-in-if-condition,
concurrency-*,
-concurrency-mt-unsafe,
cppcoreguidelines-*,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-avoid-magic-numbers,
-cppcoreguidelines-pro-bounds-constant-array-index,
-cppcoreguidelines-avoid-const-or-ref-data-members,
-cppcoreguidelines-non-private-member-variables-in-classes,
-cppcoreguidelines-avoid-goto,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-cppcoreguidelines-avoid-do-while,
-cppcoreguidelines-avoid-non-const-global-variables,
-cppcoreguidelines-special-member-functions,
-cppcoreguidelines-explicit-virtual-functions,
-cppcoreguidelines-avoid-c-arrays,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-narrowing-conversions,
-cppcoreguidelines-pro-type-union-access,
-cppcoreguidelines-pro-type-member-init,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-macro-to-enum,
-cppcoreguidelines-init-variables,
-cppcoreguidelines-pro-type-cstyle-cast,
-cppcoreguidelines-pro-type-vararg,
-cppcoreguidelines-pro-type-reinterpret-cast,
google-global-names-in-headers,
-google-readability-casting,
google-runtime-operator,
misc-*,
-misc-unused-parameters,
-misc-no-recursion,
-misc-non-private-member-variables-in-classes,
-misc-include-cleaner,
-misc-use-anonymous-namespace,
-misc-const-correctness,
modernize-*,
-modernize-return-braced-init-list,
-modernize-use-trailing-return-type,
-modernize-use-using,
-modernize-use-override,
-modernize-avoid-c-arrays,
-modernize-macro-to-enum,
-modernize-loop-convert,
-modernize-use-nodiscard,
-modernize-pass-by-value,
-modernize-use-auto,
performance-*,
-performance-avoid-endl,
-performance-unnecessary-value-param,
portability-std-allocator-const,
readability-*,
-readability-function-cognitive-complexity,
-readability-function-size,
-readability-identifier-length,
-readability-magic-numbers,
-readability-uppercase-literal-suffix,
-readability-braces-around-statements,
-readability-redundant-access-specifiers,
-readability-else-after-return,
-readability-container-data-pointer,
-readability-implicit-bool-conversion,
-readability-avoid-nested-conditional-operator,
-readability-redundant-member-init,
-readability-redundant-string-init,
-readability-avoid-const-params-in-decls,
-readability-named-parameter,
-readability-convert-member-functions-to-static,
-readability-qualified-auto,
-readability-make-member-function-const,
-readability-isolate-declaration,
-readability-inconsistent-declaration-parameter-name,
-clang-diagnostic-error,
CheckOptions:
performance-for-range-copy.WarnOnAllAutoCopies: true
performance-inefficient-string-concatenation.StrictMode: true
readability-braces-around-statements.ShortStatementLines: 0
readability-identifier-naming.ClassCase: CamelCase
readability-identifier-naming.ClassIgnoredRegexp: I.*
readability-identifier-naming.ClassPrefix: C # We can't use regex here?!?!?!?
readability-identifier-naming.EnumCase: CamelCase
readability-identifier-naming.EnumPrefix: e
readability-identifier-naming.EnumConstantCase: UPPER_CASE
readability-identifier-naming.FunctionCase: camelBack
readability-identifier-naming.NamespaceCase: CamelCase
readability-identifier-naming.NamespacePrefix: N
readability-identifier-naming.StructPrefix: S
readability-identifier-naming.StructCase: CamelCase

View File

@@ -2,13 +2,12 @@ name: Bug Report
description: Something is not working right description: Something is not working right
labels: ["bug"] labels: ["bug"]
body: body:
- type: checkboxes - type: markdown
attributes: attributes:
label: Already reported ? * value: |
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. ## Before opening a new issue, please take a moment to search through the current open and closed issues to check if it already exists.
options:
- label: I have searched the existing open and closed issues. ---
required: true
- type: dropdown - type: dropdown
id: type id: type
@@ -19,28 +18,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 are on a
launch Hyprland, paste the output of `Hyprland --systeminfo`. version that shows you help menu, omit the `-c` and attach config files
to the issue). If you have configs outside of the main config shown
here, please attach.
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 +60,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

@@ -33,9 +33,7 @@ runs:
libfontenc \ libfontenc \
libglvnd \ libglvnd \
libinput \ libinput \
libjxl \
libliftoff \ libliftoff \
libwebp \
libxcursor \ libxcursor \
libxcvt \ libxcvt \
libxfont2 \ libxfont2 \
@@ -60,17 +58,7 @@ runs:
xcb-util \ xcb-util \
xcb-util-image \ xcb-util-image \
libzip \ libzip \
librsvg \ librsvg
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
@@ -81,11 +69,6 @@ runs:
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF`
cmake --install build cmake --install build
- name: Get hyprgraphics-git
shell: bash
run: |
git clone https://github.com/hyprwm/hyprgraphics && cd hyprgraphics && cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=/usr -B build && cmake --build build --target hyprgraphics && cmake --install build
- name: Get hyprutils-git - name: Get hyprutils-git
shell: bash shell: bash
run: | run: |

View File

@@ -1,9 +1,3 @@
<!--
BEFORE you submit your PR, please check out the PR guidelines
on our wiki: https://wiki.hyprland.org/Contributing-and-Debugging/PR-Guidelines/
-->
#### Describe your PR, what does it fix/add? #### Describe your PR, what does it fix/add?

View File

@@ -39,7 +39,7 @@ jobs:
tar -cvf Hyprland.tar.xz hyprland tar -cvf Hyprland.tar.xz hyprland
- name: Release - name: Release
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: Build archive name: Build archive
path: Hyprland.tar.xz path: Hyprland.tar.xz
@@ -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

@@ -17,14 +17,14 @@ jobs:
run: sudo apt install pandoc run: sudo apt install pandoc
- name: Clone repository - name: Clone repository
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
token: ${{ secrets.PAT }} token: ${{ secrets.PAT }}
- name: Build man pages - name: Build man pages
run: make man run: make man
- uses: stefanzweifel/git-auto-commit-action@v5 - uses: stefanzweifel/git-auto-commit-action@v4
name: Commit name: Commit
with: with:
commit_message: "[gha] build man pages" commit_message: "[gha] build man pages"

View File

@@ -1,5 +1,3 @@
name: Nix (Build)
on: on:
workflow_call: workflow_call:
secrets: secrets:
@@ -12,18 +10,21 @@ jobs:
matrix: matrix:
package: package:
- hyprland - hyprland
# - hyprland-cross # cross compiling fails due to qt
# failure chain: hyprland-qtutils -> qt6.qtsvg -> qt6.qtbase -> psqlodbc & qt6.qttranslations
- xdg-desktop-portal-hyprland - xdg-desktop-portal-hyprland
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: DeterminateSystems/nix-installer-action@main - name: Clone repository
- uses: DeterminateSystems/magic-nix-cache-action@main uses: actions/checkout@v4
with:
ref: ${{ github.ref }}
submodules: recursive
- uses: cachix/install-nix-action@v27
- uses: DeterminateSystems/magic-nix-cache-action@main
- uses: cachix/cachix-action@v15 - uses: cachix/cachix-action@v15
with: with:
name: hyprland name: hyprland
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- run: nix build 'github:hyprwm/Hyprland?ref=${{ github.ref }}#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org" - run: nix build '.?submodules=1#${{ matrix.package }}' -L --extra-substituters "https://hyprland.cachix.org"

View File

@@ -1,14 +1,15 @@
name: Nix (CI) name: Nix
on: [push, pull_request, workflow_dispatch] on: [push, pull_request, workflow_dispatch]
jobs: jobs:
update-inputs: update-inputs:
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
uses: ./.github/workflows/nix-update-inputs.yml uses: ./.github/workflows/nix-update-inputs.yml
secrets: inherit secrets: inherit
build: build:
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) && !contains(needs.*.result, 'failure')
needs: update-inputs
uses: ./.github/workflows/nix-build.yml uses: ./.github/workflows/nix-build.yml
secrets: inherit secrets: inherit

View File

@@ -1,4 +1,4 @@
name: Nix (Update Inputs) name: Nix
on: on:
workflow_call: workflow_call:
@@ -8,12 +8,11 @@ on:
jobs: jobs:
update: update:
if: github.repository == 'hyprwm/Hyprland'
name: inputs name: inputs
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Clone repository - name: Clone repository
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
token: ${{ secrets.PAT }} token: ${{ secrets.PAT }}
@@ -22,6 +21,6 @@ jobs:
run: nix/update-inputs.sh run: nix/update-inputs.sh
- name: Commit - name: Commit
uses: stefanzweifel/git-auto-commit-action@v5 uses: stefanzweifel/git-auto-commit-action@v4
with: with:
commit_message: "[gha] Nix: update inputs" commit_message: "[gha] Nix: update inputs"

View File

@@ -11,7 +11,7 @@ jobs:
steps: steps:
- name: Checkout Hyprland - name: Checkout Hyprland
id: checkout id: checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
submodules: recursive submodules: recursive
@@ -20,6 +20,7 @@ jobs:
run: | run: |
git fetch --unshallow || echo "failed unshallowing" git fetch --unshallow || echo "failed unshallowing"
bash -c scripts/generateVersion.sh bash -c scripts/generateVersion.sh
mv scripts/generateVersion.sh scripts/generateVersion.sh.bak
- name: Create tarball with submodules - name: Create tarball with submodules
id: tar id: tar

View File

@@ -13,7 +13,7 @@ jobs:
security-events: write security-events: write
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Scan with Flawfinder - name: Scan with Flawfinder
uses: david-a-wheeler/flawfinder@8e4a779ad59dbfaee5da586aa9210853b701959c uses: david-a-wheeler/flawfinder@8e4a779ad59dbfaee5da586aa9210853b701959c

View File

@@ -7,22 +7,22 @@ name: Mark stale issues and pull requests
on: on:
schedule: schedule:
- cron: "7 */4 * * *" - cron: '7 */4 * * *'
workflow_dispatch: workflow_dispatch:
jobs: jobs:
stale: stale:
if: github.repository == 'hyprwm/Hyprland'
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
issues: write issues: write
pull-requests: write pull-requests: write
steps: steps:
- uses: actions/stale@v9 - uses: actions/stale@v5
with: with:
repo-token: ${{ secrets.STALEBOT_PAT }} repo-token: ${{ secrets.STALEBOT_PAT }}
stale-issue-label: "stale" stale-issue-label: 'stale'
stale-pr-label: "stale" stale-pr-label: 'stale'
operations-per-run: 40 operations-per-run: 40
days-before-close: -1 days-before-close: -1

4
.gitignore vendored
View File

@@ -14,7 +14,6 @@ _deps
build/ build/
result* result*
/.pre-commit-config.yaml
/.vscode/ /.vscode/
/.idea/ /.idea/
.envrc .envrc
@@ -40,6 +39,3 @@ PKGBUILD
src/version.h src/version.h
hyprpm/Makefile hyprpm/Makefile
hyprctl/Makefile hyprctl/Makefile
**/.#*.*
**/#*.*#

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.30) cmake_minimum_required(VERSION 3.27)
# Get version # Get version
file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW) file(READ "${CMAKE_SOURCE_DIR}/VERSION" VER_RAW)
@@ -15,7 +15,6 @@ include(GNUInstallDirs)
set(HYPRLAND_VERSION ${VER}) set(HYPRLAND_VERSION ${VER})
set(PREFIX ${CMAKE_INSTALL_PREFIX}) set(PREFIX ${CMAKE_INSTALL_PREFIX})
set(INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}) set(INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR})
set(BINDIR ${CMAKE_INSTALL_BINDIR})
configure_file(hyprland.pc.in hyprland.pc @ONLY) configure_file(hyprland.pc.in hyprland.pc @ONLY)
set(CMAKE_MESSAGE_LOG_LEVEL "STATUS") set(CMAKE_MESSAGE_LOG_LEVEL "STATUS")
@@ -26,18 +25,8 @@ message(STATUS "Gathering git info")
execute_process(COMMAND ./scripts/generateVersion.sh execute_process(COMMAND ./scripts/generateVersion.sh
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
find_package(PkgConfig REQUIRED) # udis
# Try to find canihavesomecoffee's udis86 using pkgconfig vmd/udis86 does not
# provide a .pc file and won't be detected this way
pkg_check_modules(udis_dep IMPORTED_TARGET udis86>=1.7.2)
# Fallback to subproject
if(NOT udis_dep_FOUND)
add_subdirectory("subprojects/udis86") add_subdirectory("subprojects/udis86")
include_directories("subprojects/udis86")
message(STATUS "udis86 dependency not found, falling back to subproject")
endif()
if(CMAKE_BUILD_TYPE) if(CMAKE_BUILD_TYPE)
string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER) string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER)
@@ -58,6 +47,8 @@ else()
set(BUILDTYPE_LOWER "release") set(BUILDTYPE_LOWER "release")
endif() endif()
find_package(PkgConfig REQUIRED)
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}") message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}")
pkg_get_variable(WAYLAND_SCANNER_PKGDATA_DIR wayland-scanner pkgdatadir) pkg_get_variable(WAYLAND_SCANNER_PKGDATA_DIR wayland-scanner pkgdatadir)
@@ -72,10 +63,7 @@ else()
message(STATUS "Configuring Hyprland in Release with CMake") message(STATUS "Configuring Hyprland in Release with CMake")
endif() endif()
add_compile_definitions(HYPRLAND_VERSION="${HYPRLAND_VERSION}") include_directories(. "src/" "subprojects/udis86/" "protocols/")
include_directories(. "src/" "protocols/")
set(CMAKE_CXX_STANDARD 26) set(CMAKE_CXX_STANDARD 26)
add_compile_options( add_compile_options(
-Wall -Wall
@@ -101,25 +89,18 @@ else()
endif() endif()
find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION}) find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.4.5) pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.1)
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(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.5.0)
pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.1)
add_compile_definitions(AQUAMARINE_VERSION="${aquamarine_dep_VERSION}")
add_compile_definitions(HYPRLANG_VERSION="${hyprlang_dep_VERSION}")
add_compile_definitions(HYPRUTILS_VERSION="${hyprutils_dep_VERSION}")
add_compile_definitions(HYPRCURSOR_VERSION="${hyprcursor_dep_VERSION}")
add_compile_definitions(HYPRGRAPHICS_VERSION="${hyprgraphics_dep_VERSION}")
pkg_check_modules( pkg_check_modules(
deps deps
REQUIRED REQUIRED
IMPORTED_TARGET IMPORTED_TARGET
aquamarine
xkbcommon xkbcommon
uuid uuid
wayland-server>=1.22.90 wayland-server
wayland-client
wayland-cursor
wayland-protocols wayland-protocols
cairo cairo
pango pango
@@ -128,9 +109,16 @@ pkg_check_modules(
xcursor xcursor
libdrm libdrm
libinput libinput
hwdata
libseat
libdisplay-info
libliftoff
libudev
gbm gbm
gio-2.0 gio-2.0
re2) hyprlang>=0.3.2
hyprcursor>=0.1.7
hyprutils>=0.2.1)
find_package(hyprwayland-scanner 0.3.10 REQUIRED) find_package(hyprwayland-scanner 0.3.10 REQUIRED)
@@ -197,12 +185,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)
@@ -218,11 +200,14 @@ else()
REQUIRED REQUIRED
IMPORTED_TARGET IMPORTED_TARGET
xcb xcb
xwayland
xcb-util
xcb-render xcb-render
xcb-xfixes xcb-xfixes
xcb-icccm xcb-icccm
xcb-composite xcb-composite
xcb-res xcb-res
xcb-ewmh
xcb-errors) xcb-errors)
target_link_libraries(Hyprland PkgConfig::xdeps) target_link_libraries(Hyprland PkgConfig::xdeps)
endif() endif()
@@ -232,15 +217,6 @@ if(NO_SYSTEMD)
else() else()
message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined)...") message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined)...")
add_compile_definitions(USES_SYSTEMD) add_compile_definitions(USES_SYSTEMD)
# session file -uwsm
if(NO_UWSM)
message(STATUS "UWSM support is disabled...")
else()
message(STATUS "UWSM support is enabled (NO_UWSM not defined)...")
install(FILES ${CMAKE_SOURCE_DIR}/systemd/hyprland-uwsm.desktop
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/wayland-sessions)
endif()
endif() endif()
set(CPACK_PROJECT_NAME ${PROJECT_NAME}) set(CPACK_PROJECT_NAME ${PROJECT_NAME})
@@ -254,27 +230,14 @@ target_precompile_headers(Hyprland PRIVATE
message(STATUS "Setting link libraries") message(STATUS "Setting link libraries")
target_link_libraries( target_link_libraries(Hyprland rt 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)
target_link_libraries(Hyprland PkgConfig::udis_dep)
else()
target_link_libraries(Hyprland libudis86)
endif()
# used by `make installheaders`, to ensure the headers are generated # used by `make installheaders`, to ensure the headers are generated
add_custom_target(generate-protocol-headers) add_custom_target(generate-protocol-headers)
function(protocolnew protoPath protoName external) function(protocolnew protoPath protoName external)
if(external) if(external)
set(path ${protoPath}) set(path ${CMAKE_SOURCE_DIR}/${protoPath})
else() else()
set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath}) set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath})
endif() endif()
@@ -302,22 +265,14 @@ function(protocolWayland)
PRIVATE ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp) PRIVATE ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp)
endfunction() endfunction()
target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads) target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads
libudis86 uuid)
pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.6.0) protocolnew("subprojects/hyprland-protocols/protocols"
if(hyprland_protocols_dep_FOUND) "hyprland-global-shortcuts-v1" true)
pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir)
message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}")
else()
set(HYPRLAND_PROTOCOLS "subprojects/hyprland-protocols")
message(STATUS "hyprland-protocols subproject set to ${HYPRLAND_PROTOCOLS}")
endif()
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-global-shortcuts-v1"
true)
protocolnew("unstable/text-input" "text-input-unstable-v1" false) protocolnew("unstable/text-input" "text-input-unstable-v1" false)
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-toplevel-export-v1" protocolnew("subprojects/hyprland-protocols/protocols"
true) "hyprland-toplevel-export-v1" true)
protocolnew("protocols" "wlr-screencopy-unstable-v1" true) protocolnew("protocols" "wlr-screencopy-unstable-v1" true)
protocolnew("protocols" "wlr-gamma-control-unstable-v1" true) protocolnew("protocols" "wlr-gamma-control-unstable-v1" true)
protocolnew("protocols" "wlr-foreign-toplevel-management-unstable-v1" true) protocolnew("protocols" "wlr-foreign-toplevel-management-unstable-v1" true)
@@ -328,15 +283,10 @@ protocolnew("protocols" "input-method-unstable-v2" true)
protocolnew("protocols" "wlr-output-management-unstable-v1" true) protocolnew("protocols" "wlr-output-management-unstable-v1" true)
protocolnew("protocols" "kde-server-decoration" true) 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("subprojects/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-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)
protocolnew("unstable/xdg-output" "xdg-output-unstable-v1" false) protocolnew("unstable/xdg-output" "xdg-output-unstable-v1" false)
@@ -365,21 +315,12 @@ protocolnew("stable/viewporter" "viewporter" false)
protocolnew("stable/linux-dmabuf" "linux-dmabuf-v1" false) protocolnew("stable/linux-dmabuf" "linux-dmabuf-v1" false)
protocolnew("staging/drm-lease" "drm-lease-v1" false) protocolnew("staging/drm-lease" "drm-lease-v1" false)
protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false) protocolnew("staging/linux-drm-syncobj" "linux-drm-syncobj-v1" false)
protocolnew("staging/xdg-dialog" "xdg-dialog-v1" false)
protocolnew("staging/single-pixel-buffer" "single-pixel-buffer-v1" false)
protocolnew("staging/security-context" "security-context-v1" false)
protocolwayland() protocolwayland()
# tools # tools
add_subdirectory(hyprctl) add_subdirectory(hyprctl)
if(NO_HYPRPM)
message(STATUS "hyprpm is disabled")
else()
add_subdirectory(hyprpm) 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,18 +331,17 @@ 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)
# allow Hyprland to find assets # allow Hyprland to find wallpapers
add_compile_definitions(DATAROOTDIR="${CMAKE_INSTALL_FULL_DATAROOTDIR}") add_compile_definitions(DATAROOTDIR="${CMAKE_INSTALL_FULL_DATAROOTDIR}")
# installable assets # wallpapers
file(GLOB_RECURSE INSTALLABLE_ASSETS "assets/install/*") file(GLOB_RECURSE WALLPAPERS "assets/wall*")
list(FILTER INSTALLABLE_ASSETS EXCLUDE REGEX "meson.build") install(FILES ${WALLPAPERS} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr)
install(FILES ${INSTALLABLE_ASSETS}
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr)
# default config # default config
install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.conf install(FILES ${CMAKE_SOURCE_DIR}/example/hyprland.conf

View File

@@ -1,27 +1,28 @@
PREFIX = /usr/local PREFIX = /usr/local
stub:
@echo "Do not run $(MAKE) directly without any arguments. Please refer to the wiki on how to compile Hyprland."
legacyrenderer: legacyrenderer:
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` cmake --build ./build --config Release --target all
chmod -R 777 ./build
legacyrendererdebug: legacyrendererdebug:
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` cmake --build ./build --config Release --target all
chmod -R 777 ./build
release: release:
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` cmake --build ./build --config Release --target all
chmod -R 777 ./build
debug: debug:
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -S . -B ./build -G Ninja
cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` cmake --build ./build --config Debug --target all
chmod -R 777 ./build
nopch: nopch:
cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -S . -B ./build cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:STRING=${PREFIX} -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -S . -B ./build -G Ninja
cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` cmake --build ./build --config Release --target all
clear: clear:
rm -rf build rm -rf build

View File

@@ -100,7 +100,7 @@ easy IPC, much more QoL stuff than other compositors and more...
<!-----------------------------------------------------------------------------> <!----------------------------------------------------------------------------->
[Configure]: https://wiki.hyprland.org/Configuring/ [Configure]: https://wiki.hyprland.org/Configuring/Configuring-Hyprland/
[Stars]: https://starchart.cc/hyprwm/Hyprland [Stars]: https://starchart.cc/hyprwm/Hyprland
[Hypr]: https://github.com/hyprwm/Hypr [Hypr]: https://github.com/hyprwm/Hypr

View File

@@ -1 +1 @@
0.47.2 0.42.0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -1,10 +0,0 @@
globber = run_command('sh', '-c', 'find . -type f -not -name "*.build"', check: true)
files = globber.stdout().strip().split('\n')
foreach file : files
install_data(
file,
install_dir: join_paths(get_option('datadir'), 'hypr'),
install_tag: 'runtime',
)
endforeach

View File

@@ -1,7 +1,7 @@
install_data( wallpapers = ['0', '1', '2']
'hyprland-portals.conf',
install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'),
install_tag: 'runtime',
)
subdir('install') foreach type : wallpapers
install_data(f'wall@type@.png', install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime')
endforeach
install_data('hyprland-portals.conf', install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'), install_tag: 'runtime')

View File

Before

Width:  |  Height:  |  Size: 14 MiB

After

Width:  |  Height:  |  Size: 14 MiB

View File

Before

Width:  |  Height:  |  Size: 5.9 MiB

After

Width:  |  Height:  |  Size: 5.9 MiB

View File

Before

Width:  |  Height:  |  Size: 27 MiB

After

Width:  |  Height:  |  Size: 27 MiB

View File

@@ -10,8 +10,8 @@ Hyprland - Dynamic tiling Wayland compositor
\f[B]Hyprland\f[R] [\f[I]arg [...]\f[R]]. \f[B]Hyprland\f[R] [\f[I]arg [...]\f[R]].
.SH DESCRIPTION .SH DESCRIPTION
.PP .PP
\f[B]Hyprland\f[R] is an independent, highly customizable, dynamic \f[B]Hyprland\f[R] is a dynamic tiling Wayland compositor based on
tiling Wayland compositor that doesn\[aq]t sacrifice on its looks. wlroots that doesn\[aq]t sacrifice on its looks.
.PP .PP
You can launch Hyprland by either going into a TTY and executing You can launch Hyprland by either going into a TTY and executing
\f[B]Hyprland\f[R], or with a login manager. \f[B]Hyprland\f[R], or with a login manager.

View File

@@ -14,8 +14,8 @@ SYNOPSIS
DESCRIPTION DESCRIPTION
=========== ===========
**Hyprland** is an independent, highly customizable, **Hyprland** is a dynamic tiling Wayland compositor based on
dynamic tiling Wayland compositor that doesn't sacrifice on its looks. wlroots that doesn't sacrifice on its looks.
You can launch Hyprland by either going into a TTY and You can launch Hyprland by either going into a TTY and
executing **Hyprland**, or with a login manager. executing **Hyprland**, or with a login manager.

View File

@@ -3,7 +3,7 @@
First of all, please remember to: First of all, please remember to:
- Check that your issue is not a duplicate - Check that your issue is not a duplicate
- Read the [FAQ](https://wiki.hyprland.org/FAQ/) - Read the [FAQ](https://wiki.hyprland.org/FAQ/)
- Read the [Configuring Page](https://wiki.hyprland.org/Configuring/) - Read the [Configuring Page](https://wiki.hyprland.org/Configuring/Configuring-Hyprland)
<br/> <br/>

View File

@@ -0,0 +1,14 @@
[Unit]
Description=Hyprland - Tiling compositor with the looks
Documentation=man:Hyprland(1)
BindsTo=graphical-session.target
Before=graphical-session.target
Wants=graphical-session-pre.target
After=graphical-session-pre.target
[Service]
Type=notify
ExecStart=/usr/bin/Hyprland
ExecStop=/usr/bin/hyprctl dispatch exit
Restart=on-failure
Slice=session.slice

View File

@@ -1,6 +1,5 @@
[Desktop Entry] [Desktop Entry]
Name=Hyprland (uwsm-managed) Name=Hyprland
Comment=An intelligent dynamic tiling Wayland compositor Comment=An intelligent dynamic tiling Wayland compositor
Exec=uwsm start -- hyprland.desktop Exec=systemctl --user start --wait hyprland-session
DesktopNames=Hyprland
Type=Application Type=Application

View File

@@ -1,6 +1,6 @@
# This is an example Hyprland config file. # This is an example Hyprland config file.
# Refer to the wiki for more information. # Refer to the wiki for more information.
# https://wiki.hyprland.org/Configuring/ # https://wiki.hyprland.org/Configuring/Configuring-Hyprland/
# Please note not all available settings / options are set here. # Please note not all available settings / options are set here.
# For a full list, see the wiki # For a full list, see the wiki
@@ -81,18 +81,15 @@ 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
inactive_opacity = 1.0 inactive_opacity = 1.0
shadow { drop_shadow = true
enabled = true shadow_range = 4
range = 4 shadow_render_power = 3
render_power = 3 col.shadow = rgba(1a1a1aee)
color = rgba(1a1a1aee)
}
# https://wiki.hyprland.org/Configuring/Variables/#blur # https://wiki.hyprland.org/Configuring/Variables/#blur
blur { blur {
@@ -106,44 +103,20 @@ decoration {
# https://wiki.hyprland.org/Configuring/Variables/#animations # https://wiki.hyprland.org/Configuring/Variables/#animations
animations { animations {
enabled = yes, please :) enabled = true
# Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more # Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
bezier = easeOutQuint,0.23,1,0.32,1 bezier = myBezier, 0.05, 0.9, 0.1, 1.05
bezier = easeInOutCubic,0.65,0.05,0.36,1
bezier = linear,0,0,1,1
bezier = almostLinear,0.5,0.5,0.75,1.0
bezier = quick,0.15,0,0.1,1
animation = global, 1, 10, default animation = windows, 1, 7, myBezier
animation = border, 1, 5.39, easeOutQuint animation = windowsOut, 1, 7, default, popin 80%
animation = windows, 1, 4.79, easeOutQuint animation = border, 1, 10, default
animation = windowsIn, 1, 4.1, easeOutQuint, popin 87% animation = borderangle, 1, 8, default
animation = windowsOut, 1, 1.49, linear, popin 87% animation = fade, 1, 7, default
animation = fadeIn, 1, 1.73, almostLinear animation = workspaces, 1, 6, default
animation = fadeOut, 1, 1.46, almostLinear
animation = fade, 1, 3.03, quick
animation = layers, 1, 3.81, easeOutQuint
animation = layersIn, 1, 4, easeOutQuint, fade
animation = layersOut, 1, 1.5, linear, fade
animation = fadeLayersIn, 1, 1.79, almostLinear
animation = fadeLayersOut, 1, 1.39, almostLinear
animation = workspaces, 1, 1.94, almostLinear, fade
animation = workspacesIn, 1, 1.21, almostLinear, fade
animation = workspacesOut, 1, 1.94, almostLinear, fade
} }
# Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/
# "Smart gaps" / "No gaps when only"
# uncomment all if you wish to use that.
# workspace = w[tv1], gapsout:0, gapsin:0
# workspace = f[1], gapsout:0, gapsin:0
# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tv1]
# windowrulev2 = rounding 0, floating:0, onworkspace:w[tv1]
# windowrulev2 = bordersize 0, floating:0, onworkspace:f[1]
# windowrulev2 = rounding 0, floating:0, onworkspace:f[1]
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
dwindle { dwindle {
pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
@@ -255,19 +228,6 @@ bind = $mainMod, mouse_up, workspace, e-1
bindm = $mainMod, mouse:272, movewindow bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow bindm = $mainMod, mouse:273, resizewindow
# Laptop multimedia keys for volume and LCD brightness
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+
bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+
bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
# Requires playerctl
bindl = , XF86AudioNext, exec, playerctl next
bindl = , XF86AudioPause, exec, playerctl play-pause
bindl = , XF86AudioPlay, exec, playerctl play-pause
bindl = , XF86AudioPrev, exec, playerctl previous
############################## ##############################
### WINDOWS AND WORKSPACES ### ### WINDOWS AND WORKSPACES ###
@@ -282,8 +242,4 @@ bindl = , XF86AudioPrev, exec, playerctl previous
# Example windowrule v2 # Example windowrule v2
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$ # windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
# Ignore maximize requests from apps. You'll probably like this. windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
windowrulev2 = suppressevent maximize, class:.*
# Fix some dragging issues with XWayland
windowrulev2 = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0

View File

@@ -3,5 +3,3 @@ Name=Hyprland
Comment=An intelligent dynamic tiling Wayland compositor Comment=An intelligent dynamic tiling Wayland compositor
Exec=Hyprland Exec=Hyprland
Type=Application Type=Application
DesktopNames=Hyprland
Keywords=tiling;wayland;compositor;

View File

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

View File

@@ -1,10 +1,2 @@
install_data( install_data('hyprland.conf', install_dir: join_paths(get_option('datadir'), 'hypr'), install_tag: 'runtime')
'hyprland.conf', install_data('hyprland.desktop', install_dir: join_paths(get_option('datadir'), 'wayland-sessions'), install_tag: 'runtime')
install_dir: join_paths(get_option('datadir'), 'hypr'),
install_tag: 'runtime',
)
install_data(
'hyprland.desktop',
install_dir: join_paths(get_option('datadir'), 'wayland-sessions'),
install_tag: 'runtime',
)

263
flake.lock generated
View File

@@ -16,11 +16,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1737636397, "lastModified": 1724273991,
"narHash": "sha256-F5MbBj3QVorycVSFE9qjuOTLtIQBqt2VWbXa0uwzm98=", "narHash": "sha256-+aUSOXKGpS5CRm1oTitgNAr05ThQNbKIXalZHl3nC6Y=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "aquamarine", "repo": "aquamarine",
"rev": "7fe006981fae53e931f513026fc754e322f13145", "rev": "9a3161ad4c78dc420d1cbb3aae638222608c7de4",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -29,43 +29,6 @@
"type": "github" "type": "github"
} }
}, },
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"pre-commit-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"hyprcursor": { "hyprcursor": {
"inputs": { "inputs": {
"hyprlang": [ "hyprlang": [
@@ -79,11 +42,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1737634937, "lastModified": 1722623071,
"narHash": "sha256-Ffw4ujFpi++6pPHe+gCBOfDgAoNlzVPZN6MReC1beu8=", "narHash": "sha256-sLADpVgebpCBFXkA1FlCXtvEPu1tdEsTfqK1hfeHySE=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprcursor", "repo": "hyprcursor",
"rev": "9c5dd1f7c825ee47f72727ad0a4e16ca46a2688e", "rev": "912d56025f03d41b1ad29510c423757b4379eb1c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -92,47 +55,23 @@
"type": "github" "type": "github"
} }
}, },
"hyprgraphics": {
"inputs": {
"hyprutils": [
"hyprutils"
],
"nixpkgs": [
"nixpkgs"
],
"systems": [
"systems"
]
},
"locked": {
"lastModified": 1737634889,
"narHash": "sha256-9JZE3KxcXOqZH9zs3UeadngDiK/yIACTiAR8HSA/TNI=",
"owner": "hyprwm",
"repo": "hyprgraphics",
"rev": "0d77b4895ad5f1bb3b0ee43103a5246c58b65591",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprgraphics",
"type": "github"
}
},
"hyprland-protocols": { "hyprland-protocols": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
"xdph",
"nixpkgs" "nixpkgs"
], ],
"systems": [ "systems": [
"xdph",
"systems" "systems"
] ]
}, },
"locked": { "locked": {
"lastModified": 1737556638, "lastModified": 1721326555,
"narHash": "sha256-laKgI3mr2qz6tas/q3tuGPxMdsGhBi/w+HO+hO2f1AY=", "narHash": "sha256-zCu4R0CSHEactW9JqYki26gy8h9f6rHmSwj4XJmlHgg=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprland-protocols", "repo": "hyprland-protocols",
"rev": "4c75dd5c015c8a0e5a34c6d02a018a650f57feb5", "rev": "5a11232266bf1a1f5952d5b179c3f4b2facaaa84",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -141,88 +80,7 @@
"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": {
"inputs": {
"hyprland-qt-support": "hyprland-qt-support",
"hyprutils": [
"hyprutils"
],
"nixpkgs": [
"nixpkgs"
],
"systems": [
"systems"
]
},
"locked": {
"lastModified": 1737811848,
"narHash": "sha256-WZ7LeiKHk5Y94MU5gHIWn0r8asWxYOvie4LqfCjVIZU=",
"owner": "hyprwm",
"repo": "hyprland-qtutils",
"rev": "9c0831ff98856c0f312fcb8b57553fbe3dd34d5b",
"type": "github"
},
"original": {
"owner": "hyprwm",
"repo": "hyprland-qtutils",
"type": "github"
}
},
"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 +93,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1737634606, "lastModified": 1724174162,
"narHash": "sha256-W7W87Cv6wqZ9PHegI6rH1+ve3zJPiyevMFf0/HwdbCQ=", "narHash": "sha256-fOOBLwil6M9QWMCiSULwjMQzrXhHXUnEqmjHX5ZHeVI=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprlang", "repo": "hyprlang",
"rev": "f41271d35cc0f370d300413d756c2677f386af9d", "rev": "16e5c9465f04477d8a3dd48a0a26bf437986336c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -249,35 +107,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 +116,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1737725508, "lastModified": 1722869141,
"narHash": "sha256-jGmcPc6y/prg/4A8KGYqJ27nSPaProCMiFadaxNAKvA=", "narHash": "sha256-0KU4qhyMp441qfwbirNg3+wbm489KnEjXOz2I/RbeFs=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprutils", "repo": "hyprutils",
"rev": "fb0c2d1de3d1ef7396d19c18ac09e12bd956929e", "rev": "0252fd13e78e60fb0da512a212e56007515a49f7",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -310,11 +139,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1735493474, "lastModified": 1721324119,
"narHash": "sha256-fktzv4NaqKm94VAkAoVqO/nqQlw+X0/tJJNAeCSfzK4=", "narHash": "sha256-SOOqIT27/X792+vsLSeFdrNTF+OSRp5qXv6Te+fb2Qg=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "hyprwayland-scanner", "repo": "hyprwayland-scanner",
"rev": "de913476b59ee88685fdc018e77b8f6637a2ae0b", "rev": "a048a6cb015340bd82f97c1f40a4b595ca85cc30",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -325,11 +154,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1737632463, "lastModified": 1724224976,
"narHash": "sha256-38J9QfeGSej341ouwzqf77WIHAScihAKCt8PQJ+NH28=", "narHash": "sha256-Z/ELQhrSd7bMzTO8r7NZgi9g5emh+aRKoCdaAv5fiO0=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "0aa475546ed21629c4f5bbf90e38c846a99ec9e9", "rev": "c374d94f1536013ca8e92341b540eba4c22f9c62",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -339,40 +168,14 @@
"type": "github" "type": "github"
} }
}, },
"pre-commit-hooks": {
"inputs": {
"flake-compat": "flake-compat",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1737465171,
"narHash": "sha256-R10v2hoJRLq8jcL4syVFag7nIGE7m13qO48wRIukWNg=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "9364dc02281ce2d37a1f55b6e51f7c0f65a75f17",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"root": { "root": {
"inputs": { "inputs": {
"aquamarine": "aquamarine", "aquamarine": "aquamarine",
"hyprcursor": "hyprcursor", "hyprcursor": "hyprcursor",
"hyprgraphics": "hyprgraphics", "hyprlang": "hyprlang",
"hyprland-protocols": "hyprland-protocols", "hyprutils": "hyprutils",
"hyprland-qtutils": "hyprland-qtutils",
"hyprlang": "hyprlang_2",
"hyprutils": "hyprutils_2",
"hyprwayland-scanner": "hyprwayland-scanner", "hyprwayland-scanner": "hyprwayland-scanner",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"pre-commit-hooks": "pre-commit-hooks",
"systems": "systems", "systems": "systems",
"xdph": "xdph" "xdph": "xdph"
} }
@@ -394,18 +197,10 @@
}, },
"xdph": { "xdph": {
"inputs": { "inputs": {
"hyprland-protocols": [ "hyprland-protocols": "hyprland-protocols",
"hyprland-protocols"
],
"hyprlang": [ "hyprlang": [
"hyprlang" "hyprlang"
], ],
"hyprutils": [
"hyprutils"
],
"hyprwayland-scanner": [
"hyprwayland-scanner"
],
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ],
@@ -414,11 +209,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1737634991, "lastModified": 1724073926,
"narHash": "sha256-dBAnb7Kbnier30cA7AgxVSxxARmxKZ1vHZT33THSIr8=", "narHash": "sha256-nWlUL43jOFHf+KW6Hqrx+W/r1XdXuDyb0wC/SrHsOu4=",
"owner": "hyprwm", "owner": "hyprwm",
"repo": "xdg-desktop-portal-hyprland", "repo": "xdg-desktop-portal-hyprland",
"rev": "e09dfe2726c8008f983e45a0aa1a3b7416aaeb8a", "rev": "a08ecbbf33598924e93542f737fc6169a26b481e",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@@ -22,26 +22,6 @@
inputs.hyprlang.follows = "hyprlang"; inputs.hyprlang.follows = "hyprlang";
}; };
hyprgraphics = {
url = "github:hyprwm/hyprgraphics";
inputs.nixpkgs.follows = "nixpkgs";
inputs.systems.follows = "systems";
inputs.hyprutils.follows = "hyprutils";
};
hyprland-protocols = {
url = "github:hyprwm/hyprland-protocols";
inputs.nixpkgs.follows = "nixpkgs";
inputs.systems.follows = "systems";
};
hyprland-qtutils = {
url = "github:hyprwm/hyprland-qtutils";
inputs.nixpkgs.follows = "nixpkgs";
inputs.systems.follows = "systems";
inputs.hyprutils.follows = "hyprutils";
};
hyprlang = { hyprlang = {
url = "github:hyprwm/hyprlang"; url = "github:hyprwm/hyprlang";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
@@ -65,15 +45,7 @@
url = "github:hyprwm/xdg-desktop-portal-hyprland"; url = "github:hyprwm/xdg-desktop-portal-hyprland";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
inputs.systems.follows = "systems"; inputs.systems.follows = "systems";
inputs.hyprland-protocols.follows = "hyprland-protocols";
inputs.hyprlang.follows = "hyprlang"; inputs.hyprlang.follows = "hyprlang";
inputs.hyprutils.follows = "hyprutils";
inputs.hyprwayland-scanner.follows = "hyprwayland-scanner";
};
pre-commit-hooks = {
url = "github:cachix/git-hooks.nix";
inputs.nixpkgs.follows = "nixpkgs";
}; };
}; };
@@ -93,15 +65,6 @@
hyprland-extras hyprland-extras
]; ];
}); });
pkgsCrossFor = eachSystem (system: crossSystem:
import nixpkgs {
localSystem = system;
inherit crossSystem;
overlays = with self.overlays; [
hyprland-packages
hyprland-extras
];
});
in { in {
overlays = import ./nix/overlays.nix {inherit self lib inputs;}; overlays = import ./nix/overlays.nix {inherit self lib inputs;};
@@ -111,18 +74,6 @@
self.packages.${system}) self.packages.${system})
// { // {
inherit (self.packages.${system}) xdg-desktop-portal-hyprland; inherit (self.packages.${system}) xdg-desktop-portal-hyprland;
pre-commit-check = inputs.pre-commit-hooks.lib.${system}.run {
src = ./.;
hooks = {
hyprland-treewide-formatter = {
enable = true;
entry = "${self.formatter.${system}}/bin/hyprland-treewide-formatter";
pass_filenames = false;
excludes = ["subprojects"];
always_run = true;
};
};
};
}); });
packages = eachSystem (system: { packages = eachSystem (system: {
@@ -130,30 +81,34 @@
inherit inherit
(pkgsFor.${system}) (pkgsFor.${system})
# hyprland-packages # hyprland-packages
hyprland hyprland
hyprland-debug hyprland-debug
hyprland-legacy-renderer hyprland-legacy-renderer
hyprland-unwrapped hyprland-unwrapped
# hyprland-extras # hyprland-extras
xdg-desktop-portal-hyprland xdg-desktop-portal-hyprland
; ;
hyprland-cross = (pkgsCrossFor.${system} "aarch64-linux").hyprland;
}); });
devShells = eachSystem (system: { devShells = eachSystem (system: {
default = default =
pkgsFor.${system}.mkShell.override { pkgsFor.${system}.mkShell.override {
inherit (self.packages.${system}.default) stdenv; stdenv = pkgsFor.${system}.gcc14Stdenv;
} { } {
name = "hyprland-shell"; name = "hyprland-shell";
nativeBuildInputs = with pkgsFor.${system}; [
expat
libxml2
];
hardeningDisable = ["fortify"]; hardeningDisable = ["fortify"];
inputsFrom = [pkgsFor.${system}.hyprland]; inputsFrom = [pkgsFor.${system}.hyprland];
packages = [pkgsFor.${system}.clang-tools]; packages = [pkgsFor.${system}.clang-tools];
inherit (self.checks.${system}.pre-commit-check) shellHook;
}; };
}); });
formatter = eachSystem (system: pkgsFor.${system}.callPackage ./nix/formatter.nix {}); formatter = eachSystem (system: nixpkgs.legacyPackages.${system}.alejandra);
nixosModules.default = import ./nix/module.nix inputs; nixosModules.default = import ./nix/module.nix inputs;
homeManagerModules.default = import ./nix/hm-module.nix self; homeManagerModules.default = import ./nix/hm-module.nix self;

View File

@@ -5,7 +5,7 @@ project(
DESCRIPTION "Control utility for Hyprland" DESCRIPTION "Control utility for Hyprland"
) )
pkg_check_modules(hyprctl_deps REQUIRED IMPORTED_TARGET hyprutils>=0.2.4 re2) pkg_check_modules(deps REQUIRED IMPORTED_TARGET hyprutils>=0.1.1)
add_executable(hyprctl "main.cpp") add_executable(hyprctl "main.cpp")

View File

@@ -1,7 +1,5 @@
#pragma once #pragma once
#include <string_view>
const std::string_view USAGE = R"#(usage: hyprctl [flags] <command> [args...|--help] const std::string_view USAGE = R"#(usage: hyprctl [flags] <command> [args...|--help]
commands: commands:

View File

@@ -1,5 +1,3 @@
#include <re2/re2.h>
#include <cctype> #include <cctype>
#include <netdb.h> #include <netdb.h>
#include <netinet/in.h> #include <netinet/in.h>
@@ -19,12 +17,13 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <print>
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <vector> #include <vector>
#include <deque>
#include <filesystem> #include <filesystem>
#include <cstdarg> #include <cstdarg>
#include <regex>
#include <sys/socket.h> #include <sys/socket.h>
#include <hyprutils/string/String.hpp> #include <hyprutils/string/String.hpp>
#include <cstring> #include <cstring>
@@ -45,24 +44,18 @@ struct SInstanceData {
bool valid = true; bool valid = true;
}; };
void log(const std::string& str) { void log(std::string str) {
if (quiet) if (quiet)
return; return;
std::println("{}", str); std::cout << str << "\n";
}
static int getUID() {
const auto UID = getuid();
const auto PWUID = getpwuid(UID);
return PWUID ? PWUID->pw_uid : UID;
} }
std::string getRuntimeDir() { std::string getRuntimeDir() {
const auto XDG = getenv("XDG_RUNTIME_DIR"); const auto XDG = getenv("XDG_RUNTIME_DIR");
if (!XDG) { if (!XDG) {
const std::string USERID = std::to_string(getUID()); const std::string USERID = std::to_string(getpwuid(getuid())->pw_uid);
return "/run/user/" + USERID + "/hypr"; return "/run/user/" + USERID + "/hypr";
} }
@@ -72,11 +65,6 @@ std::string getRuntimeDir() {
std::vector<SInstanceData> instances() { std::vector<SInstanceData> instances() {
std::vector<SInstanceData> result; std::vector<SInstanceData> result;
try {
if (!std::filesystem::exists(getRuntimeDir()))
return {};
} catch (std::exception& e) { return {}; }
for (const auto& el : std::filesystem::directory_iterator(getRuntimeDir())) { for (const auto& el : std::filesystem::directory_iterator(getRuntimeDir())) {
if (!el.is_directory() || !std::filesystem::exists(el.path().string() + "/hyprland.lock")) if (!el.is_directory() || !std::filesystem::exists(el.path().string() + "/hyprland.lock"))
continue; continue;
@@ -117,7 +105,7 @@ std::vector<SInstanceData> instances() {
static volatile bool sigintReceived = false; static volatile bool sigintReceived = false;
void intHandler(int sig) { void intHandler(int sig) {
sigintReceived = true; sigintReceived = true;
std::println("[hyprctl] SIGINT received, closing connection"); std::cout << "[hyprctl] SIGINT received, closing connection" << std::endl;
} }
int rollingRead(const int socket) { int rollingRead(const int socket) {
@@ -127,12 +115,12 @@ int rollingRead(const int socket) {
constexpr size_t BUFFER_SIZE = 8192; constexpr size_t BUFFER_SIZE = 8192;
std::array<char, BUFFER_SIZE> buffer = {0}; std::array<char, BUFFER_SIZE> buffer = {0};
long sizeWritten = 0; long sizeWritten = 0;
std::println("[hyprctl] reading from socket following up log:"); std::cout << "[hyprctl] reading from socket following up log:" << std::endl;
while (!sigintReceived) { while (!sigintReceived) {
sizeWritten = read(socket, buffer.data(), BUFFER_SIZE); sizeWritten = read(socket, buffer.data(), BUFFER_SIZE);
if (sizeWritten < 0 && errno != EAGAIN) { if (sizeWritten < 0 && errno != EAGAIN) {
if (errno != EINTR) if (errno != EINTR)
std::println("Couldn't read (5): {}: {}", strerror(errno), errno); std::cout << "Couldn't read (5) " << strerror(errno) << ":" << errno << std::endl;
close(socket); close(socket);
return 5; return 5;
} }
@@ -141,7 +129,7 @@ int rollingRead(const int socket) {
break; break;
if (sizeWritten > 0) { if (sizeWritten > 0) {
std::println("{}", std::string(buffer.data(), sizeWritten)); std::cout << std::string(buffer.data(), sizeWritten);
buffer.fill('\0'); buffer.fill('\0');
} }
@@ -174,7 +162,7 @@ int request(std::string arg, int minArgs = 0, bool needRoll = false) {
return 2; return 2;
} }
const std::string USERID = std::to_string(getUID()); const std::string USERID = std::to_string(getpwuid(getuid())->pw_uid);
sockaddr_un serverAddress = {0}; sockaddr_un serverAddress = {0};
serverAddress.sun_family = AF_UNIX; serverAddress.sun_family = AF_UNIX;
@@ -244,7 +232,7 @@ int requestHyprpaper(std::string arg) {
sockaddr_un serverAddress = {0}; sockaddr_un serverAddress = {0};
serverAddress.sun_family = AF_UNIX; serverAddress.sun_family = AF_UNIX;
const std::string USERID = std::to_string(getUID()); const std::string USERID = std::to_string(getpwuid(getuid())->pw_uid);
std::string socketPath = getRuntimeDir() + "/" + instanceSignature + "/.hyprpaper.sock"; std::string socketPath = getRuntimeDir() + "/" + instanceSignature + "/.hyprpaper.sock";
@@ -282,11 +270,10 @@ int requestHyprpaper(std::string arg) {
} }
void batchRequest(std::string arg, bool json) { void batchRequest(std::string arg, bool json) {
std::string commands = arg.substr(arg.find_first_of(' ') + 1); std::string commands = arg.substr(arg.find_first_of(" ") + 1);
if (json) { if (json) {
RE2::GlobalReplace(&commands, ";\\s*", ";j/"); commands = "j/" + std::regex_replace(commands, std::regex(";\\s*"), ";j/");
commands.insert(0, "j/");
} }
std::string rq = "[[BATCH]]" + commands; std::string rq = "[[BATCH]]" + commands;
@@ -300,12 +287,12 @@ void instancesRequest(bool json) {
std::vector<SInstanceData> inst = instances(); std::vector<SInstanceData> inst = instances();
if (!json) { if (!json) {
for (auto const& el : inst) { for (auto& el : inst) {
result += std::format("instance {}:\n\ttime: {}\n\tpid: {}\n\twl socket: {}\n\n", el.id, el.time, el.pid, el.wlSocket); result += std::format("instance {}:\n\ttime: {}\n\tpid: {}\n\twl socket: {}\n\n", el.id, el.time, el.pid, el.wlSocket);
} }
} else { } else {
result += '['; result += '[';
for (auto const& el : inst) { for (auto& el : inst) {
result += std::format(R"#( result += std::format(R"#(
{{ {{
"instance": "{}", "instance": "{}",
@@ -323,11 +310,11 @@ void instancesRequest(bool json) {
log(result + "\n"); log(result + "\n");
} }
std::vector<std::string> splitArgs(int argc, char** argv) { std::deque<std::string> splitArgs(int argc, char** argv) {
std::vector<std::string> result; std::deque<std::string> result;
for (auto i = 1 /* skip the executable */; i < argc; ++i) for (auto i = 1 /* skip the executable */; i < argc; ++i)
result.emplace_back(argv[i]); result.push_back(std::string(argv[i]));
return result; return result;
} }
@@ -336,7 +323,7 @@ int main(int argc, char** argv) {
bool parseArgs = true; bool parseArgs = true;
if (argc < 2) { if (argc < 2) {
std::println("{}", USAGE); std::cout << USAGE << std::endl;
return 1; return 1;
} }
@@ -373,7 +360,7 @@ int main(int argc, char** argv) {
++i; ++i;
if (i >= ARGS.size()) { if (i >= ARGS.size()) {
std::println("{}", USAGE); std::cout << USAGE << std::endl;
return 1; return 1;
} }
@@ -384,24 +371,24 @@ int main(int argc, char** argv) {
const std::string& cmd = ARGS[0]; const std::string& cmd = ARGS[0];
if (cmd == "hyprpaper") { if (cmd == "hyprpaper") {
std::println("{}", HYPRPAPER_HELP); std::cout << HYPRPAPER_HELP << std::endl;
} else if (cmd == "notify") { } else if (cmd == "notify") {
std::println("{}", NOTIFY_HELP); std::cout << NOTIFY_HELP << std::endl;
} else if (cmd == "output") { } else if (cmd == "output") {
std::println("{}", OUTPUT_HELP); std::cout << OUTPUT_HELP << std::endl;
} else if (cmd == "plugin") { } else if (cmd == "plugin") {
std::println("{}", PLUGIN_HELP); std::cout << PLUGIN_HELP << std::endl;
} else if (cmd == "setprop") { } else if (cmd == "setprop") {
std::println("{}", SETPROP_HELP); std::cout << SETPROP_HELP << std::endl;
} else if (cmd == "switchxkblayout") { } else if (cmd == "switchxkblayout") {
std::println("{}", SWITCHXKBLAYOUT_HELP); std::cout << SWITCHXKBLAYOUT_HELP << std::endl;
} else { } else {
std::println("{}", USAGE); std::cout << USAGE << std::endl;
} }
return 1; return 1;
} else { } else {
std::println("{}", USAGE); std::cout << USAGE << std::endl;
return 1; return 1;
} }
@@ -412,7 +399,7 @@ int main(int argc, char** argv) {
} }
if (fullRequest.empty()) { if (fullRequest.empty()) {
std::println("{}", USAGE); std::cout << USAGE << std::endl;
return 1; return 1;
} }
@@ -489,7 +476,7 @@ int main(int argc, char** argv) {
else if (fullRequest.contains("/decorations")) else if (fullRequest.contains("/decorations"))
exitStatus = request(fullRequest, 1); exitStatus = request(fullRequest, 1);
else if (fullRequest.contains("/--help")) else if (fullRequest.contains("/--help"))
std::println("{}", USAGE); std::cout << USAGE << std::endl;
else if (fullRequest.contains("/rollinglog") && needRoll) else if (fullRequest.contains("/rollinglog") && needRoll)
exitStatus = request(fullRequest, 0, true); exitStatus = request(fullRequest, 0, true);
else { else {

View File

@@ -1,27 +1,10 @@
executable( executable('hyprctl', 'main.cpp',
'hyprctl',
'main.cpp',
dependencies: [ dependencies: [
dependency('hyprutils', version: '>= 0.1.1'), dependency('hyprutils', version: '>= 0.1.1'),
dependency('re2', required: true)
], ],
install: true, install: true
) )
install_data( install_data('hyprctl.bash', install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_tag: 'runtime', rename: 'hyprctl')
'hyprctl.bash', install_data('hyprctl.fish', install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), install_tag: 'runtime')
install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_data('hyprctl.zsh', install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), install_tag: 'runtime', rename: '_hyprctl')
install_tag: 'runtime',
rename: 'hyprctl',
)
install_data(
'hyprctl.fish',
install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'),
install_tag: 'runtime',
)
install_data(
'hyprctl.zsh',
install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'),
install_tag: 'runtime',
rename: '_hyprctl',
)

View File

@@ -9,25 +9,11 @@ file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp")
set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD 23)
pkg_check_modules(hyprpm_deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.2.4) pkg_check_modules(deps REQUIRED IMPORTED_TARGET tomlplusplus hyprutils>=0.1.1)
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::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,13 +1,14 @@
#include "DataState.hpp" #include "DataState.hpp"
#include <toml++/toml.hpp> #include <toml++/toml.hpp>
#include <print> #include <iostream>
#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::cerr << "DataState: no $HOME\n";
throw std::runtime_error("no $HOME"); throw std::runtime_error("no $HOME");
return ""; return "";
} }
@@ -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
@@ -65,22 +49,20 @@ void DataState::addNewPluginRepo(const SPluginRepository& repo) {
{"rev", repo.rev} {"rev", repo.rev}
}} }}
}; };
for (auto const& p : repo.plugins) { for (auto& 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,8 +72,15 @@ 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")
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("");
@@ -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")
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("");
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,9 +9,8 @@ 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);

View File

@@ -6,7 +6,7 @@ CManifest::CManifest(const eManifestType type, const std::string& path) {
auto manifest = toml::parse_file(path); auto manifest = toml::parse_file(path);
if (type == MANIFEST_HYPRLOAD) { if (type == MANIFEST_HYPRLOAD) {
for (auto const& [key, val] : manifest) { for (auto& [key, val] : manifest) {
if (key.str().ends_with(".build")) if (key.str().ends_with(".build"))
continue; continue;
@@ -63,7 +63,7 @@ CManifest::CManifest(const eManifestType type, const std::string& path) {
} }
} }
for (auto const& [key, val] : manifest) { for (auto& [key, val] : manifest) {
if (key.str() == "repository") if (key.str() == "repository")
continue; continue;

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,6 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <utility>
enum eHeadersErrors { enum eHeadersErrors {
HEADERS_OK = 0, HEADERS_OK = 0,
@@ -27,8 +26,7 @@ enum ePluginLoadStateReturn {
LOADSTATE_OK = 0, LOADSTATE_OK = 0,
LOADSTATE_FAIL, LOADSTATE_FAIL,
LOADSTATE_PARTIAL_FAIL, LOADSTATE_PARTIAL_FAIL,
LOADSTATE_HEADERS_OUTDATED, LOADSTATE_HEADERS_OUTDATED
LOADSTATE_HYPRLAND_UPDATED
}; };
struct SHyprlandVersion { struct SHyprlandVersion {
@@ -51,10 +49,10 @@ 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();
void notify(const eNotifyIcons icon, uint32_t color, int durationMs, const std::string& message); void notify(const eNotifyIcons icon, uint32_t color, int durationMs, const std::string& message);
@@ -70,7 +68,7 @@ class CPluginManager {
std::string headerError(const eHeadersErrors err); std::string headerError(const eHeadersErrors err);
std::string headerErrorShort(const eHeadersErrors err); std::string headerErrorShort(const eHeadersErrors err);
std::string m_szWorkingPluginDirectory; std::string m_szWorkingPluginDirectory = "";
}; };
inline std::unique_ptr<CPluginManager> g_pPluginManager; inline std::unique_ptr<CPluginManager> g_pPluginManager;

View File

@@ -1,32 +0,0 @@
#pragma once
#include <format>
#include <string>
#include "Colors.hpp"
template <typename... Args>
std::string statusString(const std::string_view emoji, const std::string_view color, const std::string_view fmt, Args&&... args) {
std::string ret = std::format("{}{}{} ", color, emoji, Colors::RESET);
ret += std::vformat(fmt, std::make_format_args(args...));
return ret;
}
template <typename... Args>
std::string successString(const std::string_view fmt, Args&&... args) {
return statusString("", Colors::GREEN, fmt, args...);
}
template <typename... Args>
std::string failureString(const std::string_view fmt, Args&&... args) {
return statusString("", Colors::RED, fmt, args...);
}
template <typename... Args>
std::string verboseString(const std::string_view fmt, Args&&... args) {
return statusString("[v]", Colors::BLUE, fmt, args...);
}
template <typename... Args>
std::string infoString(const std::string_view fmt, Args&&... args) {
return statusString("", Colors::RESET, fmt, args...);
}

View File

@@ -1,16 +1,15 @@
#include "progress/CProgressBar.hpp"
#include "helpers/Colors.hpp" #include "helpers/Colors.hpp"
#include "helpers/StringUtils.hpp"
#include "core/PluginManager.hpp" #include "core/PluginManager.hpp"
#include "core/DataState.hpp" #include "core/DataState.hpp"
#include <cstdio> #include <iostream>
#include <vector> #include <vector>
#include <string> #include <string>
#include <print>
#include <chrono> #include <chrono>
#include <thread> #include <thread>
constexpr std::string_view HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager
add [url] [git rev] Install a new plugin repository from git. Git revision add [url] [git rev] Install a new plugin repository from git. Git revision
is optional, when set, commit locks are ignored. is optional, when set, commit locks are ignored.
@@ -23,8 +22,7 @@ constexpr std::string_view HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager
Flags: Flags:
--notify | -n Send a hyprland notification for important events (including both successes and fail events) --notify | -n Send a hyprland notification for important events (e.g. load fail)
--notify-fail | -nn Send a hyprland notification for fail events only
--help | -h Show this menu --help | -h Show this menu
--verbose | -v Enable too much logging --verbose | -v Enable too much logging
--force | -f Force an operation ignoring checks (e.g. update -f) --force | -f Force an operation ignoring checks (e.g. update -f)
@@ -39,31 +37,29 @@ int main(int argc, char** argv, char** envp) {
} }
if (ARGS.size() < 2) { if (ARGS.size() < 2) {
std::println(stderr, "{}", HELP); std::cout << HELP;
return 1; return 1;
} }
std::vector<std::string> command; std::vector<std::string> command;
bool notify = false, notifyFail = false, verbose = false, force = false, noShallow = false; bool notify = false, verbose = false, force = false, noShallow = false;
for (int i = 1; i < argc; ++i) { for (int i = 1; i < argc; ++i) {
if (ARGS[i].starts_with("-")) { if (ARGS[i].starts_with("-")) {
if (ARGS[i] == "--help" || ARGS[i] == "-h") { if (ARGS[i] == "--help" || ARGS[i] == "-h") {
std::println("{}", HELP); std::cout << HELP;
return 0; return 0;
} else if (ARGS[i] == "--notify" || ARGS[i] == "-n") { } else if (ARGS[i] == "--notify" || ARGS[i] == "-n") {
notify = true; notify = true;
} else if (ARGS[i] == "--notify-fail" || ARGS[i] == "-nn") {
notifyFail = notify = true;
} else if (ARGS[i] == "--verbose" || ARGS[i] == "-v") { } else if (ARGS[i] == "--verbose" || ARGS[i] == "-v") {
verbose = true; verbose = true;
} else if (ARGS[i] == "--no-shallow" || ARGS[i] == "-s") { } else if (ARGS[i] == "--no-shallow" || ARGS[i] == "-s") {
noShallow = true; noShallow = true;
} else if (ARGS[i] == "--force" || ARGS[i] == "-f") { } else if (ARGS[i] == "--force" || ARGS[i] == "-f") {
force = true; force = true;
std::println("{}", statusString("!", Colors::RED, "Using --force, I hope you know what you are doing.")); std::cout << Colors::RED << "!" << Colors::RESET << " Using --force, I hope you know what you are doing.\n";
} else { } else {
std::println(stderr, "Unrecognized option {}", ARGS[i]); std::cerr << "Unrecognized option " << ARGS[i] << "\n";
return 1; return 1;
} }
} else { } else {
@@ -72,8 +68,8 @@ int main(int argc, char** argv, char** envp) {
} }
if (command.empty()) { if (command.empty()) {
std::println(stderr, "{}", HELP); std::cout << HELP;
return 1; return 0;
} }
g_pPluginManager = std::make_unique<CPluginManager>(); g_pPluginManager = std::make_unique<CPluginManager>();
@@ -82,7 +78,7 @@ int main(int argc, char** argv, char** envp) {
if (command[0] == "add") { if (command[0] == "add") {
if (command.size() < 2) { if (command.size() < 2) {
std::println(stderr, "{}", failureString("Not enough args for add.")); std::cerr << Colors::RED << "" << Colors::RESET << " Not enough args for add.\n";
return 1; return 1;
} }
@@ -94,7 +90,7 @@ int main(int argc, char** argv, char** envp) {
return g_pPluginManager->addNewPluginRepo(command[1], rev) ? 0 : 1; return g_pPluginManager->addNewPluginRepo(command[1], rev) ? 0 : 1;
} else if (command[0] == "remove") { } else if (command[0] == "remove") {
if (ARGS.size() < 2) { if (ARGS.size() < 2) {
std::println(stderr, "{}", failureString("Not enough args for remove.")); std::cerr << Colors::RED << "" << Colors::RESET << " Not enough args for remove.\n";
return 1; return 1;
} }
@@ -103,7 +99,7 @@ int main(int argc, char** argv, char** envp) {
bool headersValid = g_pPluginManager->headersValid() == HEADERS_OK; bool headersValid = g_pPluginManager->headersValid() == HEADERS_OK;
bool headers = g_pPluginManager->updateHeaders(force); bool headers = g_pPluginManager->updateHeaders(force);
if (headers) { if (headers) {
const auto HLVER = g_pPluginManager->getHyprlandVersion(false); const auto HLVER = g_pPluginManager->getHyprlandVersion();
auto GLOBALSTATE = DataState::getGlobalState(); auto GLOBALSTATE = DataState::getGlobalState();
const auto COMPILEDOUTDATED = HLVER.hash != GLOBALSTATE.headersHashCompiled; const auto COMPILEDOUTDATED = HLVER.hash != GLOBALSTATE.headersHashCompiled;
@@ -114,39 +110,32 @@ int main(int argc, char** argv, char** envp) {
auto ret2 = g_pPluginManager->ensurePluginsLoadState(); auto ret2 = g_pPluginManager->ensurePluginsLoadState();
if (ret2 == LOADSTATE_HYPRLAND_UPDATED)
g_pPluginManager->notify(ICON_INFO, 0, 10000, "[hyprpm] Updated plugins, but Hyprland was updated. Please restart Hyprland.");
if (ret2 != LOADSTATE_OK) if (ret2 != LOADSTATE_OK)
return 1; return 1;
} else if (notify) } else if (notify)
g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Couldn't update headers"); g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Couldn't update headers");
} else if (command[0] == "enable") { } else if (command[0] == "enable") {
if (ARGS.size() < 2) { if (ARGS.size() < 2) {
std::println(stderr, "{}", failureString("Not enough args for enable.")); std::cerr << Colors::RED << "" << Colors::RESET << " Not enough args for enable.\n";
return 1; return 1;
} }
if (!g_pPluginManager->enablePlugin(command[1])) { if (!g_pPluginManager->enablePlugin(command[1])) {
std::println(stderr, "{}", failureString("Couldn't enable plugin (missing?)")); std::cerr << Colors::RED << "" << Colors::RESET << " Couldn't enable plugin (missing?)\n";
return 1; return 1;
} }
auto ret = g_pPluginManager->ensurePluginsLoadState(); auto ret = g_pPluginManager->ensurePluginsLoadState();
if (ret == LOADSTATE_HYPRLAND_UPDATED)
g_pPluginManager->notify(ICON_INFO, 0, 10000, "[hyprpm] Enabled plugin, but Hyprland was updated. Please restart Hyprland.");
if (ret != LOADSTATE_OK) if (ret != LOADSTATE_OK)
return 1; return 1;
} else if (command[0] == "disable") { } else if (command[0] == "disable") {
if (command.size() < 2) { if (command.size() < 2) {
std::println(stderr, "{}", failureString("Not enough args for disable.")); std::cerr << Colors::RED << "" << Colors::RESET << " Not enough args for disable.\n";
return 1; return 1;
} }
if (!g_pPluginManager->disablePlugin(command[1])) { if (!g_pPluginManager->disablePlugin(command[1])) {
std::println(stderr, "{}", failureString("Couldn't disable plugin (missing?)")); std::cerr << Colors::RED << "" << Colors::RESET << " Couldn't disable plugin (missing?)\n";
return 1; return 1;
} }
@@ -154,7 +143,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) {
@@ -165,14 +154,13 @@ int main(int argc, char** argv, char** envp) {
break; break;
default: break; default: break;
} }
return 1; } else if (notify) {
} else if (notify && !notifyFail) {
g_pPluginManager->notify(ICON_OK, 0, 4000, "[hyprpm] Loaded plugins"); g_pPluginManager->notify(ICON_OK, 0, 4000, "[hyprpm] Loaded plugins");
} }
} else if (command[0] == "list") { } else if (command[0] == "list") {
g_pPluginManager->listAllPlugins(); g_pPluginManager->listAllPlugins();
} else { } else {
std::println(stderr, "{}", HELP); std::cout << HELP;
return 1; return 1;
} }

View File

@@ -1,32 +1,15 @@
globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true) globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true)
src = globber.stdout().strip().split('\n') src = globber.stdout().strip().split('\n')
executable( executable('hyprpm', src,
'hyprpm',
src,
dependencies: [ dependencies: [
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
) )
install_data( install_data('../hyprpm.bash', install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_tag: 'runtime', rename: 'hyprpm')
'../hyprpm.bash', install_data('../hyprpm.fish', install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'), install_tag: 'runtime')
install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'), install_data('../hyprpm.zsh', install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'), install_tag: 'runtime', rename: '_hyprpm')
install_tag: 'runtime',
rename: 'hyprpm',
)
install_data(
'../hyprpm.fish',
install_dir: join_paths(get_option('datadir'), 'fish/vendor_completions.d'),
install_tag: 'runtime',
)
install_data(
'../hyprpm.zsh',
install_dir: join_paths(get_option('datadir'), 'zsh/site-functions'),
install_tag: 'runtime',
rename: '_hyprpm',
)

View File

@@ -1,11 +1,11 @@
#include "CProgressBar.hpp" #include "CProgressBar.hpp"
#include <sys/ioctl.h> #include <iostream>
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <format> #include <format>
#include <print> #include <sys/ioctl.h>
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
@@ -16,12 +16,11 @@ void CProgressBar::printMessageAbove(const std::string& msg) {
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
std::string spaces; std::string spaces;
spaces.reserve(w.ws_col);
for (size_t i = 0; i < w.ws_col; ++i) { for (size_t i = 0; i < w.ws_col; ++i) {
spaces += ' '; spaces += ' ';
} }
std::println("\r{}\r{}", spaces, msg); std::cout << "\r" << spaces << "\r" << msg << "\n";
print(); print();
} }
@@ -30,16 +29,15 @@ void CProgressBar::print() {
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
if (m_bFirstPrint) if (m_bFirstPrint)
std::print("\n"); std::cout << "\n";
m_bFirstPrint = false; m_bFirstPrint = false;
std::string spaces; std::string spaces;
spaces.reserve(w.ws_col);
for (size_t i = 0; i < w.ws_col; ++i) { for (size_t i = 0; i < w.ws_col; ++i) {
spaces += ' '; spaces += ' ';
} }
std::print("\r{}\r", spaces); std::cout << "\r" << spaces << "\r";
std::string message = ""; std::string message = "";
@@ -76,7 +74,7 @@ void CProgressBar::print() {
message += " " + std::format("{} / {}", m_iSteps, m_iMaxSteps) + " "; message += " " + std::format("{} / {}", m_iSteps, m_iMaxSteps) + " ";
// draw message // draw message
std::print("{} {}", message, m_szCurrentMessage); std::cout << message + " " + m_szCurrentMessage;
std::fflush(stdout); std::fflush(stdout);
} }

View File

@@ -1,8 +1,5 @@
project( project('Hyprland', 'cpp', 'c',
'Hyprland', version : run_command('cat', join_paths(meson.source_root(), 'VERSION'), check: true).stdout().strip(),
'cpp',
'c',
version: run_command('cat', join_paths(meson.project_source_root(), 'VERSION'), check: true).stdout().strip(),
default_options : [ default_options : [
'warning_level=2', 'warning_level=2',
'default_library=static', 'default_library=static',
@@ -10,8 +7,7 @@ project(
'buildtype=release', 'buildtype=release',
'debug=false', 'debug=false',
'cpp_std=c++26', 'cpp_std=c++26',
], ])
)
datarootdir = '-DDATAROOTDIR="' + get_option('prefix') / get_option('datadir') + '"' datarootdir = '-DDATAROOTDIR="' + get_option('prefix') / get_option('datadir') + '"'
add_project_arguments( add_project_arguments(
@@ -20,28 +16,16 @@ add_project_arguments(
'-Wno-unused-value', '-Wno-unused-value',
'-Wno-missing-field-initializers', '-Wno-missing-field-initializers',
'-Wno-narrowing', '-Wno-narrowing',
'-Wno-pointer-arith', datarootdir, '-Wno-pointer-arith',
'-DHYPRLAND_VERSION="' + meson.project_version() + '"', datarootdir,
], ],
language: 'cpp', language: 'cpp')
)
cpp_compiler = meson.get_compiler('cpp') cpp_compiler = meson.get_compiler('cpp')
if cpp_compiler.check_header('execinfo.h') if cpp_compiler.check_header('execinfo.h')
add_project_arguments('-DHAS_EXECINFO', language: 'cpp') add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
endif endif
aquamarine = dependency('aquamarine', version: '>=0.4.5')
hyprcursor = dependency('hyprcursor', version: '>=0.1.7')
hyprgraphics = dependency('hyprgraphics', version: '>= 0.1.1')
hyprlang = dependency('hyprlang', version: '>= 0.3.2')
hyprutils = dependency('hyprutils', version: '>= 0.2.3')
add_project_arguments(['-DAQUAMARINE_VERSION="@0@"'.format(aquamarine.version())], language: 'cpp')
add_project_arguments(['-DHYPRCURSOR_VERSION="@0@"'.format(hyprcursor.version())], language: 'cpp')
add_project_arguments(['-DHYPRGRAPHICS_VERSION="@0@"'.format(hyprgraphics.version())], language: 'cpp')
add_project_arguments(['-DHYPRLANG_VERSION="@0@"'.format(hyprlang.version())], language: 'cpp')
add_project_arguments(['-DHYPRUTILS_VERSION="@0@"'.format(hyprutils.version())], language: 'cpp')
xcb_dep = dependency('xcb', required: get_option('xwayland')) xcb_dep = dependency('xcb', required: get_option('xwayland'))
xcb_composite_dep = dependency('xcb-composite', required: get_option('xwayland')) xcb_composite_dep = dependency('xcb-composite', required: get_option('xwayland'))
xcb_errors_dep = dependency('xcb-errors', required: get_option('xwayland')) xcb_errors_dep = dependency('xcb-errors', required: get_option('xwayland'))
@@ -52,25 +36,19 @@ xcb_xfixes_dep = dependency('xcb-xfixes', required: get_option('xwayland'))
gio_dep = dependency('gio-2.0', required:true) gio_dep = dependency('gio-2.0', required:true)
cmake = import('cmake')
udis = cmake.subproject('udis86')
udis86 = udis.dependency('libudis86')
if not xcb_dep.found() if not xcb_dep.found()
add_project_arguments('-DNO_XWAYLAND', language: 'cpp') add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
endif 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) if get_option('systemd').enabled()
# Handle options
systemd_option = get_option('systemd')
systemd = dependency('systemd', required: systemd_option)
systemd_option.enable_auto_if(systemd.found())
if (systemd_option.enabled())
message('Enabling systemd integration')
add_project_arguments('-DUSES_SYSTEMD', language: 'cpp') add_project_arguments('-DUSES_SYSTEMD', language: 'cpp')
subdir('systemd')
endif endif
if get_option('legacy_renderer').enabled() if get_option('legacy_renderer').enabled()
@@ -81,36 +59,22 @@ if get_option('buildtype') == 'debug'
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp') add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
endif endif
# Generate hyprland version and populate version.h version_h = run_command('sh', '-c', 'scripts/generateVersion.sh', check: true)
run_command('sh', '-c', 'scripts/generateVersion.sh', check: true)
# Install headers
globber = run_command('find', 'src', '-name', '*.h*', check: true) globber = run_command('find', 'src', '-name', '*.h*', check: true)
headers = globber.stdout().strip().split('\n') headers = globber.stdout().strip().split('\n')
foreach file : headers foreach file : headers
install_headers(file, subdir: 'hyprland', preserve_path: true) install_headers(file, subdir: 'hyprland', preserve_path: true)
endforeach endforeach
tracy = dependency('tracy', static: true, required: get_option('tracy_enable'))
if get_option('tracy_enable') and get_option('buildtype') != 'debugoptimized'
warning('Profiling builds should set -- buildtype = debugoptimized')
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
pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig') pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig')
import('pkgconfig').generate( import('pkgconfig').generate(

View File

@@ -1,6 +1,3 @@
option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications') option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications')
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('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')

View File

@@ -1,38 +1,43 @@
{ {
lib, lib,
stdenv, stdenv,
stdenvAdapters,
pkg-config, pkg-config,
pkgconf, pkgconf,
makeWrapper, makeWrapper,
cmake, cmake,
meson,
ninja, ninja,
aquamarine, aquamarine,
binutils, binutils,
cairo, cairo,
expat,
fribidi,
git, git,
glaze, hwdata,
hyprcursor, hyprcursor,
hyprgraphics,
hyprland-protocols,
hyprland-qtutils,
hyprlang, hyprlang,
hyprutils, hyprutils,
hyprwayland-scanner, hyprwayland-scanner,
jq,
libGL, libGL,
libdatrie,
libdisplay-info,
libdrm, libdrm,
libexecinfo, libexecinfo,
libinput, libinput,
libxkbcommon, libliftoff,
libselinux,
libsepol,
libthai,
libuuid, libuuid,
libxkbcommon,
mesa, mesa,
pango, pango,
pciutils, pciutils,
re2, pcre2,
python3,
seatd,
systemd, systemd,
tomlplusplus, tomlplusplus,
udis86-hyprland,
wayland, wayland,
wayland-protocols, wayland-protocols,
wayland-scanner, wayland-scanner,
@@ -45,42 +50,32 @@
wrapRuntimeDeps ? true, wrapRuntimeDeps ? true,
version ? "git", version ? "git",
commit, commit,
revCount,
date, date,
# deprecated flags # deprecated flags
enableNvidiaPatches ? false, enableNvidiaPatches ? false,
nvidiaPatches ? false, nvidiaPatches ? false,
hidpiXWayland ? false, hidpiXWayland ? false,
}: let }:
inherit (builtins) baseNameOf foldl' readFile; assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed.";
inherit (lib.asserts) assertMsg; assert lib.assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed.";
inherit (lib.attrsets) mapAttrsToList; assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland";
inherit (lib.lists) flatten concatLists optional optionals; stdenv.mkDerivation {
inherit (lib.sources) cleanSourceWith cleanSource; pname = "hyprland${lib.optionalString debug "-debug"}";
inherit (lib.strings) hasSuffix makeBinPath optionalString mesonBool mesonEnable trim;
adapters = flatten [
stdenvAdapters.useMoldLinker
(lib.optional debug stdenvAdapters.keepDebugInfo)
];
customStdenv = foldl' (acc: adapter: adapter acc) stdenv adapters;
in
assert assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed.";
assert assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed.";
assert assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland";
customStdenv.mkDerivation (finalAttrs: {
pname = "hyprland${optionalString debug "-debug"}";
inherit version; inherit version;
src = cleanSourceWith { src = lib.cleanSourceWith {
filter = name: _type: let filter = name: type: let
baseName = baseNameOf (toString name); baseName = baseNameOf (toString name);
in in
! (hasSuffix ".nix" baseName); ! (lib.hasSuffix ".nix" baseName);
src = cleanSource ../.; src = lib.cleanSource ../.;
}; };
patches = [
# forces GCC to use -std=c++26
./stdcxx.patch
];
postPatch = '' postPatch = ''
# Fix hardcoded paths to /usr installation # Fix hardcoded paths to /usr installation
sed -i "s#/usr#$out#" src/render/OpenGL.cpp sed -i "s#/usr#$out#" src/render/OpenGL.cpp
@@ -89,23 +84,21 @@ in
sed -i "s#@PREFIX@/##g" hyprland.pc.in sed -i "s#@PREFIX@/##g" hyprland.pc.in
''; '';
COMMITS = revCount; COMMITS = commit;
DATE = date; DATE = date;
DIRTY = optionalString (commit == "") "dirty"; DIRTY = lib.optionalString (commit == "") "dirty";
HASH = commit; HASH = commit;
TAG = "v${trim (readFile "${finalAttrs.src}/VERSION")}";
depsBuildBuild = [
pkg-config
];
nativeBuildInputs = [ nativeBuildInputs = [
hyprwayland-scanner hyprwayland-scanner
jq
makeWrapper makeWrapper
meson cmake
ninja ninja
cmake # needed for glaze
pkg-config pkg-config
python3 # for udis86
# re-add after https://github.com/NixOS/nixpkgs/pull/214906 hits nixos-unstable
# wayland-scanner
]; ];
outputs = [ outputs = [
@@ -114,69 +107,70 @@ in
"dev" "dev"
]; ];
buildInputs = concatLists [ buildInputs = lib.concatLists [
[ [
aquamarine aquamarine
cairo cairo
expat
fribidi
git git
glaze hwdata
hyprcursor hyprcursor
hyprgraphics
hyprland-protocols
hyprlang hyprlang
hyprutils hyprutils
libdatrie
libdisplay-info
libdrm libdrm
libGL libGL
libinput libinput
libliftoff
libselinux
libsepol
libthai
libuuid libuuid
libxkbcommon libxkbcommon
mesa mesa
pango pango
pciutils pciutils
re2 pcre2
seatd
tomlplusplus tomlplusplus
udis86-hyprland
wayland wayland
wayland-protocols wayland-protocols
wayland-scanner
xorg.libXcursor xorg.libXcursor
] ]
(optionals customStdenv.hostPlatform.isMusl [libexecinfo]) (lib.optionals stdenv.hostPlatform.isMusl [libexecinfo])
(optionals enableXWayland [ (lib.optionals enableXWayland [
xorg.libxcb xorg.libxcb
xorg.libXdmcp xorg.libXdmcp
xorg.xcbutil
xorg.xcbutilerrors xorg.xcbutilerrors
xorg.xcbutilrenderutil xorg.xcbutilrenderutil
xorg.xcbutilwm xorg.xcbutilwm
xwayland xwayland
]) ])
(optional withSystemd systemd) (lib.optionals withSystemd [systemd])
]; ];
mesonBuildType = cmakeBuildType =
if debug if debug
then "debugoptimized" then "Debug"
else "release"; else "RelWithDebInfo";
mesonFlags = flatten [ # we want as much debug info as possible
(mapAttrsToList mesonEnable { dontStrip = debug;
"xwayland" = enableXWayland;
"legacy_renderer" = legacyRenderer; cmakeFlags = [
"uwsm" = false; (lib.cmakeBool "NO_XWAYLAND" (!enableXWayland))
"hyprpm" = false; (lib.cmakeBool "LEGACY_RENDERER" legacyRenderer)
}) (lib.cmakeBool "NO_SYSTEMD" (!withSystemd))
(mapAttrsToList mesonBool {
"b_pch" = false;
"tracy_enable" = false;
})
]; ];
postInstall = '' postInstall = ''
${optionalString wrapRuntimeDeps '' ${lib.optionalString wrapRuntimeDeps ''
wrapProgram $out/bin/Hyprland \ wrapProgram $out/bin/Hyprland \
--suffix PATH : ${makeBinPath [ --suffix PATH : ${lib.makeBinPath [
binutils binutils
hyprland-qtutils
pciutils pciutils
pkgconf pkgconf
]} ]}
@@ -192,4 +186,4 @@ in
platforms = lib.platforms.linux; platforms = lib.platforms.linux;
mainProgram = "Hyprland"; mainProgram = "Hyprland";
}; };
}) }

View File

@@ -1,64 +0,0 @@
{
writeShellApplication,
deadnix,
statix,
alejandra,
llvmPackages_19,
fd,
}:
writeShellApplication {
name = "hyprland-treewide-formatter";
runtimeInputs = [
deadnix
statix
alejandra
llvmPackages_19.clang-tools
fd
];
text = ''
# shellcheck disable=SC2148
# common excludes
excludes="subprojects"
nix_format() {
if [ "$*" = 0 ]; then
fd '.*\.nix' . -E "$excludes" -x statix fix -- {} \;
fd '.*\.nix' . -E "$excludes" -X deadnix -e -- {} \; -X alejandra {} \;
elif [ -d "$1" ]; then
fd '.*\.nix' "$1" -E "$excludes" -i -x statix fix -- {} \;
fd '.*\.nix' "$1" -E "$excludes" -i -X deadnix -e -- {} \; -X alejandra {} \;
else
statix fix -- "$1"
deadnix -e "$1"
alejandra "$1"
fi
}
cpp_format() {
if [ "$*" = 0 ] || [ "$1" = "." ]; then
fd '.*\.cpp' . -E "$excludes" | xargs clang-format --verbose -i
elif [ -d "$1" ]; then
fd '.*\.cpp' "$1" -E "$excludes" | xargs clang-format --verbose -i
else
clang-format --verbose -i "$1"
fi
}
for i in "$@"; do
case ''${i##*.} in
"nix")
nix_format "$i"
;;
"cpp")
cpp_format "$i"
;;
*)
nix_format "$i"
cpp_format "$i"
;;
esac
done
'';
}

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,
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 {
options = {
programs.hyprland = {
plugins = lib.mkOption {
type = with lib.types; listOf (either package path);
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; hyprland = cfg.finalPackage;
}); };
in {
config = {
programs.hyprland = {
package = lib.mkDefault package;
portalPackage = lib.mkDefault portalPackage;
};
}; };
} }
(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

@@ -22,33 +22,22 @@ in {
# Dependencies # Dependencies
inputs.aquamarine.overlays.default inputs.aquamarine.overlays.default
inputs.hyprcursor.overlays.default inputs.hyprcursor.overlays.default
inputs.hyprgraphics.overlays.default
inputs.hyprland-protocols.overlays.default
inputs.hyprland-qtutils.overlays.default
inputs.hyprlang.overlays.default inputs.hyprlang.overlays.default
inputs.hyprutils.overlays.default inputs.hyprutils.overlays.default
inputs.hyprwayland-scanner.overlays.default inputs.hyprwayland-scanner.overlays.default
self.overlays.udis86
# Hyprland packages themselves # Hyprland packages themselves
(final: _prev: let (final: prev: let
date = mkDate (self.lastModifiedDate or "19700101"); date = mkDate (self.lastModifiedDate or "19700101");
in { in {
hyprland = final.callPackage ./default.nix { hyprland = final.callPackage ./default.nix {
stdenv = final.gcc14Stdenv; stdenv = final.gcc14Stdenv;
version = "${version}+date=${date}_${self.shortRev or "dirty"}"; version = "${version}+date=${date}_${self.shortRev or "dirty"}";
commit = self.rev or ""; commit = self.rev or "";
revCount = self.sourceInfo.revCount or "";
inherit date; inherit date;
}; };
hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;}; hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;};
hyprland-debug = final.hyprland.override {debug = true;};
# Build major libs with debug to get as much info as possible in a stacktrace
hyprland-debug = final.hyprland.override {
aquamarine = final.aquamarine.override {debug = true;};
hyprutils = final.hyprutils.override {debug = true;};
debug = true;
};
hyprland-legacy-renderer = final.hyprland.override {legacyRenderer = true;}; hyprland-legacy-renderer = final.hyprland.override {legacyRenderer = true;};
# deprecated packages # deprecated packages
@@ -71,22 +60,6 @@ in {
# Packages for extra software recommended for usage with Hyprland, # Packages for extra software recommended for usage with Hyprland,
# including forked or patched packages for compatibility. # including forked or patched packages for compatibility.
hyprland-extras = lib.composeManyExtensions [ hyprland-extras = lib.composeManyExtensions [
inputs.xdph.overlays.default inputs.xdph.overlays.xdg-desktop-portal-hyprland
]; ];
# udis86 from nixpkgs is too old, and also does not provide a .pc file
# this version is the one used in the git submodule, and allows us to
# fetch the source without '?submodules=1'
udis86 = final: prev: {
udis86-hyprland = prev.udis86.overrideAttrs (_self: _super: {
src = final.fetchFromGitHub {
owner = "canihavesomecoffee";
repo = "udis86";
rev = "5336633af70f3917760a6d441ff02d93477b0c86";
hash = "sha256-HifdUQPGsKQKQprByeIznvRLONdOXeolOsU5nkwIv3g=";
};
patches = [];
});
};
} }

12
nix/stdcxx.patch Normal file
View File

@@ -0,0 +1,12 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cfbd431f..73e8e0c2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -64,6 +64,7 @@ endif()
include_directories(. "src/" "subprojects/udis86/" "protocols/")
set(CMAKE_CXX_STANDARD 26)
add_compile_options(
+ -std=c++26
-Wall
-Wextra
-Wno-unused-parameter

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

@@ -1,82 +1,76 @@
wayland_protos = dependency( wayland_protos = dependency('wayland-protocols',
'wayland-protocols',
version: '>=1.32', version: '>=1.32',
fallback: 'wayland-protocols', fallback: 'wayland-protocols',
default_options: ['tests=false'], default_options: ['tests=false'],
) )
hyprland_protos = dependency( hyprland_protos = dependency('hyprland-protocols',
'hyprland-protocols', version: '>=0.2',
version: '>=0.6',
fallback: 'hyprland-protocols', fallback: 'hyprland-protocols',
) )
wayland_protocol_dir = wayland_protos.get_variable('pkgdatadir') wl_protocol_dir = wayland_protos.get_variable('pkgdatadir')
hyprland_protocol_dir = hyprland_protos.get_variable('pkgdatadir') hl_protocol_dir = hyprland_protos.get_variable('pkgdatadir')
hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.10', native: true) hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.8', native: true)
hyprwayland_scanner = find_program( hyprwayland_scanner = find_program(
hyprwayland_scanner_dep.get_variable('hyprwayland_scanner'), hyprwayland_scanner_dep.get_variable('hyprwayland_scanner'),
native: true, native: true,
) )
protocols = [ new_protocols = [
'wlr-gamma-control-unstable-v1.xml', ['wlr-gamma-control-unstable-v1.xml'],
'wlr-foreign-toplevel-management-unstable-v1.xml', ['wlr-foreign-toplevel-management-unstable-v1.xml'],
'wlr-output-power-management-unstable-v1.xml', ['wlr-output-power-management-unstable-v1.xml'],
'input-method-unstable-v2.xml', ['input-method-unstable-v2.xml'],
'virtual-keyboard-unstable-v1.xml', ['virtual-keyboard-unstable-v1.xml'],
'wlr-virtual-pointer-unstable-v1.xml', ['wlr-virtual-pointer-unstable-v1.xml'],
'wlr-output-management-unstable-v1.xml', ['wlr-output-management-unstable-v1.xml'],
'kde-server-decoration.xml', ['kde-server-decoration.xml'],
'wlr-layer-shell-unstable-v1.xml', ['wlr-layer-shell-unstable-v1.xml'],
'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', [hl_protocol_dir, 'protocols/hyprland-global-shortcuts-v1.xml'],
'frog-color-management-v1.xml', [hl_protocol_dir, 'protocols/hyprland-toplevel-export-v1.xml'],
hyprland_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml', [hl_protocol_dir, 'protocols/hyprland-focus-grab-v1.xml'],
hyprland_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml', [wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'],
hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml', [wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'],
hyprland_protocol_dir / 'protocols/hyprland-ctm-control-v1.xml', [wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'],
hyprland_protocol_dir / 'protocols/hyprland-surface-v1.xml', [wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml'],
hyprland_protocol_dir / 'protocols/hyprland-lock-notify-v1.xml', [wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'],
wayland_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml', [wl_protocol_dir, 'unstable/relative-pointer/relative-pointer-unstable-v1.xml'],
wayland_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml', [wl_protocol_dir, 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml'],
wayland_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml', [wl_protocol_dir, 'staging/alpha-modifier/alpha-modifier-v1.xml'],
wayland_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml', [wl_protocol_dir, 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml'],
wayland_protocol_dir / 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml', [wl_protocol_dir, 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml'],
wayland_protocol_dir / 'unstable/relative-pointer/relative-pointer-unstable-v1.xml', [wl_protocol_dir, 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml'],
wayland_protocol_dir / 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml', [wl_protocol_dir, 'unstable/text-input/text-input-unstable-v3.xml'],
wayland_protocol_dir / 'staging/alpha-modifier/alpha-modifier-v1.xml', [wl_protocol_dir, 'unstable/text-input/text-input-unstable-v1.xml'],
wayland_protocol_dir / 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml', [wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'],
wayland_protocol_dir / 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml', [wl_protocol_dir, 'staging/xdg-activation/xdg-activation-v1.xml'],
wayland_protocol_dir / 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml', [wl_protocol_dir, 'staging/ext-idle-notify/ext-idle-notify-v1.xml'],
wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v3.xml', [wl_protocol_dir, 'staging/ext-session-lock/ext-session-lock-v1.xml'],
wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v1.xml', [wl_protocol_dir, 'stable/tablet/tablet-v2.xml'],
wayland_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml', [wl_protocol_dir, 'stable/presentation-time/presentation-time.xml'],
wayland_protocol_dir / 'staging/xdg-activation/xdg-activation-v1.xml', [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
wayland_protocol_dir / 'staging/ext-idle-notify/ext-idle-notify-v1.xml', [wl_protocol_dir, 'unstable/primary-selection/primary-selection-unstable-v1.xml'],
wayland_protocol_dir / 'staging/ext-session-lock/ext-session-lock-v1.xml', [wl_protocol_dir, 'staging/xwayland-shell/xwayland-shell-v1.xml'],
wayland_protocol_dir / 'stable/tablet/tablet-v2.xml', [wl_protocol_dir, 'stable/viewporter/viewporter.xml'],
wayland_protocol_dir / 'stable/presentation-time/presentation-time.xml', [wl_protocol_dir, 'stable/linux-dmabuf/linux-dmabuf-v1.xml'],
wayland_protocol_dir / 'stable/xdg-shell/xdg-shell.xml', [wl_protocol_dir, 'staging/drm-lease/drm-lease-v1.xml'],
wayland_protocol_dir / 'unstable/primary-selection/primary-selection-unstable-v1.xml', [wl_protocol_dir, 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml'],
wayland_protocol_dir / 'staging/xwayland-shell/xwayland-shell-v1.xml',
wayland_protocol_dir / 'stable/viewporter/viewporter.xml',
wayland_protocol_dir / 'stable/linux-dmabuf/linux-dmabuf-v1.xml',
wayland_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml',
wayland_protocol_dir / 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml',
wayland_protocol_dir / 'staging/xdg-dialog/xdg-dialog-v1.xml',
wayland_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml',
wayland_protocol_dir / 'staging/security-context/security-context-v1.xml',
] ]
wl_protocols = [] wl_protos_src = []
foreach protocol : protocols wl_protos_headers = []
wl_protocols += custom_target(
protocol.underscorify(), new_wl_protos = []
input: protocol, foreach p : new_protocols
xml = join_paths(p)
new_wl_protos += custom_target(
xml.underscorify(),
input: xml,
install: true, install: true,
install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')], install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
output: ['@BASENAME@.cpp', '@BASENAME@.hpp'], output: ['@BASENAME@.cpp', '@BASENAME@.hpp'],
@@ -84,26 +78,31 @@ foreach protocol : protocols
) )
endforeach endforeach
# wayland.xml generation wayland_server_dep = dependency('wayland-server', version: '>=1.20.0')
wayland_scanner = dependency('wayland-scanner') wayland_server_dir = wayland_server_dep.get_variable('pkgdatadir')
wayland_scanner_datadir = wayland_scanner.get_variable('pkgdatadir')
wayland_xml = wayland_scanner_datadir / 'wayland.xml' wl_server_protos = [
wayland_protocol = custom_target( wayland_server_dir / 'wayland.xml'
wayland_xml.underscorify(), ]
input: wayland_xml, wl_server_protos_gen = []
foreach p : wl_server_protos
wl_server_protos_gen += custom_target(
p.underscorify(),
input: p,
install: true, install: true,
install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')], install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
output: ['@BASENAME@.cpp', '@BASENAME@.hpp'], output: ['@BASENAME@.cpp', '@BASENAME@.hpp'],
command: [hyprwayland_scanner, '--wayland-enums', '@INPUT@', '@OUTDIR@'], command: [hyprwayland_scanner, '--wayland-enums', '@INPUT@', '@OUTDIR@'],
) )
endforeach
lib_server_protos = static_library( lib_server_protos = static_library(
'server_protos', 'server_protos',
wl_protocols + wayland_protocol, wl_protos_src + wl_protos_headers + new_wl_protos + wl_server_protos_gen,
dependencies: wayland_server_dep.partial_dependency(compile_args: true),
) )
server_protos = declare_dependency( server_protos = declare_dependency(
link_with: lib_server_protos, link_with: lib_server_protos,
sources: wl_protocols + wayland_protocol, sources: wl_protos_headers + new_wl_protos,
) )

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,23 +1,41 @@
#pragma once #pragma once
#include <memory>
#include <deque>
#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 {
STAGE_PRIORITY = 0, STAGE_PRIORITY = 0,
STAGE_BASICINIT, STAGE_BASICINIT,
STAGE_LATE STAGE_LATE
@@ -25,7 +43,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;
@@ -41,8 +59,8 @@ class CCompositor {
std::string m_szInstancePath = ""; std::string m_szInstancePath = "";
std::string m_szCurrentSplash = "error"; std::string m_szCurrentSplash = "error";
std::vector<PHLMONITOR> m_vMonitors; std::vector<SP<CMonitor>> m_vMonitors;
std::vector<PHLMONITOR> m_vRealMonitors; // for all monitors, even those turned off std::vector<SP<CMonitor>> m_vRealMonitors; // for all monitors, even those turned off
std::vector<PHLWINDOW> m_vWindows; std::vector<PHLWINDOW> m_vWindows;
std::vector<PHLLS> m_vLayers; std::vector<PHLLS> m_vLayers;
std::vector<PHLWORKSPACE> m_vWorkspaces; std::vector<PHLWORKSPACE> m_vWorkspaces;
@@ -62,7 +80,7 @@ class CCompositor {
WP<CWLSurfaceResource> m_pLastFocus; WP<CWLSurfaceResource> m_pLastFocus;
PHLWINDOWREF m_pLastWindow; PHLWINDOWREF m_pLastWindow;
PHLMONITORREF m_pLastMonitor; WP<CMonitor> m_pLastMonitor;
std::vector<PHLWINDOWREF> m_vWindowFocusHistory; // first element is the most recently focused. std::vector<PHLWINDOWREF> m_vWindowFocusHistory; // first element is the most recently focused.
@@ -71,64 +89,72 @@ class CCompositor {
bool m_bDPMSStateON = true; bool m_bDPMSStateON = true;
bool m_bUnsafeState = false; // unsafe state is when there is no monitors. bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
bool m_bNextIsUnsafe = false; bool m_bNextIsUnsafe = false;
PHLMONITORREF m_pUnsafeOutput; // fallback output for the unsafe state CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state
bool m_bIsShuttingDown = false; bool m_bIsShuttingDown = false;
bool m_bFinalRequests = false;
bool m_bDesktopEnvSet = false; bool m_bDesktopEnvSet = false;
bool m_bWantsXwayland = true;
bool m_bOnlyConfigVerification = false;
// ------------------------------------------------- // // ------------------------------------------------- //
PHLMONITOR getMonitorFromID(const MONITORID&); CMonitor* getMonitorFromID(const MONITORID&);
PHLMONITOR getMonitorFromName(const std::string&); CMonitor* getMonitorFromName(const std::string&);
PHLMONITOR getMonitorFromDesc(const std::string&); CMonitor* getMonitorFromDesc(const std::string&);
PHLMONITOR getMonitorFromCursor(); CMonitor* getMonitorFromCursor();
PHLMONITOR getMonitorFromVector(const Vector2D&); CMonitor* getMonitorFromVector(const Vector2D&);
void removeWindowFromVectorSafe(PHLWINDOW); void removeWindowFromVectorSafe(PHLWINDOW);
void focusWindow(PHLWINDOW, SP<CWLSurfaceResource> pSurface = nullptr); void focusWindow(PHLWINDOW, SP<CWLSurfaceResource> pSurface = nullptr);
void focusSurface(SP<CWLSurfaceResource>, PHLWINDOW pWindowOwner = nullptr); void focusSurface(SP<CWLSurfaceResource>, PHLWINDOW pWindowOwner = nullptr);
bool monitorExists(PHLMONITOR); bool monitorExists(CMonitor*);
PHLWINDOW vectorToWindowUnified(const Vector2D&, uint8_t properties, PHLWINDOW pIgnoreWindow = nullptr); PHLWINDOW vectorToWindowUnified(const Vector2D&, uint8_t properties, PHLWINDOW pIgnoreWindow = nullptr);
SP<CWLSurfaceResource> vectorToLayerSurface(const Vector2D&, std::vector<PHLLSREF>*, Vector2D*, PHLLS*); SP<CWLSurfaceResource> vectorToLayerSurface(const Vector2D&, std::vector<PHLLSREF>*, Vector2D*, PHLLS*);
SP<CWLSurfaceResource> vectorToLayerPopupSurface(const Vector2D&, PHLMONITOR monitor, Vector2D*, PHLLS*); SP<CWLSurfaceResource> vectorToLayerPopupSurface(const Vector2D&, CMonitor* monitor, Vector2D*, PHLLS*);
SP<CWLSurfaceResource> vectorWindowToSurface(const Vector2D&, PHLWINDOW, Vector2D& sl); SP<CWLSurfaceResource> vectorWindowToSurface(const Vector2D&, PHLWINDOW, Vector2D& sl);
Vector2D vectorToSurfaceLocal(const Vector2D&, PHLWINDOW, SP<CWLSurfaceResource>); Vector2D vectorToSurfaceLocal(const Vector2D&, PHLWINDOW, SP<CWLSurfaceResource>);
PHLMONITOR getMonitorFromOutput(SP<Aquamarine::IOutput>); CMonitor* getMonitorFromOutput(SP<Aquamarine::IOutput>);
PHLMONITOR getRealMonitorFromOutput(SP<Aquamarine::IOutput>); CMonitor* getRealMonitorFromOutput(SP<Aquamarine::IOutput>);
PHLWINDOW getWindowFromSurface(SP<CWLSurfaceResource>); PHLWINDOW getWindowFromSurface(SP<CWLSurfaceResource>);
PHLWINDOW getWindowFromHandle(uint32_t); PHLWINDOW getWindowFromHandle(uint32_t);
bool isWorkspaceVisible(PHLWORKSPACE);
bool isWorkspaceVisibleNotCovered(PHLWORKSPACE);
PHLWORKSPACE getWorkspaceByID(const WORKSPACEID&); PHLWORKSPACE getWorkspaceByID(const WORKSPACEID&);
PHLWORKSPACE getWorkspaceByName(const std::string&); PHLWORKSPACE getWorkspaceByName(const std::string&);
PHLWORKSPACE getWorkspaceByString(const std::string&); PHLWORKSPACE getWorkspaceByString(const std::string&);
void sanityCheckWorkspaces(); void sanityCheckWorkspaces();
void updateWorkspaceWindowDecos(const WORKSPACEID&);
void updateWorkspaceWindowData(const WORKSPACEID&);
int getWindowsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
int getGroupsOnWorkspace(const WORKSPACEID& id, std::optional<bool> onlyTiled = {}, std::optional<bool> onlyVisible = {});
PHLWINDOW getUrgentWindow(); PHLWINDOW getUrgentWindow();
bool hasUrgentWindowOnWorkspace(const WORKSPACEID&);
PHLWINDOW getFirstWindowOnWorkspace(const WORKSPACEID&);
PHLWINDOW getTopLeftWindowOnWorkspace(const WORKSPACEID&);
PHLWINDOW getFullscreenWindowOnWorkspace(const WORKSPACEID&);
bool isWindowActive(PHLWINDOW); bool isWindowActive(PHLWINDOW);
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 CMonitor* monitor = nullptr);
PHLMONITOR getMonitorInDirection(const char&); CMonitor* getMonitorInDirection(const char&);
PHLMONITOR getMonitorInDirection(PHLMONITOR, const char&); CMonitor* getMonitorInDirection(CMonitor*, const char&);
void updateAllWindowsAnimatedDecorationValues(); void updateAllWindowsAnimatedDecorationValues();
void updateWorkspaceWindows(const WORKSPACEID& id);
void updateWindowAnimatedDecorationValues(PHLWINDOW); void updateWindowAnimatedDecorationValues(PHLWINDOW);
MONITORID getNextAvailableMonitorID(std::string const& name); MONITORID getNextAvailableMonitorID(std::string const& name);
void moveWorkspaceToMonitor(PHLWORKSPACE, PHLMONITOR, bool noWarpCursor = false); void moveWorkspaceToMonitor(PHLWORKSPACE, CMonitor*, bool noWarpCursor = false);
void swapActiveWorkspaces(PHLMONITOR, PHLMONITOR); void swapActiveWorkspaces(CMonitor*, CMonitor*);
PHLMONITOR getMonitorFromString(const std::string&); CMonitor* getMonitorFromString(const std::string&);
bool workspaceIDOutOfBounds(const WORKSPACEID&); bool workspaceIDOutOfBounds(const WORKSPACEID&);
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);
void scheduleFrameForMonitor(PHLMONITOR, Aquamarine::IOutput::scheduleFrameReason reason = Aquamarine::IOutput::AQ_SCHEDULE_CLIENT_UNKNOWN); void scheduleFrameForMonitor(CMonitor*, Aquamarine::IOutput::scheduleFrameReason reason = Aquamarine::IOutput::AQ_SCHEDULE_CLIENT_UNKNOWN);
void addToFadingOutSafe(PHLLS); void addToFadingOutSafe(PHLLS);
void removeFromFadingOutSafe(PHLLS); void removeFromFadingOutSafe(PHLLS);
void addToFadingOutSafe(PHLWINDOW); void addToFadingOutSafe(PHLWINDOW);
@@ -137,9 +163,11 @@ class CCompositor {
PHLLS getLayerSurfaceFromSurface(SP<CWLSurfaceResource>); PHLLS getLayerSurfaceFromSurface(SP<CWLSurfaceResource>);
void closeWindow(PHLWINDOW); void closeWindow(PHLWINDOW);
Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&); Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&);
void forceReportSizesToWindowsOnWorkspace(const WORKSPACEID&);
PHLWORKSPACE createNewWorkspace(const WORKSPACEID&, const MONITORID&, const std::string& name = "", PHLWORKSPACE createNewWorkspace(const WORKSPACEID&, const MONITORID&, const std::string& name = "",
bool isEmpty = true); // will be deleted next frame if left empty and unfocused! bool isEmtpy = true); // will be deleted next frame if left empty and unfocused!
void setActiveMonitor(PHLMONITOR); void renameWorkspace(const WORKSPACEID&, const std::string& name = "");
void setActiveMonitor(CMonitor*);
bool isWorkspaceSpecial(const WORKSPACEID&); bool isWorkspaceSpecial(const WORKSPACEID&);
WORKSPACEID getNewSpecialID(); WORKSPACEID getNewSpecialID();
void performUserChecks(); void performUserChecks();
@@ -151,11 +179,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 +191,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,11 +3,11 @@
#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 { using namespace Hyprutils::Math;
enum eIcons {
ICON_WARNING = 0, ICON_WARNING = 0,
ICON_INFO, ICON_INFO,
ICON_HINT, ICON_HINT,
@@ -17,7 +17,7 @@ enum eIcons : uint8_t {
ICON_NONE ICON_NONE
}; };
enum eRenderStage : uint8_t { enum eRenderStage {
RENDER_PRE = 0, /* Before binding the gl context */ RENDER_PRE = 0, /* Before binding the gl context */
RENDER_BEGIN, /* Just when the rendering begins, nothing has been rendered yet. Damage, current render data in opengl valid. */ RENDER_BEGIN, /* Just when the rendering begins, nothing has been rendered yet. Damage, current render data in opengl valid. */
RENDER_PRE_WINDOWS, /* Pre windows, post bottom and overlay layers */ RENDER_PRE_WINDOWS, /* Pre windows, post bottom and overlay layers */
@@ -29,7 +29,7 @@ enum eRenderStage : uint8_t {
RENDER_POST_WINDOW, /* After rendering a window (any pass) */ RENDER_POST_WINDOW, /* After rendering a window (any pass) */
}; };
enum eInputType : uint8_t { enum eInputType {
INPUT_TYPE_AXIS = 0, INPUT_TYPE_AXIS = 0,
INPUT_TYPE_BUTTON, INPUT_TYPE_BUTTON,
INPUT_TYPE_DRAG_START, INPUT_TYPE_DRAG_START,
@@ -41,7 +41,7 @@ struct SCallbackInfo {
bool cancelled = false; /* on cancellable events, will cancel the event. */ bool cancelled = false; /* on cancellable events, will cancel the event. */
}; };
enum eHyprCtlOutputFormat : uint8_t { enum eHyprCtlOutputFormat {
FORMAT_NORMAL = 0, FORMAT_NORMAL = 0,
FORMAT_JSON FORMAT_JSON
}; };
@@ -52,12 +52,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

@@ -3,7 +3,7 @@
#include "../helpers/varlist/VarList.hpp" #include "../helpers/varlist/VarList.hpp"
#include <vector> #include <vector>
enum eConfigValueDataTypes : int8_t { enum eConfigValueDataTypes {
CVD_TYPE_INVALID = -1, CVD_TYPE_INVALID = -1,
CVD_TYPE_GRADIENT = 0, CVD_TYPE_GRADIENT = 0,
CVD_TYPE_CSS_VALUE = 1 CVD_TYPE_CSS_VALUE = 1
@@ -20,40 +20,24 @@ class ICustomConfigValueData {
class CGradientValueData : public ICustomConfigValueData { class CGradientValueData : public ICustomConfigValueData {
public: public:
CGradientValueData() = default; CGradientValueData() {};
CGradientValueData(CHyprColor col) { CGradientValueData(CColor col) {
m_vColors.push_back(col); m_vColors.push_back(col);
updateColorsOk();
}; };
virtual ~CGradientValueData() = default; virtual ~CGradientValueData() {};
virtual eConfigValueDataTypes getDataType() { virtual eConfigValueDataTypes getDataType() {
return CVD_TYPE_GRADIENT; return CVD_TYPE_GRADIENT;
} }
void reset(CHyprColor col) { void reset(CColor col) {
m_vColors.clear(); m_vColors.clear();
m_vColors.emplace_back(col); m_vColors.emplace_back(col);
m_fAngle = 0; m_fAngle = 0;
updateColorsOk();
}
void updateColorsOk() {
m_vColorsOkLabA.clear();
for (auto& c : m_vColors) {
const auto OKLAB = c.asOkLab();
m_vColorsOkLabA.emplace_back(OKLAB.l);
m_vColorsOkLabA.emplace_back(OKLAB.a);
m_vColorsOkLabA.emplace_back(OKLAB.b);
m_vColorsOkLabA.emplace_back(c.a);
}
} }
/* Vector containing the colors */ /* Vector containing the colors */
std::vector<CHyprColor> m_vColors; std::vector<CColor> m_vColors;
/* Vector containing pure colors for shoving into opengl */
std::vector<float> m_vColorsOkLabA;
/* Float corresponding to the angle (rad) */ /* Float corresponding to the angle (rad) */
float m_fAngle = 0; float m_fAngle = 0;

View File

@@ -104,30 +104,6 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.type = CONFIG_OPTION_INT, .type = CONFIG_OPTION_INT,
.data = SConfigOptionDescription::SRangeData{0, 0, 4}, .data = SConfigOptionDescription::SRangeData{0, 0, 4},
}, },
SConfigOptionDescription{
.value = "general:snap:enabled",
.description = "enable snapping for floating windows",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "general:snap:window_gap",
.description = "minimum gap in pixels between windows before snapping",
.type = CONFIG_OPTION_INT,
.data = SConfigOptionDescription::SRangeData{10, 0, 100},
},
SConfigOptionDescription{
.value = "general:snap:monitor_gap",
.description = "minimum gap in pixels between window and monitor edges before snapping",
.type = CONFIG_OPTION_INT,
.data = SConfigOptionDescription::SRangeData{10, 0, 100},
},
SConfigOptionDescription{
.value = "general:snap:border_overlap",
.description = "if true, windows snap such that only one border's worth of space is between them",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
/* /*
* decoration: * decoration:
@@ -139,12 +115,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]",
@@ -164,55 +134,49 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.data = SConfigOptionDescription::SFloatData{1, 0, 1}, .data = SConfigOptionDescription::SFloatData{1, 0, 1},
}, },
SConfigOptionDescription{ SConfigOptionDescription{
.value = "decoration:shadow:enabled", .value = "decoration:drop_shadow",
.description = "enable drop shadows on windows", .description = "enable drop shadows on windows",
.type = CONFIG_OPTION_BOOL, .type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true}, .data = SConfigOptionDescription::SBoolData{true},
}, },
SConfigOptionDescription{ SConfigOptionDescription{
.value = "decoration:shadow:range", .value = "decoration:shadow_range",
.description = "Shadow range (size) in layout px", .description = "Shadow range (size) in layout px",
.type = CONFIG_OPTION_INT, .type = CONFIG_OPTION_INT,
.data = SConfigOptionDescription::SRangeData{4, 0, 100}, .data = SConfigOptionDescription::SRangeData{4, 0, 100},
}, },
SConfigOptionDescription{ SConfigOptionDescription{
.value = "decoration:shadow:render_power", .value = "decoration:shadow_render_power",
.description = "in what power to render the falloff (more power, the faster the falloff) [1 - 4]", .description = "in what power to render the falloff (more power, the faster the falloff) [1 - 4]",
.type = CONFIG_OPTION_INT, .type = CONFIG_OPTION_INT,
.data = SConfigOptionDescription::SRangeData{3, 1, 4}, .data = SConfigOptionDescription::SRangeData{3, 1, 4},
}, },
SConfigOptionDescription{ SConfigOptionDescription{
.value = "decoration:shadow:sharp", .value = "decoration:shadow_ignore_window",
.description = "whether the shadow should be sharp or not. Akin to an infinitely high render power.",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "decoration:shadow:ignore_window",
.description = "if true, the shadow will not be rendered behind the window itself, only around it.", .description = "if true, the shadow will not be rendered behind the window itself, only around it.",
.type = CONFIG_OPTION_BOOL, .type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true}, .data = SConfigOptionDescription::SBoolData{true},
}, },
SConfigOptionDescription{ SConfigOptionDescription{
.value = "decoration:shadow:color", .value = "decoration:col.shadow",
.description = "shadow's color. Alpha dictates shadow's opacity.", .description = "shadow's color. Alpha dictates shadow's opacity.",
.type = CONFIG_OPTION_COLOR, .type = CONFIG_OPTION_COLOR,
.data = SConfigOptionDescription::SColorData{0xee1a1a1a}, .data = SConfigOptionDescription::SColorData{0xee1a1a1a},
}, },
SConfigOptionDescription{ SConfigOptionDescription{
.value = "decoration:shadow:color_inactive", .value = "decoration:col.shadow_inactive",
.description = "inactive shadow color. (if not set, will fall back to col.shadow)", .description = "inactive shadow color. (if not set, will fall back to col.shadow)",
.type = CONFIG_OPTION_COLOR, .type = CONFIG_OPTION_COLOR,
.data = SConfigOptionDescription::SColorData{}, //TODO: UNSET? .data = SConfigOptionDescription::SColorData{}, //##TODO UNSET?
}, },
SConfigOptionDescription{ SConfigOptionDescription{
.value = "decoration:shadow:offset", .value = "decoration:shadow_offset",
.description = "shadow's rendering offset.", .description = "shadow's rendering offset.",
.type = CONFIG_OPTION_VECTOR, .type = CONFIG_OPTION_VECTOR,
.data = SConfigOptionDescription::SVectorData{{}, {-250, -250}, {250, 250}}, .data = SConfigOptionDescription::SVectorData{{}, {-250, -250}, {250, 250}},
}, },
SConfigOptionDescription{ SConfigOptionDescription{
.value = "decoration:shadow:scale", .value = "decoration:shadow_scale",
.description = "shadow's scale. [0.0 - 1.0]", .description = "shadow's scale. [0.0 - 1.0]",
.type = CONFIG_OPTION_FLOAT, .type = CONFIG_OPTION_FLOAT,
.data = SConfigOptionDescription::SFloatData{1, 0, 1}, .data = SConfigOptionDescription::SFloatData{1, 0, 1},
@@ -274,7 +238,7 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.value = "blur:ignore_opacity", .value = "blur:ignore_opacity",
.description = "make the blur layer ignore the opacity of the window", .description = "make the blur layer ignore the opacity of the window",
.type = CONFIG_OPTION_BOOL, .type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true}, .data = SConfigOptionDescription::SBoolData{false},
}, },
SConfigOptionDescription{ SConfigOptionDescription{
.value = "blur:new_optimizations", .value = "blur:new_optimizations",
@@ -337,18 +301,6 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.type = CONFIG_OPTION_FLOAT, .type = CONFIG_OPTION_FLOAT,
.data = SConfigOptionDescription::SFloatData{0.2, 0, 1}, .data = SConfigOptionDescription::SFloatData{0.2, 0, 1},
}, },
SConfigOptionDescription{
.value = "blur:input_methods",
.description = "whether to blur input methods (e.g. fcitx5)",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "blur:input_methods_ignorealpha",
.description = "works like ignorealpha in layer rules. If pixel opacity is below set value, will not blur. [0.0 - 1.0]",
.type = CONFIG_OPTION_FLOAT,
.data = SConfigOptionDescription::SFloatData{0.2, 0, 1},
},
/* /*
* animations: * animations:
@@ -638,22 +590,16 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
}, },
SConfigOptionDescription{ SConfigOptionDescription{
.value = "input:tablet:output", .value = "input:tablet:output",
.description = "the monitor to bind tablets. Can be current or a monitor name. Leave empty to map across all monitors.", .description = "the monitor to bind tablets. Empty means unbound..",
.type = CONFIG_OPTION_STRING_SHORT, .type = CONFIG_OPTION_STRING_SHORT,
.data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET? .data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET?
}, },
SConfigOptionDescription{ SConfigOptionDescription{
.value = "input:tablet:region_position", .value = "input:tablet:region_position",
.description = "position of the mapped region in monitor layout relative to the top left corner of the bound monitor or all monitors.", .description = "position of the mapped region in monitor layout.",
.type = CONFIG_OPTION_VECTOR, .type = CONFIG_OPTION_VECTOR,
.data = SConfigOptionDescription::SVectorData{{}, {-20000, -20000}, {20000, 20000}}, .data = SConfigOptionDescription::SVectorData{{}, {-20000, -20000}, {20000, 20000}},
}, },
SConfigOptionDescription{
.value = "input:tablet:absolute_region_position",
.description = "whether to treat the region_position as an absolute position in monitor layout. Only applies when output is empty.",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{ SConfigOptionDescription{
.value = "input:tablet:region_size", .value = "input:tablet:region_size",
.description = "size of the mapped region. When this variable is set, tablet input will be mapped to the region. [0, 0] or invalid size means unset.", .description = "size of the mapped region. When this variable is set, tablet input will be mapped to the region. [0, 0] or invalid size means unset.",
@@ -796,18 +742,6 @@ 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 = "group:merge_groups_on_drag",
.description = "whether window groups can be dragged into other groups",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true},
},
SConfigOptionDescription{
.value = "group:merge_groups_on_groupbar",
.description = "whether one group will be merged with another when dragged into its groupbar",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true},
},
SConfigOptionDescription{ SConfigOptionDescription{
.value = "general:col.border_active", .value = "general:col.border_active",
.description = "border color for inactive windows", .description = "border color for inactive windows",
@@ -832,30 +766,6 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.type = CONFIG_OPTION_GRADIENT, .type = CONFIG_OPTION_GRADIENT,
.data = SConfigOptionDescription::SGradientData{"0x66775500"}, .data = SConfigOptionDescription::SGradientData{"0x66775500"},
}, },
SConfigOptionDescription{
.value = "group:auto_group",
.description = "automatically group new windows",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true},
},
SConfigOptionDescription{
.value = "group:drag_into_group",
.description = "whether dragging a window into a unlocked group will merge them. Options: 0 (disabled), 1 (enabled), 2 (only when dragging into the groupbar)",
.type = CONFIG_OPTION_CHOICE,
.data = SConfigOptionDescription::SChoiceData{0, "disabled,enabled,only when dragging into the groupbar"},
},
SConfigOptionDescription{
.value = "group:merge_floated_into_tiled_on_groupbar",
.description = "whether dragging a floating window into a tiled window groupbar will merge them",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "group:group_on_movetoworkspace",
.description = "whether using movetoworkspace[silent] will merge the window into the workspace's solitary unlocked group",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
/* /*
* group:groupbar: * group:groupbar:
@@ -1127,30 +1037,6 @@ 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 = "misc:render_unfocused_fps",
.description = "the maximum limit for renderunfocused windows' fps in the background",
.type = CONFIG_OPTION_INT,
.data = SConfigOptionDescription::SRangeData{15, 1, 120},
},
SConfigOptionDescription{
.value = "misc:disable_xdg_env_checks",
.description = "disable the warning if XDG environment is externally managed",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "misc:disable_hyprland_qtutils_check",
.description = "disable the warning if hyprland-qtutils is missing",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "misc:lockdead_screen_delay",
.description = "the delay in ms after the lockdead screen appears if the lock screen did not appear after a lock event occurred.",
.type = CONFIG_OPTION_INT,
.data = SConfigOptionDescription::SRangeData{1000, 0, 5000},
},
/* /*
* binds: * binds:
@@ -1206,12 +1092,6 @@ 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 = "binds:movefocus_cycles_groupfirst",
.description = "If enabled, when in a grouped window, movefocus will cycle windows in the groups first, then at each ends of tabs, it'll move on to other windows/groups",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{ SConfigOptionDescription{
.value = "binds:disable_keybind_grabbing", .value = "binds:disable_keybind_grabbing",
.description = "If enabled, apps that request keybinds to be disabled (e.g. VMs) will not be able to do so.", .description = "If enabled, apps that request keybinds to be disabled (e.g. VMs) will not be able to do so.",
@@ -1224,23 +1104,11 @@ 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 = "binds:allow_pin_fullscreen",
.description = "Allows fullscreen to pinned windows, and restore their pinned status afterwards",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
/* /*
* xwayland: * xwayland:
*/ */
SConfigOptionDescription{
.value = "xwayland:enabled",
.description = "allow running applications using X11",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true},
},
SConfigOptionDescription{ SConfigOptionDescription{
.value = "xwayland:use_nearest_neighbor", .value = "xwayland:use_nearest_neighbor",
.description = "uses the nearest neighbor filtering for xwayland apps, making them pixelated rather than blurry", .description = "uses the nearest neighbor filtering for xwayland apps, making them pixelated rather than blurry",
@@ -1295,30 +1163,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:
@@ -1334,8 +1178,8 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
SConfigOptionDescription{ SConfigOptionDescription{
.value = "cursor:no_hardware_cursors", .value = "cursor:no_hardware_cursors",
.description = "disables hardware cursors", .description = "disables hardware cursors",
.type = CONFIG_OPTION_CHOICE, .type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SChoiceData{0, "Disabled,Enabled,Auto"}, .data = SConfigOptionDescription::SBoolData{false},
}, },
SConfigOptionDescription{ SConfigOptionDescription{
.value = "cursor:no_break_fs_vrr", .value = "cursor:no_break_fs_vrr",
@@ -1375,9 +1219,9 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
}, },
SConfigOptionDescription{ SConfigOptionDescription{
.value = "cursor:warp_on_change_workspace", .value = "cursor:warp_on_change_workspace",
.description = "Move the cursor to the last focused window after changing the workspace. Options: 0 (Disabled), 1 (Enabled), 2 (Force - ignores cursor:no_warps option)", .description = "If true, move the cursor to the last focused window after changing the workspace.",
.type = CONFIG_OPTION_CHOICE, .type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SChoiceData{0, "Disabled,Enabled,Force"}, .data = SConfigOptionDescription::SBoolData{false},
}, },
SConfigOptionDescription{ SConfigOptionDescription{
.value = "cursor:default_monitor", .value = "cursor:default_monitor",
@@ -1416,8 +1260,8 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.data = SConfigOptionDescription::SBoolData{true}, .data = SConfigOptionDescription::SBoolData{true},
}, },
SConfigOptionDescription{ SConfigOptionDescription{
.value = "cursor:use_cpu_buffer", .value = "cursor:allow_dumb_copy",
.description = "Makes HW cursors use a CPU buffer. Required on Nvidia to have HW cursors. Experimental", .description = "Makes HW cursors work on Nvidia, at the cost of a possible hitch whenever the image changes",
.type = CONFIG_OPTION_BOOL, .type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false}, .data = SConfigOptionDescription::SBoolData{false},
}, },
@@ -1504,182 +1348,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},
}, },
/*
* dwindle:
*/
SConfigOptionDescription{
.value = "dwindle:pseudotile",
.description = "enable pseudotiling. Pseudotiled windows retain their floating size when tiled.",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "dwindle:force_split",
.description = "0 -> split follows mouse, 1 -> always split to the left (new = left or top) 2 -> always split to the right (new = right or bottom)",
.type = CONFIG_OPTION_CHOICE,
.data = SConfigOptionDescription::SChoiceData{0, "follow mouse,left or top,right or bottom"},
},
SConfigOptionDescription{
.value = "dwindle:preserve_split",
.description = "if enabled, the split (side/top) will not change regardless of what happens to the container.",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "dwindle:smart_split",
.description = "if enabled, allows a more precise control over the window split direction based on the cursor's position. The window is conceptually divided into four "
"triangles, and cursor's triangle determines the split direction. This feature also turns on preserve_split.",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "dwindle:smart_resizing",
.description =
"if enabled, resizing direction will be determined by the mouse's position on the window (nearest to which corner). Else, it is based on the window's tiling position.",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true},
},
SConfigOptionDescription{
.value = "dwindle:permanent_direction_override",
.description = "if enabled, makes the preselect direction persist until either this mode is turned off, another direction is specified, or a non-direction is specified "
"(anything other than l,r,u/t,d/b)",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "dwindle:special_scale_factor",
.description = "specifies the scale factor of windows on the special workspace [0 - 1]",
.type = CONFIG_OPTION_FLOAT,
.data = SConfigOptionDescription::SFloatData{1, 0, 1},
},
SConfigOptionDescription{
.value = "dwindle:split_width_multiplier",
.description = "specifies the auto-split width multiplier",
.type = CONFIG_OPTION_FLOAT,
.data = SConfigOptionDescription::SFloatData{1, 0.1, 3},
},
SConfigOptionDescription{
.value = "dwindle:use_active_for_splits",
.description = "whether to prefer the active window or the mouse position for splits",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true},
},
SConfigOptionDescription{
.value = "dwindle:default_split_ratio",
.description = "the default split ratio on window open. 1 means even 50/50 split. [0.1 - 1.9]",
.type = CONFIG_OPTION_FLOAT,
.data = SConfigOptionDescription::SFloatData{1, 0.1, 1.9},
},
SConfigOptionDescription{
.value = "dwindle:split_bias",
.description = "specifies which window will receive the larger half of a split. positional - 0, current window - 1, opening window - 2 [0/1/2]",
.type = CONFIG_OPTION_CHOICE,
.data = SConfigOptionDescription::SChoiceData{0, "positional,current,opening"},
},
/*
* master:
*/
SConfigOptionDescription{
.value = "master:allow_small_split",
.description = "enable adding additional master windows in a horizontal split style",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "master:special_scale_factor",
.description = "the scale of the special workspace windows. [0.0 - 1.0]",
.type = CONFIG_OPTION_FLOAT,
.data = SConfigOptionDescription::SFloatData{1, 0, 1},
},
SConfigOptionDescription{
.value = "master:mfact",
.description =
"the size as a percentage of the master window, for example `mfact = 0.70` would mean 70% of the screen will be the master window, and 30% the slave [0.0 - 1.0]",
.type = CONFIG_OPTION_FLOAT,
.data = SConfigOptionDescription::SFloatData{0.55, 0, 1},
},
SConfigOptionDescription{
.value = "master:new_status",
.description = "`master`: new window becomes master; `slave`: new windows are added to slave stack; `inherit`: inherit from focused window",
.type = CONFIG_OPTION_STRING_SHORT,
.data = SConfigOptionDescription::SStringData{"slave"},
},
SConfigOptionDescription{
.value = "master:new_on_top",
.description = "whether a newly open window should be on the top of the stack",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "master:new_on_active",
.description = "`before`, `after`: place new window relative to the focused window; `none`: place new window according to the value of `new_on_top`. ",
.type = CONFIG_OPTION_STRING_SHORT,
.data = SConfigOptionDescription::SStringData{"none"},
},
SConfigOptionDescription{
.value = "master:orientation",
.description = "default placement of the master area, can be left, right, top, bottom or center",
.type = CONFIG_OPTION_STRING_SHORT,
.data = SConfigOptionDescription::SStringData{"left"},
},
SConfigOptionDescription{
.value = "master:inherit_fullscreen",
.description = "inherit fullscreen status when cycling/swapping to another window (e.g. monocle layout)",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true},
},
SConfigOptionDescription{
.value = "master:slave_count_for_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)",
.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,
.data = SConfigOptionDescription::SBoolData{true},
},
SConfigOptionDescription{
.value = "master:center_ignores_reserved",
.description = "centers the master window on monitor ignoring reserved areas",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "master:smart_resizing",
.description =
"if enabled, resizing direction will be determined by the mouse's position on the window (nearest to which corner). Else, it is based on the window's tiling position.",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{true},
},
SConfigOptionDescription{
.value = "master:drop_at_cursor",
.description = "when enabled, dragging and dropping windows will put them at the cursor position. Otherwise, when dropped at the stack side, they will go to the "
"top/bottom of the stack depending on new_on_top.",
.type = CONFIG_OPTION_BOOL,
.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},
},
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +1,33 @@
#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 <deque>
#include <algorithm>
#include <regex>
#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,14 +56,26 @@ 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 = 0;
std::string name = ""; std::string name = "";
Hyprlang::PCONFIGHANDLERFUNC fn = nullptr; Hyprlang::PCONFIGHANDLERFUNC fn = nullptr;
}; };
struct SPluginVariable { struct SPluginVariable {
HANDLE handle = nullptr; HANDLE handle = 0;
std::string name = ""; std::string name = "";
}; };
@@ -69,7 +84,7 @@ struct SExecRequestedRule {
uint64_t iPid = 0; uint64_t iPid = 0;
}; };
enum eConfigOptionType : uint8_t { enum eConfigOptionType : uint16_t {
CONFIG_OPTION_BOOL = 0, CONFIG_OPTION_BOOL = 0,
CONFIG_OPTION_INT = 1, /* e.g. 0/1/2*/ CONFIG_OPTION_INT = 1, /* e.g. 0/1/2*/
CONFIG_OPTION_FLOAT = 2, CONFIG_OPTION_FLOAT = 2,
@@ -81,7 +96,7 @@ enum eConfigOptionType : uint8_t {
CONFIG_OPTION_VECTOR = 8, CONFIG_OPTION_VECTOR = 8,
}; };
enum eConfigOptionFlags : uint8_t { enum eConfigOptionFlags : uint32_t {
CONFIG_OPTION_FLAG_PERCENTAGE = (1 << 0), CONFIG_OPTION_FLAG_PERCENTAGE = (1 << 0),
}; };
@@ -104,7 +119,7 @@ struct SConfigOptionDescription {
}; };
struct SColorData { struct SColorData {
CHyprColor color; CColor color;
}; };
struct SChoiceData { struct SChoiceData {
@@ -133,18 +148,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,26 +165,26 @@ 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);
std::string getConfigString(); static std::string getMainConfigPath();
const std::string getConfigString();
SMonitorRule getMonitorRuleFor(const PHLMONITOR); SMonitorRule getMonitorRuleFor(const CMonitor&);
SWorkspaceRule getWorkspaceRuleFor(PHLWORKSPACE workspace); SWorkspaceRule getWorkspaceRuleFor(PHLWORKSPACE workspace);
std::string getDefaultWorkspaceFor(const std::string&); std::string getDefaultWorkspaceFor(const std::string&);
PHLMONITOR getBoundMonitorForWS(const std::string&); CMonitor* getBoundMonitorForWS(const std::string&);
std::string getBoundMonitorStringForWS(const std::string&); std::string getBoundMonitorStringForWS(const std::string&);
const std::vector<SWorkspaceRule>& getAllWorkspaceRules(); const std::deque<SWorkspaceRule>& getAllWorkspaceRules();
std::vector<SP<CWindowRule>> getMatchingRules(PHLWINDOW, bool dynamic = true, bool shadowExec = false); std::vector<SWindowRule> getMatchingRules(PHLWINDOW, bool dynamic = true, bool shadowExec = false);
std::vector<SP<CLayerRule>> getMatchingRules(PHLLS); std::vector<SLayerRule> 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 = {});
@@ -183,20 +192,18 @@ class CConfigManager {
// no-op when done. // no-op when done.
void dispatchExecOnce(); void dispatchExecOnce();
void dispatchExecShutdown();
void performMonitorReload(); void performMonitorReload();
void appendMonitorRule(const SMonitorRule&);
bool replaceMonitorRule(const SMonitorRule&);
void ensureMonitorStatus(); void ensureMonitorStatus();
void ensureVRR(PHLMONITOR pMonitor = nullptr); void ensureVRR(CMonitor* pMonitor = nullptr);
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&);
@@ -205,10 +212,7 @@ class CConfigManager {
// 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> 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&);
std::optional<std::string> handleUnbind(const std::string&, const std::string&); std::optional<std::string> handleUnbind(const std::string&, const std::string&);
@@ -227,50 +231,44 @@ class CConfigManager {
std::string configCurrentPath; std::string configCurrentPath;
std::unordered_map<std::string, std::function<CWindowOverridableVar<bool>*(const PHLWINDOW&)>> mbWindowProperties = { std::unordered_map<std::string, std::function<CWindowOverridableVar<bool>*(PHLWINDOW)>> mbWindowProperties = {
{"allowsinput", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.allowsInput; }}, {"allowsinput", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.allowsInput; }},
{"dimaround", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.dimAround; }}, {"dimaround", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.dimAround; }},
{"decorate", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.decorate; }}, {"decorate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.decorate; }},
{"focusonactivate", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.focusOnActivate; }}, {"focusonactivate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.focusOnActivate; }},
{"keepaspectratio", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.keepAspectRatio; }}, {"keepaspectratio", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.keepAspectRatio; }},
{"nearestneighbor", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.nearestNeighbor; }}, {"nearestneighbor", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.nearestNeighbor; }},
{"noanim", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noAnim; }}, {"noanim", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noAnim; }},
{"noblur", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noBlur; }}, {"noblur", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noBlur; }},
{"noborder", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noBorder; }}, {"noborder", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noBorder; }},
{"nodim", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noDim; }}, {"nodim", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noDim; }},
{"nofocus", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noFocus; }}, {"nofocus", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noFocus; }},
{"nomaxsize", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noMaxSize; }}, {"nomaxsize", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noMaxSize; }},
{"norounding", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noRounding; }}, {"norounding", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noRounding; }},
{"noshadow", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noShadow; }}, {"noshadow", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noShadow; }},
{"noshortcutsinhibit", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.noShortcutsInhibit; }}, {"noshortcutsinhibit", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.noShortcutsInhibit; }},
{"opaque", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.opaque; }}, {"opaque", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.opaque; }},
{"forcergbx", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.RGBX; }}, {"forcergbx", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.RGBX; }},
{"syncfullscreen", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.syncFullscreen; }}, {"syncfullscreen", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.syncFullscreen; }},
{"immediate", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.tearing; }}, {"immediate", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.tearing; }},
{"xray", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.xray; }}, {"xray", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.xray; }},
}; };
std::unordered_map<std::string, std::function<CWindowOverridableVar<int>*(const PHLWINDOW&)>> miWindowProperties = { std::unordered_map<std::string, std::function<CWindowOverridableVar<int>*(PHLWINDOW)>> miWindowProperties = {
{"rounding", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.rounding; }}, {"rounding", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.rounding; }}, {"bordersize", [](PHLWINDOW pWindow) { return &pWindow->m_sWindowData.borderSize; }}};
{"bordersize", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.borderSize; }},
};
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; }},
{"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollTouchpad; }}};
bool m_bWantsMonitorReload = false; bool m_bWantsMonitorReload = false;
bool m_bForceReload = false;
bool m_bNoMonitorReload = false; bool m_bNoMonitorReload = false;
bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking
bool m_bLastConfigVerificationWasSuccessful = true;
private: private:
UP<Hyprlang::CConfig> m_pConfig; std::unique_ptr<Hyprlang::CConfig> m_pConfig;
std::vector<std::string> m_configPaths; std::deque<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
@@ -282,29 +280,29 @@ class CConfigManager {
bool isFirstLaunch = true; // For exec-once bool isFirstLaunch = true; // For exec-once
std::vector<SMonitorRule> m_vMonitorRules; std::deque<SMonitorRule> m_dMonitorRules;
std::vector<SWorkspaceRule> m_vWorkspaceRules; std::deque<SWorkspaceRule> m_dWorkspaceRules;
std::vector<SP<CWindowRule>> m_vWindowRules; std::deque<SWindowRule> m_dWindowRules;
std::vector<SP<CLayerRule>> m_vLayerRules; std::deque<SLayerRule> m_dLayerRules;
std::vector<std::string> m_dBlurLSNamespaces; std::deque<std::string> m_dBlurLSNamespaces;
bool firstExecDispatched = false; bool firstExecDispatched = false;
bool m_bManualCrashInitiated = false; bool m_bManualCrashInitiated = false;
std::deque<std::string> firstExecRequests;
std::vector<SFirstExecRequest> firstExecRequests; // bool is for if with rules
std::vector<std::string> finalExecRequests;
std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins
std::string m_szConfigErrors = ""; std::string m_szConfigErrors = "";
// internal methods // internal methods
void setAnimForChildren(SAnimationPropertyConfig* const);
void updateBlurredLS(const std::string&, const bool); void updateBlurredLS(const std::string&, const bool);
void setDefaultAnimationVars(); void setDefaultAnimationVars();
std::optional<std::string> resetHLConfig(); std::optional<std::string> resetHLConfig();
std::optional<std::string> generateConfig(std::string configPath); static std::optional<std::string> generateConfig(std::string configPath);
std::optional<std::string> verifyConfigExists(); static std::optional<std::string> verifyConfigExists();
void postConfigReload(const Hyprlang::CParseResult& result); void postConfigReload(const Hyprlang::CParseResult& result);
void reload();
SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&); 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"
@@ -12,7 +13,6 @@ class CConfigValue {
CConfigValue(const std::string& val) { CConfigValue(const std::string& val) {
const auto PVHYPRLANG = g_pConfigManager->getHyprlangConfigValuePtr(val); const auto PVHYPRLANG = g_pConfigManager->getHyprlangConfigValuePtr(val);
// NOLINTNEXTLINE
p_ = PVHYPRLANG->getDataStaticPtr(); p_ = PVHYPRLANG->getDataStaticPtr();
#ifdef HYPRLAND_DEBUG #ifdef HYPRLAND_DEBUG

View File

@@ -1,84 +0,0 @@
#include "ConfigWatcher.hpp"
#include <sys/inotify.h>
#include "../debug/Log.hpp"
#include <ranges>
#include <fcntl.h>
#include <unistd.h>
#include <filesystem>
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 | IN_DONT_FOLLOW),
.file = path,
});
std::error_code ec, ec2;
const auto CANONICAL = std::filesystem::canonical(path, ec);
const auto IS_SYMLINK = std::filesystem::is_symlink(path, ec2);
if (!ec && !ec2 && IS_SYMLINK) {
m_watches.emplace_back(SInotifyWatch{
.wd = inotify_add_watch(m_inotifyFd, CANONICAL.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

@@ -4,8 +4,8 @@
inline const std::string AUTOCONFIG = R"#( inline const std::string AUTOCONFIG = R"#(
# ####################################################################################### # #######################################################################################
# AUTOGENERATED HYPRLAND CONFIG. # AUTOGENERATED HYPR CONFIG.
# PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hyprland.conf AND EDIT IT, # PLEASE USE THE CONFIG PROVIDED IN THE GIT REPO /examples/hypr.conf AND EDIT IT,
# OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS. # OR EDIT THIS ONE ACCORDING TO THE WIKI INSTRUCTIONS.
# ####################################################################################### # #######################################################################################
@@ -13,7 +13,7 @@ autogenerated = 1 # remove this line to remove the warning
# This is an example Hyprland config file. # This is an example Hyprland config file.
# Refer to the wiki for more information. # Refer to the wiki for more information.
# https://wiki.hyprland.org/Configuring/ # https://wiki.hyprland.org/Configuring/Configuring-Hyprland/
# Please note not all available settings / options are set here. # Please note not all available settings / options are set here.
# For a full list, see the wiki # For a full list, see the wiki
@@ -94,18 +94,15 @@ 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
inactive_opacity = 1.0 inactive_opacity = 1.0
shadow { drop_shadow = true
enabled = true shadow_range = 4
range = 4 shadow_render_power = 3
render_power = 3 col.shadow = rgba(1a1a1aee)
color = rgba(1a1a1aee)
}
# https://wiki.hyprland.org/Configuring/Variables/#blur # https://wiki.hyprland.org/Configuring/Variables/#blur
blur { blur {
@@ -119,44 +116,20 @@ decoration {
# https://wiki.hyprland.org/Configuring/Variables/#animations # https://wiki.hyprland.org/Configuring/Variables/#animations
animations { animations {
enabled = yes, please :) enabled = true
# Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more # Default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
bezier = easeOutQuint,0.23,1,0.32,1 bezier = myBezier, 0.05, 0.9, 0.1, 1.05
bezier = easeInOutCubic,0.65,0.05,0.36,1
bezier = linear,0,0,1,1
bezier = almostLinear,0.5,0.5,0.75,1.0
bezier = quick,0.15,0,0.1,1
animation = global, 1, 10, default animation = windows, 1, 7, myBezier
animation = border, 1, 5.39, easeOutQuint animation = windowsOut, 1, 7, default, popin 80%
animation = windows, 1, 4.79, easeOutQuint animation = border, 1, 10, default
animation = windowsIn, 1, 4.1, easeOutQuint, popin 87% animation = borderangle, 1, 8, default
animation = windowsOut, 1, 1.49, linear, popin 87% animation = fade, 1, 7, default
animation = fadeIn, 1, 1.73, almostLinear animation = workspaces, 1, 6, default
animation = fadeOut, 1, 1.46, almostLinear
animation = fade, 1, 3.03, quick
animation = layers, 1, 3.81, easeOutQuint
animation = layersIn, 1, 4, easeOutQuint, fade
animation = layersOut, 1, 1.5, linear, fade
animation = fadeLayersIn, 1, 1.79, almostLinear
animation = fadeLayersOut, 1, 1.39, almostLinear
animation = workspaces, 1, 1.94, almostLinear, fade
animation = workspacesIn, 1, 1.21, almostLinear, fade
animation = workspacesOut, 1, 1.94, almostLinear, fade
} }
# Ref https://wiki.hyprland.org/Configuring/Workspace-Rules/
# "Smart gaps" / "No gaps when only"
# uncomment all if you wish to use that.
# workspace = w[tv1], gapsout:0, gapsin:0
# workspace = f[1], gapsout:0, gapsin:0
# windowrulev2 = bordersize 0, floating:0, onworkspace:w[tv1]
# windowrulev2 = rounding 0, floating:0, onworkspace:w[tv1]
# windowrulev2 = bordersize 0, floating:0, onworkspace:f[1]
# windowrulev2 = rounding 0, floating:0, onworkspace:f[1]
# See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
dwindle { dwindle {
pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below pseudotile = true # Master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
@@ -268,19 +241,6 @@ bind = $mainMod, mouse_up, workspace, e-1
bindm = $mainMod, mouse:272, movewindow bindm = $mainMod, mouse:272, movewindow
bindm = $mainMod, mouse:273, resizewindow bindm = $mainMod, mouse:273, resizewindow
# Laptop multimedia keys for volume and LCD brightness
bindel = ,XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
bindel = ,XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
bindel = ,XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
bindel = ,XF86AudioMicMute, exec, wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle
bindel = ,XF86MonBrightnessUp, exec, brightnessctl s 10%+
bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
# Requires playerctl
bindl = , XF86AudioNext, exec, playerctl next
bindl = , XF86AudioPause, exec, playerctl play-pause
bindl = , XF86AudioPlay, exec, playerctl play-pause
bindl = , XF86AudioPrev, exec, playerctl previous
############################## ##############################
### WINDOWS AND WORKSPACES ### ### WINDOWS AND WORKSPACES ###
@@ -295,9 +255,5 @@ bindl = , XF86AudioPrev, exec, playerctl previous
# Example windowrule v2 # Example windowrule v2
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$ # windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
# Ignore maximize requests from apps. You'll probably like this. windowrulev2 = suppressevent maximize, class:.* # You'll probably like this.
windowrulev2 = suppressevent maximize, class:.*
# Fix some dragging issues with XWayland
windowrulev2 = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0
)#"; )#";

View File

@@ -2,11 +2,10 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#include <link.h> #include <link.h>
#include <ctime> #include <time.h>
#include <cerrno> #include <errno.h>
#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"
@@ -32,10 +31,10 @@ static char const* const MESSAGES[] = {"Sorry, didn't mean to...",
// <random> is not async-signal-safe, fake it with time(NULL) instead // <random> is not async-signal-safe, fake it with time(NULL) instead
char const* getRandomMessage() { char const* getRandomMessage() {
return MESSAGES[time(nullptr) % (sizeof(MESSAGES) / sizeof(MESSAGES[0]))]; return MESSAGES[time(NULL) % (sizeof(MESSAGES) / sizeof(MESSAGES[0]))];
} }
[[noreturn]] inline void exitWithError(char const* err) { [[noreturn]] inline void exit_with_error(char const* err) {
write(STDERR_FILENO, err, strlen(err)); write(STDERR_FILENO, err, strlen(err));
// perror() is not signal-safe, but we use it here // perror() is not signal-safe, but we use it here
// because if the crash-handler already crashed, it can't get any worse. // because if the crash-handler already crashed, it can't get any worse.
@@ -43,17 +42,17 @@ char const* getRandomMessage() {
abort(); abort();
} }
void NCrashReporter::createAndSaveCrash(int sig) { void CrashReporter::createAndSaveCrash(int sig) {
int reportFd = -1; int reportFd;
// We're in the signal handler, so we *only* have stack memory. // We're in the signal handler, so we *only* have stack memory.
// To save as much stack memory as possible, // To save as much stack memory as possible,
// destroy things as soon as possible. // destroy things as soon as possible.
{ {
CMaxLengthCString<255> reportPath; MaxLengthCString<255> reportPath;
const auto HOME = sigGetenv("HOME"); const auto HOME = sig_getenv("HOME");
const auto CACHE_HOME = sigGetenv("XDG_CACHE_HOME"); const auto CACHE_HOME = sig_getenv("XDG_CACHE_HOME");
if (CACHE_HOME && CACHE_HOME[0] != '\0') { if (CACHE_HOME && CACHE_HOME[0] != '\0') {
reportPath += CACHE_HOME; reportPath += CACHE_HOME;
@@ -62,24 +61,24 @@ void NCrashReporter::createAndSaveCrash(int sig) {
reportPath += HOME; reportPath += HOME;
reportPath += "/.cache/hyprland"; reportPath += "/.cache/hyprland";
} else { } else {
exitWithError("$CACHE_HOME and $HOME not set, nowhere to report crash\n"); exit_with_error("$CACHE_HOME and $HOME not set, nowhere to report crash\n");
return; return;
} }
int ret = mkdir(reportPath.getStr(), S_IRWXU); int ret = mkdir(reportPath.get_str(), S_IRWXU);
//__asm__("int $3"); //__asm__("int $3");
if (ret < 0 && errno != EEXIST) { if (ret < 0 && errno != EEXIST) {
exitWithError("failed to mkdir() crash report directory\n"); exit_with_error("failed to mkdir() crash report directory\n");
} }
reportPath += "/hyprlandCrashReport"; reportPath += "/hyprlandCrashReport";
reportPath.writeNum(getpid()); reportPath.write_num(getpid());
reportPath += ".txt"; reportPath += ".txt";
{ {
CBufFileWriter<64> stderr(2); BufFileWriter<64> stderr(2);
stderr += "Hyprland has crashed :( Consult the crash report at "; stderr += "Hyprland has crashed :( Consult the crash report at ";
if (!reportPath.boundsExceeded()) { if (!reportPath.boundsExceeded()) {
stderr += reportPath.getStr(); stderr += reportPath.get_str();
} else { } else {
stderr += "[ERROR: Crash report path does not fit into memory! Check if your $CACHE_HOME/$HOME is too deeply nested. Max 255 characters.]"; stderr += "[ERROR: Crash report path does not fit into memory! Check if your $CACHE_HOME/$HOME is too deeply nested. Max 255 characters.]";
} }
@@ -87,12 +86,12 @@ void NCrashReporter::createAndSaveCrash(int sig) {
stderr.flush(); stderr.flush();
} }
reportFd = open(reportPath.getStr(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); reportFd = open(reportPath.get_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
if (reportFd < 0) { if (reportFd < 0) {
exitWithError("Failed to open crash report path for writing"); exit_with_error("Failed to open crash report path for writing");
} }
} }
CBufFileWriter<512> finalCrashReport(reportFd); BufFileWriter<512> finalCrashReport(reportFd);
finalCrashReport += "--------------------------------------------\n Hyprland Crash Report\n--------------------------------------------\n"; finalCrashReport += "--------------------------------------------\n Hyprland Crash Report\n--------------------------------------------\n";
finalCrashReport += getRandomMessage(); finalCrashReport += getRandomMessage();
@@ -101,7 +100,7 @@ void NCrashReporter::createAndSaveCrash(int sig) {
finalCrashReport += "Hyprland received signal "; finalCrashReport += "Hyprland received signal ";
finalCrashReport.writeNum(sig); finalCrashReport.writeNum(sig);
finalCrashReport += '('; finalCrashReport += '(';
finalCrashReport += sigStrsignal(sig); finalCrashReport += sig_strsignal(sig);
finalCrashReport += ")\nVersion: "; finalCrashReport += ")\nVersion: ";
finalCrashReport += GIT_COMMIT_HASH; finalCrashReport += GIT_COMMIT_HASH;
finalCrashReport += "\nTag: "; finalCrashReport += "\nTag: ";
@@ -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
@@ -123,9 +122,9 @@ void NCrashReporter::createAndSaveCrash(int sig) {
if (g_pPluginSystem && g_pPluginSystem->pluginCount() > 0) { if (g_pPluginSystem && g_pPluginSystem->pluginCount() > 0) {
finalCrashReport += "Hyprland seems to be running with plugins. This crash might not be Hyprland's fault.\nPlugins:\n"; finalCrashReport += "Hyprland seems to be running with plugins. This crash might not be Hyprland's fault.\nPlugins:\n";
const size_t count = g_pPluginSystem->pluginCount(); size_t count = g_pPluginSystem->pluginCount();
std::vector<CPlugin*> plugins(count); CPlugin* plugins[count];
g_pPluginSystem->sigGetPlugins(plugins.data(), count); g_pPluginSystem->sig_getPlugins(plugins, count);
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
auto p = plugins[i]; auto p = plugins[i];
@@ -160,9 +159,9 @@ void NCrashReporter::createAndSaveCrash(int sig) {
finalCrashReport += "GPU:\n\t"; finalCrashReport += "GPU:\n\t";
#if defined(__DragonFly__) || defined(__FreeBSD__) #if defined(__DragonFly__) || defined(__FreeBSD__)
finalCrashReport.writeCmdOutput("pciconf -lv | grep -F -A4 vga"); finalCrashReport.writeCmdOutput("pciconf -lv | fgrep -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";
@@ -242,5 +241,5 @@ void NCrashReporter::createAndSaveCrash(int sig) {
finalCrashReport += "\n\nLog tail:\n"; finalCrashReport += "\n\nLog tail:\n";
finalCrashReport += std::string_view(Debug::rollingLog).substr(Debug::rollingLog.find('\n') + 1); finalCrashReport += std::string_view(Debug::rollingLog).substr(Debug::rollingLog.find("\n") + 1);
} }

View File

@@ -2,6 +2,6 @@
#include "../defines.hpp" #include "../defines.hpp"
namespace NCrashReporter { namespace CrashReporter {
void createAndSaveCrash(int sig); void createAndSaveCrash(int sig);
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,10 @@
#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
std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request);
std::string versionRequest(eHyprCtlOutputFormat format, std::string request);
class CHyprCtl { class CHyprCtl {
public: public:
CHyprCtl(); CHyprCtl();
@@ -38,4 +34,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,21 +2,13 @@
#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>();
} }
void CHyprMonitorDebugOverlay::renderData(PHLMONITOR pMonitor, float durationUs) { void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) {
static auto PDEBUGOVERLAY = CConfigValue<Hyprlang::INT>("debug:overlay"); m_dLastRenderTimes.push_back(durationUs / 1000.f);
if (!*PDEBUGOVERLAY)
return;
m_dLastRenderTimes.emplace_back(durationUs / 1000.f);
if (m_dLastRenderTimes.size() > (long unsigned int)pMonitor->refreshRate) if (m_dLastRenderTimes.size() > (long unsigned int)pMonitor->refreshRate)
m_dLastRenderTimes.pop_front(); m_dLastRenderTimes.pop_front();
@@ -25,13 +17,8 @@ void CHyprMonitorDebugOverlay::renderData(PHLMONITOR pMonitor, float durationUs)
m_pMonitor = pMonitor; m_pMonitor = pMonitor;
} }
void CHyprMonitorDebugOverlay::renderDataNoOverlay(PHLMONITOR pMonitor, float durationUs) { void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) {
static auto PDEBUGOVERLAY = CConfigValue<Hyprlang::INT>("debug:overlay"); m_dLastRenderTimesNoOverlay.push_back(durationUs / 1000.f);
if (!*PDEBUGOVERLAY)
return;
m_dLastRenderTimesNoOverlay.emplace_back(durationUs / 1000.f);
if (m_dLastRenderTimesNoOverlay.size() > (long unsigned int)pMonitor->refreshRate) if (m_dLastRenderTimesNoOverlay.size() > (long unsigned int)pMonitor->refreshRate)
m_dLastRenderTimesNoOverlay.pop_front(); m_dLastRenderTimesNoOverlay.pop_front();
@@ -40,13 +27,8 @@ void CHyprMonitorDebugOverlay::renderDataNoOverlay(PHLMONITOR pMonitor, float du
m_pMonitor = pMonitor; m_pMonitor = pMonitor;
} }
void CHyprMonitorDebugOverlay::frameData(PHLMONITOR pMonitor) { void CHyprMonitorDebugOverlay::frameData(CMonitor* pMonitor) {
static auto PDEBUGOVERLAY = CConfigValue<Hyprlang::INT>("debug:overlay"); m_dLastFrametimes.push_back(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - m_tpLastFrame).count() / 1000.f);
if (!*PDEBUGOVERLAY)
return;
m_dLastFrametimes.emplace_back(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - m_tpLastFrame).count() / 1000.f);
if (m_dLastFrametimes.size() > (long unsigned int)pMonitor->refreshRate) if (m_dLastFrametimes.size() > (long unsigned int)pMonitor->refreshRate)
m_dLastFrametimes.pop_front(); m_dLastFrametimes.pop_front();
@@ -57,7 +39,7 @@ void CHyprMonitorDebugOverlay::frameData(PHLMONITOR pMonitor) {
m_pMonitor = pMonitor; m_pMonitor = pMonitor;
// anim data too // anim data too
const auto PMONITORFORTICKS = g_pHyprRenderer->m_pMostHzMonitor ? g_pHyprRenderer->m_pMostHzMonitor.lock() : g_pCompositor->m_pLastMonitor.lock(); const auto PMONITORFORTICKS = g_pHyprRenderer->m_pMostHzMonitor ? g_pHyprRenderer->m_pMostHzMonitor : g_pCompositor->m_pLastMonitor.get();
if (PMONITORFORTICKS) { if (PMONITORFORTICKS) {
if (m_dLastAnimationTicks.size() > (long unsigned int)PMONITORFORTICKS->refreshRate) if (m_dLastAnimationTicks.size() > (long unsigned int)PMONITORFORTICKS->refreshRate)
m_dLastAnimationTicks.pop_front(); m_dLastAnimationTicks.pop_front();
@@ -75,7 +57,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
float avgFrametime = 0; float avgFrametime = 0;
float maxFrametime = 0; float maxFrametime = 0;
float minFrametime = 9999; float minFrametime = 9999;
for (auto const& ft : m_dLastFrametimes) { for (auto& ft : m_dLastFrametimes) {
if (ft > maxFrametime) if (ft > maxFrametime)
maxFrametime = ft; maxFrametime = ft;
if (ft < minFrametime) if (ft < minFrametime)
@@ -88,7 +70,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
float avgRenderTime = 0; float avgRenderTime = 0;
float maxRenderTime = 0; float maxRenderTime = 0;
float minRenderTime = 9999; float minRenderTime = 9999;
for (auto const& rt : m_dLastRenderTimes) { for (auto& rt : m_dLastRenderTimes) {
if (rt > maxRenderTime) if (rt > maxRenderTime)
maxRenderTime = rt; maxRenderTime = rt;
if (rt < minRenderTime) if (rt < minRenderTime)
@@ -101,7 +83,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
float avgRenderTimeNoOverlay = 0; float avgRenderTimeNoOverlay = 0;
float maxRenderTimeNoOverlay = 0; float maxRenderTimeNoOverlay = 0;
float minRenderTimeNoOverlay = 9999; float minRenderTimeNoOverlay = 9999;
for (auto const& rt : m_dLastRenderTimesNoOverlay) { for (auto& rt : m_dLastRenderTimesNoOverlay) {
if (rt > maxRenderTimeNoOverlay) if (rt > maxRenderTimeNoOverlay)
maxRenderTimeNoOverlay = rt; maxRenderTimeNoOverlay = rt;
if (rt < minRenderTimeNoOverlay) if (rt < minRenderTimeNoOverlay)
@@ -114,7 +96,7 @@ int CHyprMonitorDebugOverlay::draw(int offset) {
float avgAnimMgrTick = 0; float avgAnimMgrTick = 0;
float maxAnimMgrTick = 0; float maxAnimMgrTick = 0;
float minAnimMgrTick = 9999; float minAnimMgrTick = 9999;
for (auto const& at : m_dLastAnimationTicks) { for (auto& at : m_dLastAnimationTicks) {
if (at > maxAnimMgrTick) if (at > maxAnimMgrTick)
maxAnimMgrTick = at; maxAnimMgrTick = at;
if (at < minAnimMgrTick) if (at < minAnimMgrTick)
@@ -198,44 +180,29 @@ 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;
} }
void CHyprDebugOverlay::renderData(PHLMONITOR pMonitor, float durationUs) { void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float durationUs) {
static auto PDEBUGOVERLAY = CConfigValue<Hyprlang::INT>("debug:overlay");
if (!*PDEBUGOVERLAY)
return;
m_mMonitorOverlays[pMonitor].renderData(pMonitor, durationUs); m_mMonitorOverlays[pMonitor].renderData(pMonitor, durationUs);
} }
void CHyprDebugOverlay::renderDataNoOverlay(PHLMONITOR pMonitor, float durationUs) { void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float durationUs) {
static auto PDEBUGOVERLAY = CConfigValue<Hyprlang::INT>("debug:overlay");
if (!*PDEBUGOVERLAY)
return;
m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, durationUs); m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, durationUs);
} }
void CHyprDebugOverlay::frameData(PHLMONITOR pMonitor) { void CHyprDebugOverlay::frameData(CMonitor* pMonitor) {
static auto PDEBUGOVERLAY = CConfigValue<Hyprlang::INT>("debug:overlay");
if (!*PDEBUGOVERLAY)
return;
m_mMonitorOverlays[pMonitor].frameData(pMonitor); m_mMonitorOverlays[pMonitor].frameData(pMonitor);
} }
void CHyprDebugOverlay::draw() { void CHyprDebugOverlay::draw() {
const auto PMONITOR = g_pCompositor->m_vMonitors.front(); const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
if (!m_pCairoSurface || !m_pCairo) { if (!m_pCairoSurface || !m_pCairo) {
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
@@ -250,8 +217,8 @@ void CHyprDebugOverlay::draw() {
// draw the things // draw the things
int offsetY = 0; int offsetY = 0;
for (auto const& m : g_pCompositor->m_vMonitors) { for (auto& m : g_pCompositor->m_vMonitors) {
offsetY += m_mMonitorOverlays[m].draw(offsetY); offsetY += m_mMonitorOverlays[m.get()].draw(offsetY);
offsetY += 5; // for padding between mons offsetY += 5; // for padding between mons
} }
@@ -271,8 +238,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,10 +1,11 @@
#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 <map>
#include <deque> #include <deque>
#include <cairo/cairo.h>
#include <unordered_map>
class CHyprRenderer; class CHyprRenderer;
@@ -12,9 +13,9 @@ class CHyprMonitorDebugOverlay {
public: public:
int draw(int offset); int draw(int offset);
void renderData(PHLMONITOR pMonitor, float durationUs); void renderData(CMonitor* pMonitor, float durationUs);
void renderDataNoOverlay(PHLMONITOR pMonitor, float durationUs); void renderDataNoOverlay(CMonitor* pMonitor, float durationUs);
void frameData(PHLMONITOR pMonitor); void frameData(CMonitor* pMonitor);
private: private:
std::deque<float> m_dLastFrametimes; std::deque<float> m_dLastFrametimes;
@@ -22,7 +23,7 @@ class CHyprMonitorDebugOverlay {
std::deque<float> m_dLastRenderTimesNoOverlay; std::deque<float> m_dLastRenderTimesNoOverlay;
std::deque<float> m_dLastAnimationTicks; std::deque<float> m_dLastAnimationTicks;
std::chrono::high_resolution_clock::time_point m_tpLastFrame; std::chrono::high_resolution_clock::time_point m_tpLastFrame;
PHLMONITORREF m_pMonitor; CMonitor* m_pMonitor = nullptr;
CBox m_wbLastDrawnBox; CBox m_wbLastDrawnBox;
friend class CHyprRenderer; friend class CHyprRenderer;
@@ -32,12 +33,12 @@ class CHyprDebugOverlay {
public: public:
CHyprDebugOverlay(); CHyprDebugOverlay();
void draw(); void draw();
void renderData(PHLMONITOR, float durationUs); void renderData(CMonitor*, float durationUs);
void renderDataNoOverlay(PHLMONITOR, float durationUs); void renderDataNoOverlay(CMonitor*, float durationUs);
void frameData(PHLMONITOR); void frameData(CMonitor*);
private: private:
std::map<PHLMONITORREF, CHyprMonitorDebugOverlay> m_mMonitorOverlays; std::unordered_map<CMonitor*, CHyprMonitorDebugOverlay> m_mMonitorOverlays;
cairo_surface_t* m_pCairoSurface = nullptr; cairo_surface_t* m_pCairoSurface = nullptr;
cairo_t* m_pCairo = nullptr; cairo_t* m_pCairo = nullptr;
@@ -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) {
@@ -23,10 +18,10 @@ static inline auto iconBackendFromLayout(PangoLayout* layout) {
CHyprNotificationOverlay::CHyprNotificationOverlay() { CHyprNotificationOverlay::CHyprNotificationOverlay() {
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_vNotifications.size() == 0) if (m_dNotifications.size() == 0)
return; return;
g_pHyprRenderer->damageBox(m_bLastDamage); g_pHyprRenderer->damageBox(&m_bLastDamage);
}); });
m_pTexture = makeShared<CTexture>(); m_pTexture = makeShared<CTexture>();
@@ -39,34 +34,34 @@ CHyprNotificationOverlay::~CHyprNotificationOverlay() {
cairo_surface_destroy(m_pCairoSurface); cairo_surface_destroy(m_pCairoSurface);
} }
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 CColor& color, const float timeMs, const eIcons icon, const float fontSize) {
const auto PNOTIF = m_vNotifications.emplace_back(makeUnique<SNotification>()).get(); const auto PNOTIF = m_dNotifications.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 = text;
PNOTIF->color = color == CHyprColor(0) ? ICONS_COLORS[icon] : color; PNOTIF->color = color == CColor(0) ? ICONS_COLORS[icon] : color;
PNOTIF->started.reset(); PNOTIF->started.reset();
PNOTIF->timeMs = timeMs; PNOTIF->timeMs = timeMs;
PNOTIF->icon = icon; PNOTIF->icon = icon;
PNOTIF->fontSize = fontSize; PNOTIF->fontSize = fontSize;
for (auto const& m : g_pCompositor->m_vMonitors) { for (auto& m : g_pCompositor->m_vMonitors) {
g_pCompositor->scheduleFrameForMonitor(m); g_pCompositor->scheduleFrameForMonitor(m.get());
} }
} }
void CHyprNotificationOverlay::dismissNotifications(const int amount) { void CHyprNotificationOverlay::dismissNotifications(const int amount) {
if (amount == -1) if (amount == -1)
m_vNotifications.clear(); m_dNotifications.clear();
else { else {
const int AMT = std::min(amount, static_cast<int>(m_vNotifications.size())); const int AMT = std::min(amount, static_cast<int>(m_dNotifications.size()));
for (int i = 0; i < AMT; ++i) { for (int i = 0; i < AMT; ++i) {
m_vNotifications.erase(m_vNotifications.begin()); m_dNotifications.pop_front();
} }
} }
} }
CBox CHyprNotificationOverlay::drawNotifications(PHLMONITOR pMonitor) { CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) {
static constexpr auto ANIM_DURATION_MS = 600.0; static constexpr auto ANIM_DURATION_MS = 600.0;
static constexpr auto ANIM_LAG_MS = 100.0; static constexpr auto ANIM_LAG_MS = 100.0;
static constexpr auto NOTIF_LEFTBAR_SIZE = 5.0; static constexpr auto NOTIF_LEFTBAR_SIZE = 5.0;
@@ -92,7 +87,7 @@ CBox CHyprNotificationOverlay::drawNotifications(PHLMONITOR pMonitor) {
const auto iconBackendID = iconBackendFromLayout(layout); const auto iconBackendID = iconBackendFromLayout(layout);
const auto PBEZIER = g_pAnimationManager->getBezier("default"); const auto PBEZIER = g_pAnimationManager->getBezier("default");
for (auto const& notif : m_vNotifications) { for (auto& notif : m_dNotifications) {
const auto ICONPADFORNOTIF = notif->icon == ICON_NONE ? 0 : ICON_PAD; const auto ICONPADFORNOTIF = notif->icon == ICON_NONE ? 0 : ICON_PAD;
const auto FONTSIZE = std::clamp((int)(notif->fontSize * ((pMonitor->vecPixelSize.x * SCALE) / 1920.f)), 8, 40); const auto FONTSIZE = std::clamp((int)(notif->fontSize * ((pMonitor->vecPixelSize.x * SCALE) / 1920.f)), 8, 40);
@@ -187,12 +182,12 @@ CBox CHyprNotificationOverlay::drawNotifications(PHLMONITOR pMonitor) {
g_object_unref(layout); g_object_unref(layout);
// cleanup notifs // cleanup notifs
std::erase_if(m_vNotifications, [](const auto& notif) { return notif->started.getMillis() > notif->timeMs; }); std::erase_if(m_dNotifications, [](const auto& notif) { return notif->started.getMillis() > notif->timeMs; });
return CBox{(int)(pMonitor->vecPosition.x + pMonitor->vecSize.x - maxWidth - 20), (int)pMonitor->vecPosition.y, (int)maxWidth + 20, (int)offsetY + 10}; return CBox{(int)(pMonitor->vecPosition.x + pMonitor->vecSize.x - maxWidth - 20), (int)pMonitor->vecPosition.y, (int)maxWidth + 20, (int)offsetY + 10};
} }
void CHyprNotificationOverlay::draw(PHLMONITOR pMonitor) { void CHyprNotificationOverlay::draw(CMonitor* pMonitor) {
const auto MONSIZE = pMonitor->vecTransformedSize; const auto MONSIZE = pMonitor->vecTransformedSize;
@@ -210,7 +205,7 @@ void CHyprNotificationOverlay::draw(PHLMONITOR pMonitor) {
} }
// Draw the notifications // Draw the notifications
if (m_vNotifications.size() == 0) if (m_dNotifications.size() == 0)
return; return;
// Render to the monitor // Render to the monitor
@@ -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,14 +241,10 @@ 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() {
return !m_vNotifications.empty(); return !m_dNotifications.empty();
} }

View File

@@ -2,14 +2,15 @@
#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"
#include <vector> #include <deque>
#include <cairo/cairo.h> #include <cairo/cairo.h>
enum eIconBackend : uint8_t { enum eIconBackend {
ICONS_BACKEND_NONE = 0, ICONS_BACKEND_NONE = 0,
ICONS_BACKEND_NF, ICONS_BACKEND_NF,
ICONS_BACKEND_FA ICONS_BACKEND_FA
@@ -18,17 +19,17 @@ enum eIconBackend : uint8_t {
static const std::array<std::array<std::string, ICON_NONE + 1>, 3 /* backends */> ICONS_ARRAY = { static const std::array<std::array<std::string, ICON_NONE + 1>, 3 /* backends */> ICONS_ARRAY = {
std::array<std::string, ICON_NONE + 1>{"[!]", "[i]", "[Hint]", "[Err]", "[?]", "[ok]", ""}, std::array<std::string, ICON_NONE + 1>{"[!]", "[i]", "[Hint]", "[Err]", "[?]", "[ok]", ""},
std::array<std::string, ICON_NONE + 1>{"", "", "", "", "", "󰸞", ""}, std::array<std::string, ICON_NONE + 1>{"", "", "", "", "", ""}}; std::array<std::string, ICON_NONE + 1>{"", "", "", "", "", "󰸞", ""}, std::array<std::string, ICON_NONE + 1>{"", "", "", "", "", ""}};
static const std::array<CHyprColor, ICON_NONE + 1> ICONS_COLORS = {CHyprColor{255.0 / 255.0, 204 / 255.0, 102 / 255.0, 1.0}, static const std::array<CColor, ICON_NONE + 1> ICONS_COLORS = {CColor{255.0 / 255.0, 204 / 255.0, 102 / 255.0, 1.0},
CHyprColor{128 / 255.0, 255 / 255.0, 255 / 255.0, 1.0}, CColor{128 / 255.0, 255 / 255.0, 255 / 255.0, 1.0},
CHyprColor{179 / 255.0, 255 / 255.0, 204 / 255.0, 1.0}, CColor{179 / 255.0, 255 / 255.0, 204 / 255.0, 1.0},
CHyprColor{255 / 255.0, 77 / 255.0, 77 / 255.0, 1.0}, CColor{255 / 255.0, 77 / 255.0, 77 / 255.0, 1.0},
CHyprColor{255 / 255.0, 204 / 255.0, 153 / 255.0, 1.0}, CColor{255 / 255.0, 204 / 255.0, 153 / 255.0, 1.0},
CHyprColor{128 / 255.0, 255 / 255.0, 128 / 255.0, 1.0}, CColor{128 / 255.0, 255 / 255.0, 128 / 255.0, 1.0},
CHyprColor{0, 0, 0, 1.0}}; CColor{0, 0, 0, 1.0}};
struct SNotification { struct SNotification {
std::string text = ""; std::string text = "";
CHyprColor color; CColor color;
CTimer started; CTimer started;
float timeMs = 0; float timeMs = 0;
eIcons icon = ICON_NONE; eIcons icon = ICON_NONE;
@@ -40,24 +41,24 @@ class CHyprNotificationOverlay {
CHyprNotificationOverlay(); CHyprNotificationOverlay();
~CHyprNotificationOverlay(); ~CHyprNotificationOverlay();
void draw(PHLMONITOR pMonitor); void draw(CMonitor* pMonitor);
void addNotification(const std::string& text, const CHyprColor& color, const float timeMs, const eIcons icon = ICON_NONE, const float fontSize = 13.f); void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE, const float fontSize = 13.f);
void dismissNotifications(const int amount); void dismissNotifications(const int amount);
bool hasAny(); bool hasAny();
private: private:
CBox drawNotifications(PHLMONITOR pMonitor); CBox drawNotifications(CMonitor* pMonitor);
CBox m_bLastDamage; CBox m_bLastDamage;
std::vector<UP<SNotification>> m_vNotifications; std::deque<std::unique_ptr<SNotification>> m_dNotifications;
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; CMonitor* m_pLastMonitor = nullptr;
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,9 +1,10 @@
#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>
#include <print> #include <iostream>
#include <fcntl.h> #include <fcntl.h>
void Debug::init(const std::string& IS) { void Debug::init(const std::string& IS) {
@@ -17,7 +18,7 @@ void Debug::close() {
logOfs.close(); logOfs.close();
} }
void Debug::log(eLogLevel level, std::string str) { void Debug::log(LogLevel level, std::string str) {
if (level == TRACE && !trace) if (level == TRACE && !trace)
return; return;
@@ -25,7 +26,6 @@ void Debug::log(eLogLevel level, std::string str) {
return; return;
std::string coloredStr = str; std::string coloredStr = str;
//NOLINTBEGIN
switch (level) { switch (level) {
case LOG: case LOG:
str = "[LOG] " + str; str = "[LOG] " + str;
@@ -53,14 +53,13 @@ void Debug::log(eLogLevel level, std::string str) {
break; break;
default: break; default: break;
} }
//NOLINTEND
rollingLog += str + "\n"; rollingLog += str + "\n";
if (rollingLog.size() > ROLLING_LOG_SIZE) if (rollingLog.size() > ROLLING_LOG_SIZE)
rollingLog = rollingLog.substr(rollingLog.size() - ROLLING_LOG_SIZE); rollingLog = rollingLog.substr(rollingLog.size() - ROLLING_LOG_SIZE);
if (SRollingLogFollow::get().isRunning()) if (RollingLogFollow::Get().IsRunning())
SRollingLogFollow::get().addLog(str); RollingLogFollow::Get().AddLog(str);
if (!disableLogs || !**disableLogs) { if (!disableLogs || !**disableLogs) {
// log to a file // log to a file
@@ -70,5 +69,5 @@ void Debug::log(eLogLevel level, std::string str) {
// log it to the stdout too. // log it to the stdout too.
if (!disableStdout) if (!disableStdout)
std::println("{}", ((coloredLogs && !**coloredLogs) ? str : coloredStr)); std::cout << ((coloredLogs && !**coloredLogs) ? str : coloredStr) << "\n";
} }

View File

@@ -5,11 +5,13 @@
#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
enum eLogLevel : int8_t { enum LogLevel {
NONE = -1, NONE = -1,
LOG = 0, LOG = 0,
WARN, WARN,
@@ -19,7 +21,6 @@ enum eLogLevel : int8_t {
TRACE TRACE
}; };
// NOLINTNEXTLINE(readability-identifier-naming)
namespace Debug { namespace Debug {
inline std::string logFile; inline std::string logFile;
inline std::ofstream logOfs; inline std::ofstream logOfs;
@@ -37,11 +38,10 @@ namespace Debug {
void close(); void close();
// //
void log(eLogLevel level, std::string str); void log(LogLevel level, std::string str);
template <typename... Args> template <typename... Args>
//NOLINTNEXTLINE void log(LogLevel level, std::format_string<Args...> fmt, Args&&... args) {
void log(eLogLevel level, std::format_string<Args...> fmt, Args&&... args) {
std::lock_guard<std::mutex> guard(logMutex); std::lock_guard<std::mutex> guard(logMutex);
if (level == TRACE && !trace) if (level == TRACE && !trace)
@@ -55,8 +55,7 @@ namespace Debug {
// print date and time to the ofs // print date and time to the ofs
if (disableTime && !**disableTime) { if (disableTime && !**disableTime) {
#ifndef _LIBCPP_VERSION #ifndef _LIBCPP_VERSION
static auto current_zone = std::chrono::current_zone(); const auto zt = std::chrono::zoned_time{std::chrono::current_zone(), std::chrono::system_clock::now()};
const auto zt = std::chrono::zoned_time{current_zone, std::chrono::system_clock::now()};
const auto hms = std::chrono::hh_mm_ss{zt.get_local_time() - std::chrono::floor<std::chrono::days>(zt.get_local_time())}; const auto hms = std::chrono::hh_mm_ss{zt.get_local_time() - std::chrono::floor<std::chrono::days>(zt.get_local_time())};
#else #else
// TODO: current clang 17 does not support `zoned_time`, remove this once clang 19 is ready // TODO: current clang 17 does not support `zoned_time`, remove this once clang 19 is ready

View File

@@ -2,9 +2,8 @@
#include <shared_mutex> #include <shared_mutex>
// NOLINTNEXTLINE(readability-identifier-naming)
namespace Debug { namespace Debug {
struct SRollingLogFollow { struct RollingLogFollow {
std::unordered_map<int, std::string> socketToRollingLogFollowQueue; std::unordered_map<int, std::string> socketToRollingLogFollowQueue;
std::shared_mutex m; std::shared_mutex m;
bool running = false; bool running = false;
@@ -16,12 +15,12 @@ namespace Debug {
return socketToRollingLogFollowQueue[socket].empty(); return socketToRollingLogFollowQueue[socket].empty();
} }
std::string debugInfo() { std::string DebugInfo() {
std::shared_lock<std::shared_mutex> r(m); std::shared_lock<std::shared_mutex> r(m);
return std::format("RollingLogFollow, got {} connections", socketToRollingLogFollowQueue.size()); return std::format("RollingLogFollow, got {} connections", socketToRollingLogFollowQueue.size());
} }
std::string getLog(int socket) { std::string GetLog(int socket) {
std::unique_lock<std::shared_mutex> w(m); std::unique_lock<std::shared_mutex> w(m);
const std::string ret = socketToRollingLogFollowQueue[socket]; const std::string ret = socketToRollingLogFollowQueue[socket];
@@ -30,7 +29,7 @@ namespace Debug {
return ret; return ret;
}; };
void addLog(const std::string& log) { void AddLog(std::string log) {
std::unique_lock<std::shared_mutex> w(m); std::unique_lock<std::shared_mutex> w(m);
running = true; running = true;
std::vector<int> to_erase; std::vector<int> to_erase;
@@ -38,26 +37,26 @@ namespace Debug {
socketToRollingLogFollowQueue[p.first] += log + "\n"; socketToRollingLogFollowQueue[p.first] += log + "\n";
} }
bool isRunning() { bool IsRunning() {
std::shared_lock<std::shared_mutex> r(m); std::shared_lock<std::shared_mutex> r(m);
return running; return running;
} }
void stopFor(int socket) { void StopFor(int socket) {
std::unique_lock<std::shared_mutex> w(m); std::unique_lock<std::shared_mutex> w(m);
socketToRollingLogFollowQueue.erase(socket); socketToRollingLogFollowQueue.erase(socket);
if (socketToRollingLogFollowQueue.empty()) if (socketToRollingLogFollowQueue.empty())
running = false; running = false;
} }
void startFor(int socket) { void StartFor(int socket) {
std::unique_lock<std::shared_mutex> w(m); std::unique_lock<std::shared_mutex> w(m);
socketToRollingLogFollowQueue[socket] = std::format("[LOG] Following log to socket: {} started\n", socket); socketToRollingLogFollowQueue[socket] = std::format("[LOG] Following log to socket: {} started\n", socket);
running = true; running = true;
} }
static SRollingLogFollow& get() { static RollingLogFollow& Get() {
static SRollingLogFollow instance; static RollingLogFollow instance;
static std::mutex gm; static std::mutex gm;
std::lock_guard<std::mutex> lock(gm); std::lock_guard<std::mutex> lock(gm);
return instance; return instance;

View File

@@ -1,7 +1,6 @@
#pragma once
#include "includes.hpp" #include "includes.hpp"
#include "debug/Log.hpp" #include "debug/Log.hpp"
#include "helpers/WLListener.hpp"
#include "helpers/Color.hpp" #include "helpers/Color.hpp"
#include "macros.hpp" #include "macros.hpp"
#include "desktop/DesktopTypes.hpp" #include "desktop/DesktopTypes.hpp"

View File

@@ -1,9 +1,8 @@
#pragma once #pragma once
#include "../helpers/memory/Memory.hpp" #include "../macros.hpp"
class CWorkspace; class CWorkspace;
class CWindow; class CWindow;
class CLayerSurface; class CLayerSurface;
class CMonitor;
/* Shared pointer to a workspace */ /* Shared pointer to a workspace */
typedef SP<CWorkspace> PHLWORKSPACE; typedef SP<CWorkspace> PHLWORKSPACE;
@@ -19,8 +18,3 @@ typedef WP<CWindow> PHLWINDOWREF;
typedef SP<CLayerSurface> PHLLS; typedef SP<CLayerSurface> PHLLS;
/* Weak pointer to a layer surface */ /* Weak pointer to a layer surface */
typedef WP<CLayerSurface> PHLLSREF; typedef WP<CLayerSurface> PHLLSREF;
/* Shared pointer to a monitor */
typedef SP<CMonitor> PHLMONITOR;
/* Weak pointer to a monitor */
typedef WP<CMonitor> PHLMONITORREF;

View File

@@ -1,38 +0,0 @@
#include <re2/re2.h>
#include "LayerRule.hpp"
#include <unordered_set>
#include <algorithm>
#include "../debug/Log.hpp"
static const auto RULES = std::unordered_set<std::string>{"noanim", "blur", "blurpopups", "dimaround"};
static const auto RULES_PREFIX = std::unordered_set<std::string>{"ignorealpha", "ignorezero", "xray", "animation", "order"};
CLayerRule::CLayerRule(const std::string& rule_, const std::string& ns_) : targetNamespace(ns_), rule(rule_) {
const bool VALID = RULES.contains(rule) || std::any_of(RULES_PREFIX.begin(), RULES_PREFIX.end(), [&rule_](const auto& prefix) { return rule_.starts_with(prefix); });
if (!VALID)
return;
if (rule == "noanim")
ruleType = RULE_NOANIM;
else if (rule == "blur")
ruleType = RULE_BLUR;
else if (rule == "blurpopups")
ruleType = RULE_BLURPOPUPS;
else if (rule == "dimaround")
ruleType = RULE_DIMAROUND;
else if (rule.starts_with("ignorealpha"))
ruleType = RULE_IGNOREALPHA;
else if (rule.starts_with("ignorezero"))
ruleType = RULE_IGNOREZERO;
else if (rule.starts_with("xray"))
ruleType = RULE_XRAY;
else if (rule.starts_with("animation"))
ruleType = RULE_ANIMATION;
else if (rule.starts_with("order"))
ruleType = RULE_ORDER;
else {
Debug::log(ERR, "CLayerRule: didn't match a rule that was found valid?!");
ruleType = RULE_INVALID;
}
}

View File

@@ -1,31 +0,0 @@
#pragma once
#include <string>
#include <cstdint>
#include "Rule.hpp"
class CLayerRule {
public:
CLayerRule(const std::string& rule, const std::string& targetNS);
enum eRuleType : uint8_t {
RULE_INVALID = 0,
RULE_NOANIM,
RULE_BLUR,
RULE_BLURPOPUPS,
RULE_DIMAROUND,
RULE_IGNOREALPHA,
RULE_IGNOREZERO,
RULE_XRAY,
RULE_ANIMATION,
RULE_ORDER,
RULE_ZUMBA,
};
eRuleType ruleType = RULE_INVALID;
const std::string targetNamespace;
const std::string rule;
CRuleRegexContainer targetNamespaceRegex;
};

View File

@@ -4,18 +4,11 @@
#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));
auto pMonitor = resource->monitor.empty() ? g_pCompositor->m_pLastMonitor.lock() : g_pCompositor->getMonitorFromName(resource->monitor); CMonitor* pMonitor = resource->monitor.empty() ? g_pCompositor->getMonitorFromCursor() : g_pCompositor->getMonitorFromName(resource->monitor);
pLS->surface->assign(resource->surface.lock(), pLS); pLS->surface->assign(resource->surface.lock(), pLS);
@@ -25,26 +18,29 @@ PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) {
} }
if (pMonitor->pMirrorOf) if (pMonitor->pMirrorOf)
pMonitor = g_pCompositor->m_vMonitors.front(); pMonitor = g_pCompositor->m_vMonitors.front().get();
pLS->self = pLS; pLS->self = pLS;
pLS->szNamespace = resource->layerNamespace; pLS->szNamespace = resource->layerNamespace;
pLS->layer = resource->current.layer; pLS->layer = resource->current.layer;
pLS->popupHead = CPopup::create(pLS); pLS->popupHead = std::make_unique<CPopup>(pLS);
pLS->monitor = pMonitor; pLS->monitorID = pMonitor->ID;
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);
@@ -52,9 +48,9 @@ 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(g_pCompositor->getMonitorFromID(monitorID));
}); });
} }
@@ -76,7 +72,7 @@ CLayerSurface::~CLayerSurface() {
g_pHyprRenderer->makeEGLCurrent(); g_pHyprRenderer->makeEGLCurrent();
std::erase_if(g_pHyprOpenGL->m_mLayerFramebuffers, [&](const auto& other) { return other.first.expired() || other.first.lock() == self.lock(); }); std::erase_if(g_pHyprOpenGL->m_mLayerFramebuffers, [&](const auto& other) { return other.first.expired() || other.first.lock() == self.lock(); });
for (auto const& mon : g_pCompositor->m_vRealMonitors) { for (auto& mon : g_pCompositor->m_vRealMonitors) {
for (auto& lsl : mon->m_aLayerSurfaceLayers) { for (auto& lsl : mon->m_aLayerSurfaceLayers) {
std::erase_if(lsl, [this](auto& ls) { return ls.expired() || ls.get() == this; }); std::erase_if(lsl, [this](auto& ls) { return ls.expired() || ls.get() == this; });
} }
@@ -86,9 +82,9 @@ CLayerSurface::~CLayerSurface() {
void CLayerSurface::onDestroy() { void CLayerSurface::onDestroy() {
Debug::log(LOG, "LayerSurface {:x} destroyed", (uintptr_t)layerSurface.get()); Debug::log(LOG, "LayerSurface {:x} destroyed", (uintptr_t)layerSurface.get());
const auto PMONITOR = monitor.lock(); const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
if (!PMONITOR) if (!g_pCompositor->getMonitorFromID(monitorID))
Debug::log(WARN, "Layersurface destroyed on an invalid monitor (removed?)"); Debug::log(WARN, "Layersurface destroyed on an invalid monitor (removed?)");
if (!fadingOut) { if (!fadingOut) {
@@ -97,8 +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.");
if (alpha) 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;
@@ -142,7 +137,7 @@ void CLayerSurface::onMap() {
g_pCompositor->removeFromFadingOutSafe(self.lock()); g_pCompositor->removeFromFadingOutSafe(self.lock());
// fix if it changed its mon // fix if it changed its mon
const auto PMONITOR = monitor.lock(); const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
if (!PMONITOR) if (!PMONITOR)
return; return;
@@ -179,8 +174,9 @@ 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 auto WORKSPACE = PMONITOR->activeWorkspace;
const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FSMODE_FULLSCREEN;
startAnimation(!(layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS)); startAnimation(!(layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP && FULLSCREEN && !GRABSFOCUS));
readyToDelete = false; readyToDelete = false;
@@ -201,7 +197,7 @@ void CLayerSurface::onUnmap() {
std::erase_if(g_pInputManager->m_dExclusiveLSes, [this](const auto& other) { return !other.lock() || other.lock() == self.lock(); }); std::erase_if(g_pInputManager->m_dExclusiveLSes, [this](const auto& other) { return !other.lock() || other.lock() == self.lock(); });
if (!monitor || g_pCompositor->m_bUnsafeState) { if (!g_pCompositor->getMonitorFromID(monitorID) || g_pCompositor->m_bUnsafeState) {
Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring."); Debug::log(WARN, "Layersurface unmapping on invalid monitor (removed?) ignoring.");
g_pCompositor->addToFadingOutSafe(self.lock()); g_pCompositor->addToFadingOutSafe(self.lock());
@@ -215,7 +211,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);
@@ -225,9 +221,9 @@ void CLayerSurface::onUnmap() {
g_pCompositor->addToFadingOutSafe(self.lock()); g_pCompositor->addToFadingOutSafe(self.lock());
const auto PMONITOR = monitor.lock(); const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
const bool WASLASTFOCUS = g_pSeatManager->state.keyboardFocus == surface->resource() || g_pSeatManager->state.pointerFocus == surface->resource(); const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == surface->resource();
if (!PMONITOR) if (!PMONITOR)
return; return;
@@ -236,17 +232,17 @@ void CLayerSurface::onUnmap() {
// vvvvvvvvvvvvv if there is a last focus and the last focus is not keyboard focusable, fallback to window // vvvvvvvvvvvvv if there is a last focus and the last focus is not keyboard focusable, fallback to window
if (WASLASTFOCUS || (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastFocus->hlSurface && !g_pCompositor->m_pLastFocus->hlSurface->keyboardFocusable())) if (WASLASTFOCUS || (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastFocus->hlSurface && !g_pCompositor->m_pLastFocus->hlSurface->keyboardFocusable()))
g_pInputManager->refocusLastWindow(PMONITOR); g_pInputManager->refocusLastWindow(PMONITOR);
else if (g_pCompositor->m_pLastFocus && g_pCompositor->m_pLastFocus != surface->resource()) else if (g_pCompositor->m_pLastFocus)
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);
} }
@@ -260,13 +256,13 @@ void CLayerSurface::onCommit() {
if (layerSurface->surface && !layerSurface->surface->current.texture) { if (layerSurface->surface && !layerSurface->surface->current.texture) {
fadingOut = false; fadingOut = false;
geometry = {}; geometry = {};
g_pHyprRenderer->arrangeLayersForMonitor(monitorID()); g_pHyprRenderer->arrangeLayersForMonitor(monitorID);
} }
return; return;
} }
const auto PMONITOR = monitor.lock(); const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID);
if (!PMONITOR) if (!PMONITOR)
return; return;
@@ -275,7 +271,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,31 +308,21 @@ 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) {
bool WASLASTFOCUS = false; const bool WASLASTFOCUS = g_pCompositor->m_pLastFocus == surface->resource();
layerSurface->surface->breadthfirst(
[&WASLASTFOCUS](SP<CWLSurfaceResource> surf, const Vector2D& offset, void* data) { WASLASTFOCUS = WASLASTFOCUS || g_pSeatManager->state.keyboardFocus == surf; },
nullptr);
if (!WASLASTFOCUS && popupHead) {
popupHead->breadthfirst(
[&WASLASTFOCUS](WP<CPopup> popup, void* data) {
WASLASTFOCUS = WASLASTFOCUS || (popup->m_pWLSurface && g_pSeatManager->state.keyboardFocus == popup->m_pWLSurface->resource());
},
nullptr);
}
const bool WASEXCLUSIVE = interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE; const bool WASEXCLUSIVE = interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE;
const bool ISEXCLUSIVE = layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE; const bool ISEXCLUSIVE = layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE;
@@ -346,13 +332,11 @@ void CLayerSurface::onCommit() {
std::erase_if(g_pInputManager->m_dExclusiveLSes, [this](const auto& other) { return !other.lock() || other.lock() == self.lock(); }); std::erase_if(g_pInputManager->m_dExclusiveLSes, [this](const auto& other) { return !other.lock() || other.lock() == self.lock(); });
// if the surface was focused and interactive but now isn't, refocus // if the surface was focused and interactive but now isn't, refocus
if (WASLASTFOCUS && layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE) { if (WASLASTFOCUS && !layerSurface->current.interactivity) {
// moveMouseUnified won't focus non interactive layers but it won't unfocus them either, // moveMouseUnified won't focus non interactive layers but it won't unfocus them either,
// so unfocus the surface here. // so unfocus the surface here.
g_pCompositor->focusSurface(nullptr); g_pCompositor->focusSurface(nullptr);
g_pInputManager->refocusLastWindow(monitor.lock()); g_pInputManager->refocusLastWindow(g_pCompositor->getMonitorFromID(monitorID));
} else if (WASLASTFOCUS && WASEXCLUSIVE && layerSurface->current.interactivity == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND) {
g_pInputManager->simulateMouseMovement();
} else if (!WASEXCLUSIVE && ISEXCLUSIVE) { } else if (!WASEXCLUSIVE && ISEXCLUSIVE) {
// if now exclusive and not previously // if now exclusive and not previously
g_pSeatManager->setGrab(nullptr); g_pSeatManager->setGrab(nullptr);
@@ -382,74 +366,50 @@ void CLayerSurface::applyRules() {
xray = -1; xray = -1;
animationStyle.reset(); animationStyle.reset();
for (auto const& rule : g_pConfigManager->getMatchingRules(self.lock())) { for (auto& rule : g_pConfigManager->getMatchingRules(self.lock())) {
switch (rule->ruleType) { if (rule.rule == "noanim")
case CLayerRule::RULE_NOANIM: {
noAnimations = true; noAnimations = true;
break; else if (rule.rule == "blur")
}
case CLayerRule::RULE_BLUR: {
forceBlur = true; forceBlur = true;
break; else if (rule.rule == "blurpopups")
}
case CLayerRule::RULE_BLURPOPUPS: {
forceBlurPopups = true; forceBlurPopups = true;
break; else if (rule.rule.starts_with("ignorealpha") || rule.rule.starts_with("ignorezero")) {
} const auto FIRST_SPACE_POS = rule.rule.find_first_of(' ');
case CLayerRule::RULE_IGNOREALPHA:
case CLayerRule::RULE_IGNOREZERO: {
const auto FIRST_SPACE_POS = rule->rule.find_first_of(' ');
std::string alphaValue = ""; std::string alphaValue = "";
if (FIRST_SPACE_POS != std::string::npos) if (FIRST_SPACE_POS != std::string::npos)
alphaValue = rule->rule.substr(FIRST_SPACE_POS + 1); alphaValue = rule.rule.substr(FIRST_SPACE_POS + 1);
try { try {
ignoreAlpha = true; ignoreAlpha = true;
if (!alphaValue.empty()) if (!alphaValue.empty())
ignoreAlphaValue = std::stof(alphaValue); ignoreAlphaValue = std::stof(alphaValue);
} catch (...) { Debug::log(ERR, "Invalid value passed to ignoreAlpha"); } } catch (...) { Debug::log(ERR, "Invalid value passed to ignoreAlpha"); }
break; } else if (rule.rule == "dimaround") {
}
case CLayerRule::RULE_DIMAROUND: {
dimAround = true; dimAround = true;
break; } else if (rule.rule.starts_with("xray")) {
} CVarList vars{rule.rule, 0, ' '};
case CLayerRule::RULE_XRAY: {
CVarList vars{rule->rule, 0, ' '};
try { try {
xray = configStringToInt(vars[1]).value_or(false); xray = configStringToInt(vars[1]);
} catch (...) {} } catch (...) {}
break; } else if (rule.rule.starts_with("animation")) {
} CVarList vars{rule.rule, 2, 's'};
case CLayerRule::RULE_ANIMATION: {
CVarList vars{rule->rule, 2, 's'};
animationStyle = vars[1]; animationStyle = vars[1];
break;
}
case CLayerRule::RULE_ORDER: {
CVarList vars{rule->rule, 2, 's'};
try {
order = std::stoi(vars[1]);
} catch (...) { Debug::log(ERR, "Invalid value passed to order"); }
break;
}
default: break;
} }
} }
} }
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 +450,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 +477,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 +500,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 +529,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,10 +537,6 @@ 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;
} }
MONITORID CLayerSurface::monitorID() {
return monitor ? monitor->ID : MONITOR_INVALID;
}

View File

@@ -5,6 +5,11 @@
#include "WLSurface.hpp" #include "WLSurface.hpp"
#include "../helpers/AnimatedVariable.hpp" #include "../helpers/AnimatedVariable.hpp"
struct SLayerRule {
std::string targetNamespace = "";
std::string rule = "";
};
class CLayerShellResource; class CLayerShellResource;
class CLayerSurface { class CLayerSurface {
@@ -22,9 +27,9 @@ class CLayerSurface {
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;
@@ -37,7 +42,7 @@ class CLayerSurface {
bool mapped = false; bool mapped = false;
uint32_t layer = 0; uint32_t layer = 0;
PHLMONITORREF monitor; MONITORID monitorID = -1;
bool fadingOut = false; bool fadingOut = false;
bool readyToDelete = false; bool readyToDelete = false;
@@ -50,7 +55,6 @@ class CLayerSurface {
bool ignoreAlpha = false; bool ignoreAlpha = false;
float ignoreAlphaValue = 0.f; float ignoreAlphaValue = 0.f;
bool dimAround = false; bool dimAround = false;
int64_t order = 0;
std::optional<std::string> animationStyle; std::optional<std::string> animationStyle;
@@ -59,13 +63,12 @@ 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();
void onUnmap(); void onUnmap();
void onCommit(); void onCommit();
MONITORID monitorID();
private: private:
struct { struct {
@@ -79,6 +82,6 @@ class CLayerSurface {
// For the list lookup // For the list lookup
bool operator==(const CLayerSurface& rhs) const { bool operator==(const CLayerSurface& rhs) const {
return layerSurface == rhs.layerSurface && monitor == rhs.monitor; return layerSurface == rhs.layerSurface && monitorID == rhs.monitorID;
} }
}; };

View File

@@ -4,45 +4,27 @@
#include "../protocols/LayerShell.hpp" #include "../protocols/LayerShell.hpp"
#include "../protocols/XDGShell.hpp" #include "../protocols/XDGShell.hpp"
#include "../protocols/core/Compositor.hpp" #include "../protocols/core/Compositor.hpp"
#include "../managers/SeatManager.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>
UP<CPopup> CPopup::create(PHLWINDOW pOwner) { CPopup::CPopup(PHLWINDOW pOwner) : m_pWindowOwner(pOwner) {
auto popup = UP<CPopup>(new CPopup()); initAllSignals();
popup->m_pWindowOwner = pOwner;
popup->m_pSelf = popup;
popup->initAllSignals();
return popup;
} }
UP<CPopup> CPopup::create(PHLLS pOwner) { CPopup::CPopup(PHLLS pOwner) : m_pLayerOwner(pOwner) {
auto popup = UP<CPopup>(new CPopup()); initAllSignals();
popup->m_pLayerOwner = pOwner;
popup->m_pSelf = popup;
popup->initAllSignals();
return popup;
} }
UP<CPopup> CPopup::create(SP<CXDGPopupResource> resource, WP<CPopup> pOwner) { CPopup::CPopup(SP<CXDGPopupResource> popup, CPopup* pOwner) : m_pParent(pOwner), m_pResource(popup) {
auto popup = UP<CPopup>(new CPopup()); m_pWLSurface = CWLSurface::create();
popup->m_pResource = resource; m_pWLSurface->assign(popup->surface->surface.lock(), this);
popup->m_pWindowOwner = pOwner->m_pWindowOwner;
popup->m_pLayerOwner = pOwner->m_pLayerOwner;
popup->m_pParent = pOwner;
popup->m_pSelf = popup;
popup->m_pWLSurface = CWLSurface::create();
popup->m_pWLSurface->assign(resource->surface->surface.lock(), popup.get());
popup->m_vLastSize = resource->surface->current.geometry.size(); m_pLayerOwner = pOwner->m_pLayerOwner;
popup->reposition(); m_pWindowOwner = pOwner->m_pWindowOwner;
popup->initAllSignals(); m_vLastSize = popup->surface->current.geometry.size();
return popup; reposition();
initAllSignals();
} }
CPopup::~CPopup() { CPopup::~CPopup() {
@@ -73,8 +55,7 @@ void CPopup::initAllSignals() {
} }
void CPopup::onNewPopup(SP<CXDGPopupResource> popup) { void CPopup::onNewPopup(SP<CXDGPopupResource> popup) {
const auto& POPUP = m_vChildren.emplace_back(CPopup::create(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);
} }
@@ -99,13 +80,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 = CSubsurface::create(m_pSelf); m_pSubsurfaceHead = std::make_unique<CSubsurface>(this);
//unconstrain(); //unconstrain();
sendScale(); sendScale();
@@ -125,37 +106,31 @@ void CPopup::onUnmap() {
return; return;
} }
m_bMapped = false;
m_vLastSize = m_pResource->surface->surface->current.size; m_vLastSize = m_pResource->surface->surface->current.size;
const auto COORDS = coordsGlobal(); const auto COORDS = coordsGlobal();
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();
g_pInputManager->simulateMouseMovement();
if (!m_pLayerOwner.expired() && m_pLayerOwner->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP) if (!m_pLayerOwner.expired() && m_pLayerOwner->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner->layer)); g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner->layer));
// 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();
// if (WASLASTFOCUS)
// g_pInputManager->simulateMouseMovement();
} }
void CPopup::onCommit(bool ignoreSiblings) { void CPopup::onCommit(bool ignoreSiblings) {
@@ -187,10 +162,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,20 +202,13 @@ void CPopup::reposition() {
m_pResource->applyPositioning(box, COORDS); m_pResource->applyPositioning(box, COORDS);
} }
SP<CWLSurface> CPopup::getT1Owner() {
if (m_pWindowOwner)
return m_pWindowOwner->m_pWLSurface;
else
return m_pLayerOwner->surface;
}
Vector2D CPopup::coordsRelativeToParent() { Vector2D CPopup::coordsRelativeToParent() {
Vector2D offset; Vector2D offset;
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) {
@@ -264,16 +232,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;
} }
@@ -282,9 +250,8 @@ void CPopup::recheckTree() {
} }
void CPopup::recheckChildrenRecursive() { void CPopup::recheckChildrenRecursive() {
std::vector<WP<CPopup>> cpy; auto cpy = m_vChildren;
std::ranges::for_each(m_vChildren, [&cpy](const auto& el) { cpy.emplace_back(el); }); for (auto& c : cpy) {
for (auto const& c : cpy) {
c->onCommit(true); c->onCommit(true);
c->recheckChildrenRecursive(); c->recheckChildrenRecursive();
} }
@@ -314,17 +281,16 @@ 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*> nodes, std::function<void(CPopup*, void*)> fn, void* data) {
for (auto const& n : nodes) { for (auto& n : nodes) {
fn(n, data); fn(n, data);
} }
std::vector<WP<CPopup>> nodes2; std::vector<CPopup*> nodes2;
nodes2.reserve(nodes.size() * 2);
for (auto const& n : nodes) { for (auto& n : nodes) {
for (auto const& c : n->m_vChildren) { for (auto& c : n->m_vChildren) {
nodes2.push_back(c->m_pSelf); nodes2.push_back(c.get());
} }
} }
@@ -332,31 +298,29 @@ 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([&popups](WP<CPopup> popup, void* data) { popups.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& p : popups | std::views::reverse) {
if (!p->m_pResource || !p->m_bMapped) if (!p->m_pResource)
continue; continue;
if (!allowsInput) { if (!allowsInput) {
const Vector2D offset = const Vector2D offset = p->m_pResource ? (p->size() - p->m_pResource->geometry.size()) / 2.F : Vector2D{};
p->m_pResource && p->m_pResource->surface ? (p->size() - p->m_pResource->geometry.size()) / 2.F - p->m_pResource->surface->current.geometry.pos() : Vector2D{};
const Vector2D size = p->m_pResource ? p->m_pResource->geometry.size() : p->size(); const Vector2D size = p->m_pResource ? p->m_pResource->geometry.size() : p->size();
const auto BOX = CBox{p->coordsGlobal() + offset, size}; const auto BOX = CBox{p->coordsGlobal() + offset, size};
if (BOX.containsPoint(globalCoords)) if (BOX.containsPoint(globalCoords))
return p; return p;
} else { } else {
const Vector2D offset = const Vector2D offset = p->m_pResource ? (p->size() - p->m_pResource->geometry.size()) / 2.F : Vector2D{};
p->m_pResource && p->m_pResource->surface ? (p->size() - p->m_pResource->geometry.size()) / 2.F - p->m_pResource->surface->current.geometry.pos() : Vector2D{};
const auto REGION = const auto REGION =
CRegion{p->m_pWLSurface->resource()->current.input}.intersect(CBox{{}, p->m_pWLSurface->resource()->current.size}).translate(p->coordsGlobal() + offset); CRegion{p->m_pWLSurface->resource()->current.input}.intersect(CBox{{}, p->m_pWLSurface->resource()->current.size}).translate(p->coordsGlobal() + offset);
if (REGION.containsPoint(globalCoords)) if (REGION.containsPoint(globalCoords))
@@ -364,5 +328,5 @@ WP<CPopup> CPopup::at(const Vector2D& globalCoords, bool allowsInput) {
} }
} }
return {}; return nullptr;
} }

View File

@@ -1,24 +1,23 @@
#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;
class CPopup { class CPopup {
public: public:
// dummy head nodes // dummy head nodes
static UP<CPopup> create(PHLWINDOW pOwner); CPopup(PHLWINDOW pOwner);
static UP<CPopup> create(PHLLS pOwner); CPopup(PHLLS pOwner);
// real nodes // real nodes
static UP<CPopup> create(SP<CXDGPopupResource> popup, WP<CPopup> pOwner); CPopup(SP<CXDGPopupResource> popup, CPopup* pOwner);
~CPopup(); ~CPopup();
SP<CWLSurface> getT1Owner();
Vector2D coordsRelativeToParent(); Vector2D coordsRelativeToParent();
Vector2D coordsGlobal(); Vector2D coordsGlobal();
@@ -36,23 +35,19 @@ 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;
private: private:
CPopup() = default;
// T1 owners, each popup has to have one of these // T1 owners, each popup has to have one of these
PHLWINDOWREF m_pWindowOwner; PHLWINDOWREF m_pWindowOwner;
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,10 +57,11 @@ class CPopup {
bool m_bRequestedReposition = false; bool m_bRequestedReposition = false;
bool m_bInert = false; bool m_bInert = false;
bool m_bMapped = false;
// //
std::vector<UP<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;
@@ -84,5 +80,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*> 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,54 +4,39 @@
#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"
UP<CSubsurface> CSubsurface::create(PHLWINDOW pOwner) { CSubsurface::CSubsurface(PHLWINDOW pOwner) : m_pWindowParent(pOwner) {
auto subsurface = UP<CSubsurface>(new CSubsurface()); initSignals();
subsurface->m_pWindowParent = pOwner; initExistingSubsurfaces(pOwner->m_pWLSurface->resource());
subsurface->m_pSelf = subsurface;
subsurface->initSignals();
subsurface->initExistingSubsurfaces(pOwner->m_pWLSurface->resource());
return subsurface;
} }
UP<CSubsurface> CSubsurface::create(WP<CPopup> pOwner) { CSubsurface::CSubsurface(CPopup* pOwner) : m_pPopupParent(pOwner) {
auto subsurface = UP<CSubsurface>(new CSubsurface()); initSignals();
subsurface->m_pPopupParent = pOwner; initExistingSubsurfaces(pOwner->m_pWLSurface->resource());
subsurface->m_pSelf = subsurface;
subsurface->initSignals();
subsurface->initExistingSubsurfaces(pOwner->m_pWLSurface->resource());
return subsurface;
} }
UP<CSubsurface> CSubsurface::create(SP<CWLSubsurfaceResource> pSubsurface, PHLWINDOW pOwner) { CSubsurface::CSubsurface(SP<CWLSubsurfaceResource> pSubsurface, PHLWINDOW pOwner) : m_pSubsurface(pSubsurface), m_pWindowParent(pOwner) {
auto subsurface = UP<CSubsurface>(new CSubsurface()); m_pWLSurface = CWLSurface::create();
subsurface->m_pWindowParent = pOwner; m_pWLSurface->assign(pSubsurface->surface.lock(), this);
subsurface->m_pSubsurface = pSubsurface; initSignals();
subsurface->m_pSelf = subsurface; initExistingSubsurfaces(pSubsurface->surface.lock());
subsurface->m_pWLSurface = CWLSurface::create();
subsurface->m_pWLSurface->assign(pSubsurface->surface.lock(), subsurface.get());
subsurface->initSignals();
subsurface->initExistingSubsurfaces(pSubsurface->surface.lock());
return subsurface;
} }
UP<CSubsurface> CSubsurface::create(SP<CWLSubsurfaceResource> pSubsurface, WP<CPopup> pOwner) { CSubsurface::CSubsurface(SP<CWLSubsurfaceResource> pSubsurface, CPopup* pOwner) : m_pSubsurface(pSubsurface), m_pPopupParent(pOwner) {
auto subsurface = UP<CSubsurface>(new CSubsurface()); m_pWLSurface = CWLSurface::create();
subsurface->m_pPopupParent = pOwner; m_pWLSurface->assign(pSubsurface->surface.lock(), this);
subsurface->m_pSubsurface = pSubsurface; initSignals();
subsurface->m_pSelf = subsurface; initExistingSubsurfaces(pSubsurface->surface.lock());
subsurface->m_pWLSurface = CWLSurface::create();
subsurface->m_pWLSurface->assign(pSubsurface->surface.lock(), subsurface.get());
subsurface->initSignals();
subsurface->initExistingSubsurfaces(pSubsurface->surface.lock());
return subsurface;
} }
CSubsurface::~CSubsurface() { CSubsurface::~CSubsurface() {
; hyprListener_newSubsurface.removeCallback();
if (!m_pSubsurface)
return;
hyprListener_commitSubsurface.removeCallback();
hyprListener_destroySubsurface.removeCallback();
} }
void CSubsurface::initSignals() { void CSubsurface::initSignals() {
@@ -80,7 +65,7 @@ void CSubsurface::checkSiblingDamage() {
const double SCALE = m_pWindowParent.lock() && m_pWindowParent->m_bIsX11 ? 1.0 / m_pWindowParent->m_fX11SurfaceScaledBy : 1.0; const double SCALE = m_pWindowParent.lock() && m_pWindowParent->m_bIsX11 ? 1.0 / m_pWindowParent->m_fX11SurfaceScaledBy : 1.0;
for (auto const& n : m_pParent->m_vChildren) { for (auto& n : m_pParent->m_vChildren) {
if (n.get() == this) if (n.get() == this)
continue; continue;
@@ -90,7 +75,7 @@ void CSubsurface::checkSiblingDamage() {
} }
void CSubsurface::recheckDamageForSubsurfaces() { void CSubsurface::recheckDamageForSubsurfaces() {
for (auto const& n : m_vChildren) { for (auto& n : m_vChildren) {
const auto COORDS = n->coordsGlobal(); const auto COORDS = n->coordsGlobal();
g_pHyprRenderer->damageSurface(n->m_pWLSurface->resource(), COORDS.x, COORDS.y); g_pHyprRenderer->damageSurface(n->m_pWLSurface->resource(), COORDS.x, COORDS.y);
} }
@@ -120,20 +105,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);
} }
} }
@@ -151,18 +127,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(CSubsurface::create(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(CSubsurface::create(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() {
@@ -171,7 +145,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();
@@ -181,7 +155,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();
@@ -201,7 +175,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();
@@ -209,7 +183,7 @@ Vector2D CSubsurface::coordsGlobal() {
} }
void CSubsurface::initExistingSubsurfaces(SP<CWLSurfaceResource> pSurface) { void CSubsurface::initExistingSubsurfaces(SP<CWLSurfaceResource> pSurface) {
for (auto const& s : pSurface->subsurfaces) { for (auto& s : pSurface->subsurfaces) {
if (!s || s->surface->hlSurface /* already assigned */) if (!s || s->surface->hlSurface /* already assigned */)
continue; continue;
onNewSubsurface(s.lock()); onNewSubsurface(s.lock());

View File

@@ -10,12 +10,12 @@ class CWLSubsurfaceResource;
class CSubsurface { class CSubsurface {
public: public:
// root dummy nodes // root dummy nodes
static UP<CSubsurface> create(PHLWINDOW pOwner); CSubsurface(PHLWINDOW pOwner);
static UP<CSubsurface> create(WP<CPopup> pOwner); CSubsurface(CPopup* pOwner);
// real nodes // real nodes
static UP<CSubsurface> create(SP<CWLSubsurfaceResource> pSubsurface, PHLWINDOW pOwner); CSubsurface(SP<CWLSubsurfaceResource> pSubsurface, PHLWINDOW pOwner);
static UP<CSubsurface> create(SP<CWLSubsurfaceResource> pSubsurface, WP<CPopup> pOwner); CSubsurface(SP<CWLSubsurfaceResource> pSubsurface, CPopup* pOwner);
~CSubsurface(); ~CSubsurface();
@@ -34,10 +34,10 @@ class CSubsurface {
void recheckDamageForSubsurfaces(); void recheckDamageForSubsurfaces();
WP<CSubsurface> m_pSelf;
private: private:
CSubsurface() = default; DYNLISTENER(destroySubsurface);
DYNLISTENER(commitSubsurface);
DYNLISTENER(newSubsurface);
struct { struct {
CHyprSignalListener destroySubsurface; CHyprSignalListener destroySubsurface;
@@ -52,12 +52,12 @@ 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;

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;
@@ -64,7 +62,7 @@ bool CWLSurface::small() const {
const auto O = m_pWindowOwner.lock(); const auto O = m_pWindowOwner.lock();
return O->m_vReportedSize.x > m_pResource->current.size.x + 1 || O->m_vReportedSize.y > m_pResource->current.size.y + 1; return O->m_vReportedSize.x > m_pResource->current.bufferSize.x + 1 || O->m_vReportedSize.y > m_pResource->current.bufferSize.y + 1;
} }
Vector2D CWLSurface::correctSmallVec() const { Vector2D CWLSurface::correctSmallVec() const {
@@ -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;
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,10 @@
#pragma once #pragma once
#include <vector> #include <deque>
#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,25 +12,23 @@
#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"
#include "WLSurface.hpp" #include "WLSurface.hpp"
#include "Workspace.hpp" #include "Workspace.hpp"
#include "WindowRule.hpp"
class CXDGSurfaceResource; class CXDGSurfaceResource;
class CXWaylandSurface; class CXWaylandSurface;
enum eIdleInhibitMode : uint8_t { enum eIdleInhibitMode {
IDLEINHIBIT_NONE = 0, IDLEINHIBIT_NONE = 0,
IDLEINHIBIT_ALWAYS, IDLEINHIBIT_ALWAYS,
IDLEINHIBIT_FULLSCREEN, IDLEINHIBIT_FULLSCREEN,
IDLEINHIBIT_FOCUS IDLEINHIBIT_FOCUS
}; };
enum eGroupRules : uint8_t { enum eGroupRules {
// effective only during first map, except for _ALWAYS variant // effective only during first map, except for _ALWAYS variant
GROUP_NONE = 0, GROUP_NONE = 0,
GROUP_SET = 1 << 0, // Open as new group or add to focused group GROUP_SET = 1 << 0, // Open as new group or add to focused group
@@ -42,7 +40,7 @@ enum eGroupRules : uint8_t {
GROUP_OVERRIDE = 1 << 6, // Override other rules GROUP_OVERRIDE = 1 << 6, // Override other rules
}; };
enum eGetWindowProperties : uint8_t { enum eGetWindowProperties {
WINDOW_ONLY = 0, WINDOW_ONLY = 0,
RESERVED_EXTENTS = 1 << 0, RESERVED_EXTENTS = 1 << 0,
INPUT_EXTENTS = 1 << 1, INPUT_EXTENTS = 1 << 1,
@@ -52,13 +50,12 @@ enum eGetWindowProperties : uint8_t {
USE_PROP_TILED = 1 << 5, USE_PROP_TILED = 1 << 5,
}; };
enum eSuppressEvents : uint8_t { enum eSuppressEvents {
SUPPRESS_NONE = 0, SUPPRESS_NONE = 0,
SUPPRESS_FULLSCREEN = 1 << 0, SUPPRESS_FULLSCREEN = 1 << 0,
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;
@@ -67,7 +64,7 @@ struct SAlphaValue {
float m_fAlpha; float m_fAlpha;
bool m_bOverride; bool m_bOverride;
float applyAlpha(float alpha) const { float applyAlpha(float alpha) {
if (m_bOverride) if (m_bOverride)
return m_fAlpha; return m_fAlpha;
else else
@@ -75,8 +72,8 @@ struct SAlphaValue {
}; };
}; };
enum eOverridePriority : uint8_t { enum eOverridePriority {
PRIORITY_LAYOUT = 0, PRIORITY_LAYOUT,
PRIORITY_WORKSPACE_RULE, PRIORITY_WORKSPACE_RULE,
PRIORITY_WINDOW_RULE, PRIORITY_WINDOW_RULE,
PRIORITY_SET_PROP, PRIORITY_SET_PROP,
@@ -88,7 +85,9 @@ class CWindowOverridableVar {
CWindowOverridableVar(T const& value, eOverridePriority priority) { CWindowOverridableVar(T const& value, eOverridePriority priority) {
values[priority] = value; values[priority] = value;
} }
CWindowOverridableVar(T const& value) : defaultValue{value} {} CWindowOverridableVar(T const& value) {
defaultValue = value;
}
CWindowOverridableVar() = default; CWindowOverridableVar() = default;
~CWindowOverridableVar() = default; ~CWindowOverridableVar() = default;
@@ -145,13 +144,6 @@ class CWindowOverridableVar {
unset(priority); unset(priority);
} }
operator std::optional<T>() {
if (hasValue())
return value();
else
return std::nullopt;
}
private: private:
std::map<eOverridePriority, T> values; std::map<eOverridePriority, T> values;
T defaultValue; // used for toggling, so required for bool T defaultValue; // used for toggling, so required for bool
@@ -182,15 +174,10 @@ struct SWindowData {
CWindowOverridableVar<bool> syncFullscreen = true; CWindowOverridableVar<bool> syncFullscreen = true;
CWindowOverridableVar<bool> tearing = false; CWindowOverridableVar<bool> tearing = false;
CWindowOverridableVar<bool> xray = false; CWindowOverridableVar<bool> xray = 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> scrollTouchpad;
CWindowOverridableVar<std::string> animationStyle; CWindowOverridableVar<std::string> animationStyle;
CWindowOverridableVar<Vector2D> maxSize; CWindowOverridableVar<Vector2D> maxSize;
CWindowOverridableVar<Vector2D> minSize; CWindowOverridableVar<Vector2D> minSize;
@@ -199,12 +186,32 @@ struct SWindowData {
CWindowOverridableVar<CGradientValueData> inactiveBorderColor; CWindowOverridableVar<CGradientValueData> inactiveBorderColor;
}; };
struct SWindowRule {
std::string szRule;
std::string szValue;
bool v2 = false;
std::string szTitle;
std::string szClass;
std::string szInitialTitle;
std::string szInitialClass;
std::string szTag;
int bX11 = -1; // -1 means "ANY"
int bFloating = -1;
int bFullscreen = -1;
int bPinned = -1;
int bFocus = -1;
std::string szFullscreenState = ""; // empty means any
std::string szOnWorkspace = ""; // empty means any
std::string szWorkspace = ""; // empty means any
};
struct SInitialWorkspaceToken { struct SInitialWorkspaceToken {
PHLWINDOWREF primaryOwner; PHLWINDOWREF primaryOwner;
std::string workspace; std::string workspace;
}; };
struct SFullscreenState { struct sFullscreenState {
eFullscreenMode internal = FSMODE_NONE; eFullscreenMode internal = FSMODE_NONE;
eFullscreenMode client = FSMODE_NONE; eFullscreenMode client = FSMODE_NONE;
}; };
@@ -235,8 +242,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;
@@ -263,13 +270,13 @@ class CWindow {
bool m_bIsFloating = false; bool m_bIsFloating = false;
bool m_bDraggingTiled = false; // for dragging around tiled windows bool m_bDraggingTiled = false; // for dragging around tiled windows
bool m_bWasMaximized = false; bool m_bWasMaximized = false;
SFullscreenState m_sFullscreenState = {.internal = FSMODE_NONE, .client = FSMODE_NONE}; sFullscreenState m_sFullscreenState = {.internal = FSMODE_NONE, .client = FSMODE_NONE};
MONITORID m_iMonitorID = -1;
std::string m_szTitle = ""; std::string m_szTitle = "";
std::string m_szClass = ""; std::string m_szClass = "";
std::string m_szInitialTitle = ""; std::string m_szInitialTitle = "";
std::string m_szInitialClass = ""; std::string m_szInitialClass = "";
PHLWORKSPACE m_pWorkspace; PHLWORKSPACE m_pWorkspace;
PHLMONITORREF m_pMonitor;
bool m_bIsMapped = false; bool m_bIsMapped = false;
@@ -281,6 +288,8 @@ class CWindow {
// XWayland stuff // XWayland stuff
bool m_bIsX11 = false; bool m_bIsX11 = false;
PHLWINDOWREF m_pX11Parent; PHLWINDOWREF m_pX11Parent;
uint64_t m_iX11Type = 0;
bool m_bIsModal = false;
bool m_bX11DoesntWantBorders = false; bool m_bX11DoesntWantBorders = false;
bool m_bX11ShouldntFocus = false; bool m_bX11ShouldntFocus = false;
float m_fX11SurfaceScaledBy = 1.f; float m_fX11SurfaceScaledBy = 1.f;
@@ -291,23 +300,22 @@ class CWindow {
// 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
@@ -318,9 +326,6 @@ class CWindow {
// For pinned (sticky) windows // For pinned (sticky) windows
bool m_bPinned = false; bool m_bPinned = false;
// For preserving pinned state when fullscreening a pinned window
bool m_bPinFullscreened = false;
// urgency hint // urgency hint
bool m_bIsUrgent = false; bool m_bIsUrgent = false;
@@ -329,32 +334,26 @@ class CWindow {
// Window decorations // Window decorations
// TODO: make this a SP. // TODO: make this a SP.
std::vector<UP<IHyprWindowDecoration>> m_dWindowDecorations; std::deque<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<CColor> m_cRealShadowColor;
// animated tint // animated tint
PHLANIMVAR<float> m_fDimPercent; CAnimatedVariable<float> m_fDimPercent;
// animate moving to an invisible workspace
int m_iMonitorMovedFrom = -1; // -1 means not moving
PHLANIMVAR<float> m_fMovingToWorkspaceAlpha;
// swallowing // swallowing
PHLWINDOWREF m_pSwallowed; PHLWINDOWREF m_pSwallowed;
bool m_bGroupSwallowed = false;
// focus stuff // focus stuff
bool m_bStayFocused = false; bool m_bStayFocused = false;
@@ -381,13 +380,13 @@ class CWindow {
bool m_bTearingHint = false; bool m_bTearingHint = false;
// stores the currently matched window rules // stores the currently matched window rules
std::vector<SP<CWindowRule>> m_vMatchedRules; std::vector<SWindowRule> m_vMatchedRules;
// window tags // window tags
CTagKeeper m_tags; CTagKeeper m_tags;
// For the list lookup // For the list lookup
bool operator==(const CWindow& rhs) const { bool operator==(const CWindow& rhs) {
return m_pXDGSurface == rhs.m_pXDGSurface && m_pXWaylandSurface == rhs.m_pXWaylandSurface && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize && return m_pXDGSurface == rhs.m_pXDGSurface && m_pXWaylandSurface == rhs.m_pXWaylandSurface && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize &&
m_bFadingOut == rhs.m_bFadingOut; m_bFadingOut == rhs.m_bFadingOut;
} }
@@ -396,49 +395,50 @@ class CWindow {
CBox getFullWindowBoundingBox(); CBox getFullWindowBoundingBox();
SBoxExtents getFullWindowExtents(); SBoxExtents getFullWindowExtents();
CBox getWindowBoxUnified(uint64_t props); CBox getWindowBoxUnified(uint64_t props);
CBox getWindowMainSurfaceBox();
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);
PHLWINDOW x11TransientFor(); PHLWINDOW X11TransientFor();
void onUnmap(); void onUnmap();
void onMap(); void onMap();
void setHidden(bool hidden); void setHidden(bool hidden);
bool isHidden(); bool isHidden();
void applyDynamicRule(const SP<CWindowRule>& r); void applyDynamicRule(const SWindowRule& r);
void updateDynamicRules(); void updateDynamicRules();
SBoxExtents getFullWindowReservedArea(); SBoxExtents getFullWindowReservedArea();
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(CMonitor* pMonitor);
WORKSPACEID workspaceID(); WORKSPACEID workspaceID();
MONITORID monitorID();
bool onSpecialWorkspace(); bool onSpecialWorkspace();
void activate(bool force = false); void activate(bool force = false);
int surfacesCount(); int surfacesCount();
void clampWindowSize(const std::optional<Vector2D> minSize, const std::optional<Vector2D> maxSize);
bool isFullscreen(); bool isFullscreen();
bool isEffectiveInternalFSMode(const eFullscreenMode); bool isEffectiveInternalFSMode(const eFullscreenMode);
int getRealBorderSize(); int getRealBorderSize();
float getScrollMouse();
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();
void applyGroupRules(); void applyGroupRules();
void createGroup(); void createGroup();
void destroyGroup(); void destroyGroup();
@@ -455,25 +455,15 @@ 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);
void onResourceChangeX11(); void onResourceChangeX11();
std::string fetchTitle(); std::string fetchTitle();
std::string fetchClass(); std::string fetchClass();
void warpCursor(bool force = false); void warpCursor();
PHLWINDOW getSwallower(); PHLWINDOW getSwallower();
void unsetWindowData(eOverridePriority priority); void unsetWindowData(eOverridePriority priority);
bool isX11OverrideRedirect();
bool isModal();
Vector2D requestedMinSize();
Vector2D requestedMaxSize();
void sendWindowSize(Vector2D size, bool force = false, std::optional<Vector2D> overridePos = std::nullopt);
CBox getWindowMainSurfaceBox() const {
return {m_vRealPosition->value().x, m_vRealPosition->value().y, m_vRealSize->value().x, m_vRealSize->value().y};
}
// listeners // listeners
void onAck(uint32_t serial); void onAck(uint32_t serial);
@@ -560,7 +550,7 @@ struct std::formatter<PHLWINDOW, CharT> : std::formatter<CharT> {
if (formatWorkspace) if (formatWorkspace)
std::format_to(out, ", workspace: {}", w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID); std::format_to(out, ", workspace: {}", w->m_pWorkspace ? w->workspaceID() : WORKSPACE_INVALID);
if (formatMonitor) if (formatMonitor)
std::format_to(out, ", monitor: {}", w->monitorID()); std::format_to(out, ", monitor: {}", w->m_iMonitorID);
if (formatClass) if (formatClass)
std::format_to(out, ", class: {}", w->m_szClass); std::format_to(out, ", class: {}", w->m_szClass);
return std::format_to(out, "]"); return std::format_to(out, "]");

View File

@@ -1,91 +0,0 @@
#include "WindowRule.hpp"
#include <unordered_set>
#include <algorithm>
#include <re2/re2.h>
#include "../config/ConfigManager.hpp"
static const auto RULES = std::unordered_set<std::string>{
"float", "fullscreen", "maximize", "noinitialfocus", "pin", "stayfocused", "tile", "renderunfocused",
};
static const auto RULES_PREFIX = std::unordered_set<std::string>{
"animation", "bordercolor", "bordersize", "center", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", "move", "opacity",
"plugin:", "prop", "pseudo", "rounding", "roundingpower", "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) {
const auto VALS = CVarList(rule, 2, ' ');
const bool VALID = RULES.contains(rule) || std::any_of(RULES_PREFIX.begin(), RULES_PREFIX.end(), [&rule](auto prefix) { return rule.starts_with(prefix); }) ||
(g_pConfigManager->mbWindowProperties.find(VALS[0]) != g_pConfigManager->mbWindowProperties.end()) ||
(g_pConfigManager->miWindowProperties.find(VALS[0]) != g_pConfigManager->miWindowProperties.end()) ||
(g_pConfigManager->mfWindowProperties.find(VALS[0]) != g_pConfigManager->mfWindowProperties.end());
if (!VALID)
return;
if (rule == "float")
ruleType = RULE_FLOAT;
else if (rule == "fullscreen")
ruleType = RULE_FULLSCREEN;
else if (rule == "maximize")
ruleType = RULE_MAXIMIZE;
else if (rule == "noinitialfocus")
ruleType = RULE_NOINITIALFOCUS;
else if (rule == "pin")
ruleType = RULE_PIN;
else if (rule == "stayfocused")
ruleType = RULE_STAYFOCUSED;
else if (rule == "tile")
ruleType = RULE_TILE;
else if (rule == "renderunfocused")
ruleType = RULE_RENDERUNFOCUSED;
else if (rule.starts_with("animation"))
ruleType = RULE_ANIMATION;
else if (rule.starts_with("bordercolor"))
ruleType = RULE_BORDERCOLOR;
else if (rule.starts_with("center"))
ruleType = RULE_CENTER;
else if (rule.starts_with("fullscreenstate"))
ruleType = RULE_FULLSCREENSTATE;
else if (rule.starts_with("group"))
ruleType = RULE_GROUP;
else if (rule.starts_with("idleinhibit"))
ruleType = RULE_IDLEINHIBIT;
else if (rule.starts_with("maxsize"))
ruleType = RULE_MAXSIZE;
else if (rule.starts_with("minsize"))
ruleType = RULE_MINSIZE;
else if (rule.starts_with("monitor"))
ruleType = RULE_MONITOR;
else if (rule.starts_with("move"))
ruleType = RULE_MOVE;
else if (rule.starts_with("opacity"))
ruleType = RULE_OPACITY;
else if (rule.starts_with("plugin:"))
ruleType = RULE_PLUGIN;
else if (rule.starts_with("pseudo"))
ruleType = RULE_PSEUDO;
else if (rule.starts_with("size"))
ruleType = RULE_SIZE;
else if (rule.starts_with("suppressevent"))
ruleType = RULE_SUPPRESSEVENT;
else if (rule.starts_with("tag"))
ruleType = RULE_TAG;
else if (rule.starts_with("workspace"))
ruleType = RULE_WORKSPACE;
else if (rule.starts_with("prop"))
ruleType = RULE_PROP;
else {
// check if this is a prop.
const CVarList VARS(rule, 0, 's', true);
if (g_pConfigManager->miWindowProperties.find(VARS[0]) != g_pConfigManager->miWindowProperties.end() ||
g_pConfigManager->mbWindowProperties.find(VARS[0]) != g_pConfigManager->mbWindowProperties.end() ||
g_pConfigManager->mfWindowProperties.find(VARS[0]) != g_pConfigManager->mfWindowProperties.end()) {
*const_cast<std::string*>(&szRule) = "prop " + rule;
ruleType = RULE_PROP;
Debug::log(LOG, "CWindowRule: direct prop rule found, rewritten {} -> {}", rule, szRule);
} else {
Debug::log(ERR, "CWindowRule: didn't match a rule that was found valid?!");
ruleType = RULE_INVALID;
}
}
}

View File

@@ -1,68 +0,0 @@
#pragma once
#include <string>
#include <cstdint>
#include "Rule.hpp"
class CWindowRule {
public:
CWindowRule(const std::string& rule, const std::string& value, bool isV2 = false, bool isExecRule = false);
enum eRuleType : uint8_t {
RULE_INVALID = 0,
RULE_FLOAT,
RULE_FULLSCREEN,
RULE_MAXIMIZE,
RULE_NOINITIALFOCUS,
RULE_PIN,
RULE_STAYFOCUSED,
RULE_TILE,
RULE_RENDERUNFOCUSED,
RULE_ANIMATION,
RULE_BORDERCOLOR,
RULE_CENTER,
RULE_FULLSCREENSTATE,
RULE_GROUP,
RULE_IDLEINHIBIT,
RULE_MAXSIZE,
RULE_MINSIZE,
RULE_MONITOR,
RULE_MOVE,
RULE_OPACITY,
RULE_PLUGIN,
RULE_PSEUDO,
RULE_SIZE,
RULE_SUPPRESSEVENT,
RULE_TAG,
RULE_WORKSPACE,
RULE_PROP,
};
eRuleType ruleType = RULE_INVALID;
const std::string szValue;
const std::string szRule;
const bool v2 = false;
const bool execRule = false;
std::string szTitle;
std::string szClass;
std::string szInitialTitle;
std::string szInitialClass;
std::string szTag;
int bX11 = -1; // -1 means "ANY"
int bFloating = -1;
int bFullscreen = -1;
int bPinned = -1;
int bFocus = -1;
std::string szFullscreenState = ""; // empty means any
std::string szOnWorkspace = ""; // empty means any
std::string szWorkspace = ""; // empty means any
// precompiled regexes
CRuleRegexContainer rTitle;
CRuleRegexContainer rClass;
CRuleRegexContainer rInitialTitle;
CRuleRegexContainer rInitialClass;
CRuleRegexContainer rV1Regex;
};

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