mirror of
https://github.com/hyprwm/Hyprland
synced 2025-12-20 11:10:04 +01:00
Merge branch 'hyprwm:main' into gowno
This commit is contained in:
commit
b37f8ee903
129 changed files with 5106 additions and 3224 deletions
1
.github/actions/setup_base/action.yml
vendored
1
.github/actions/setup_base/action.yml
vendored
|
|
@ -45,6 +45,7 @@ runs:
|
||||||
libxkbfile \
|
libxkbfile \
|
||||||
lld \
|
lld \
|
||||||
meson \
|
meson \
|
||||||
|
muparser \
|
||||||
ninja \
|
ninja \
|
||||||
pango \
|
pango \
|
||||||
pixman \
|
pixman \
|
||||||
|
|
|
||||||
82
.github/workflows/ci.yaml
vendored
82
.github/workflows/ci.yaml
vendored
|
|
@ -21,7 +21,7 @@ jobs:
|
||||||
|
|
||||||
- name: Build Hyprland
|
- name: Build Hyprland
|
||||||
run: |
|
run: |
|
||||||
CFLAGS=-Werror CXXFLAGS=-Werror make all
|
CFLAGS=-Werror CXXFLAGS=-Werror make nopch
|
||||||
|
|
||||||
- name: Compress and package artifacts
|
- name: Compress and package artifacts
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -41,86 +41,16 @@ jobs:
|
||||||
name: Build archive
|
name: Build archive
|
||||||
path: Hyprland.tar.xz
|
path: Hyprland.tar.xz
|
||||||
|
|
||||||
meson:
|
|
||||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
|
||||||
name: "Build Hyprland with Meson (Arch)"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container:
|
|
||||||
image: archlinux
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository actions
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
sparse-checkout: .github/actions
|
|
||||||
|
|
||||||
- name: Setup base
|
|
||||||
uses: ./.github/actions/setup_base
|
|
||||||
|
|
||||||
- name: Configure
|
|
||||||
run: meson setup build -Ddefault_library=static
|
|
||||||
|
|
||||||
- name: Compile
|
|
||||||
run: ninja -C build
|
|
||||||
|
|
||||||
no-pch:
|
|
||||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
|
||||||
name: "Build Hyprland without precompiled headers (Arch)"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container:
|
|
||||||
image: archlinux
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository actions
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
sparse-checkout: .github/actions
|
|
||||||
|
|
||||||
- name: Setup base
|
|
||||||
uses: ./.github/actions/setup_base
|
|
||||||
with:
|
|
||||||
INSTALL_XORG_PKGS: true
|
|
||||||
|
|
||||||
- name: Compile
|
|
||||||
run: make nopch
|
|
||||||
|
|
||||||
noxwayland:
|
|
||||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork
|
|
||||||
name: "Build Hyprland in pure Wayland (Arch)"
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container:
|
|
||||||
image: archlinux
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository actions
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
sparse-checkout: .github/actions
|
|
||||||
|
|
||||||
- name: Setup base
|
|
||||||
uses: ./.github/actions/setup_base
|
|
||||||
|
|
||||||
- name: Configure
|
|
||||||
run: mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DNO_XWAYLAND:STRING=true -H./ -B./build -G Ninja
|
|
||||||
|
|
||||||
- name: Compile
|
|
||||||
run: make release
|
|
||||||
|
|
||||||
clang-format:
|
clang-format:
|
||||||
permissions: read-all
|
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"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
|
||||||
image: archlinux
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository actions
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
|
||||||
sparse-checkout: .github/actions
|
|
||||||
|
|
||||||
- name: Setup base
|
|
||||||
uses: ./.github/actions/setup_base
|
|
||||||
|
|
||||||
- name: Configure
|
|
||||||
run: meson setup build -Ddefault_library=static
|
|
||||||
|
|
||||||
- name: clang-format check
|
- name: clang-format check
|
||||||
run: ninja -C build clang-format-check
|
uses: jidicula/clang-format-action@v4.16.0
|
||||||
|
with:
|
||||||
|
exclude-regex: ^subprojects$
|
||||||
|
|
|
||||||
36
.github/workflows/clang-format.yml
vendored
36
.github/workflows/clang-format.yml
vendored
|
|
@ -4,43 +4,23 @@ jobs:
|
||||||
clang-format:
|
clang-format:
|
||||||
permissions: write-all
|
permissions: write-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"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
|
||||||
image: archlinux
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository actions
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
|
||||||
sparse-checkout: .github/actions
|
|
||||||
|
|
||||||
- name: Setup base
|
|
||||||
uses: ./.github/actions/setup_base
|
|
||||||
|
|
||||||
- name: Configure
|
|
||||||
run: meson setup build -Ddefault_library=static
|
|
||||||
|
|
||||||
- name: clang-format check
|
- name: clang-format check
|
||||||
run: ninja -C build clang-format-check
|
uses: jidicula/clang-format-action@v4.16.0
|
||||||
|
with:
|
||||||
|
exclude-regex: ^subprojects$
|
||||||
|
|
||||||
- name: clang-format apply
|
- name: Create comment
|
||||||
if: ${{ failure() && github.event_name == 'pull_request' }}
|
|
||||||
run: ninja -C build clang-format
|
|
||||||
|
|
||||||
- name: Create patch
|
|
||||||
if: ${{ failure() && github.event_name == 'pull_request' }}
|
if: ${{ failure() && github.event_name == 'pull_request' }}
|
||||||
run: |
|
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 'Please fix the formatting issues by running [`clang-format`](https://wiki.hyprland.org/Contributing-and-Debugging/PR-Guidelines/#code-style).' > 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
|
- name: Post comment
|
||||||
if: ${{ failure() && github.event_name == 'pull_request' }}
|
if: ${{ failure() && github.event_name == 'pull_request' }}
|
||||||
uses: mshick/add-pr-comment@v2
|
uses: mshick/add-pr-comment@v2
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
16
.github/workflows/nix-test.yml
vendored
16
.github/workflows/nix-test.yml
vendored
|
|
@ -20,25 +20,13 @@ jobs:
|
||||||
- name: Restore and save Nix store
|
- name: Restore and save Nix store
|
||||||
uses: nix-community/cache-nix-action@v6
|
uses: nix-community/cache-nix-action@v6
|
||||||
with:
|
with:
|
||||||
# restore and save a cache using this key
|
# restore and save a cache using this key (per job)
|
||||||
primary-key: nix-${{ runner.os }}
|
primary-key: nix-${{ runner.os }}-${{ github.job }}
|
||||||
# if there's no cache hit, restore a cache by this prefix
|
# if there's no cache hit, restore a cache by this prefix
|
||||||
restore-prefixes-first-match: nix-${{ runner.os }}
|
restore-prefixes-first-match: nix-${{ runner.os }}
|
||||||
# collect garbage until the Nix store size (in bytes) is at most this number
|
# collect garbage until the Nix store size (in bytes) is at most this number
|
||||||
# before trying to save a new cache
|
# before trying to save a new cache
|
||||||
# 1G = 1073741824
|
|
||||||
gc-max-store-size-linux: 5G
|
gc-max-store-size-linux: 5G
|
||||||
# do purge caches
|
|
||||||
purge: true
|
|
||||||
# purge all versions of the cache
|
|
||||||
purge-prefixes: nix-${{ runner.os }}
|
|
||||||
# created more than this number of seconds ago
|
|
||||||
purge-created: 0
|
|
||||||
# or, last accessed more than this number of seconds ago
|
|
||||||
# relative to the start of the `Post Restore and save Nix store` phase
|
|
||||||
purge-last-accessed: 0
|
|
||||||
# except any version with the key that is the same as the `primary-key`
|
|
||||||
purge-primary-key: never
|
|
||||||
|
|
||||||
- uses: cachix/cachix-action@v15
|
- uses: cachix/cachix-action@v15
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
20
.github/workflows/nix-update-inputs.yml
vendored
20
.github/workflows/nix-update-inputs.yml
vendored
|
|
@ -27,25 +27,13 @@ jobs:
|
||||||
- name: Restore and save Nix store
|
- name: Restore and save Nix store
|
||||||
uses: nix-community/cache-nix-action@v6
|
uses: nix-community/cache-nix-action@v6
|
||||||
with:
|
with:
|
||||||
# restore and save a cache using this key
|
# restore and save a cache using this key (per job)
|
||||||
primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }}
|
primary-key: nix-${{ runner.os }}-${{ github.job }}
|
||||||
# if there's no cache hit, restore a cache by this prefix
|
# if there's no cache hit, restore a cache by this prefix
|
||||||
restore-prefixes-first-match: nix-${{ runner.os }}-
|
restore-prefixes-first-match: nix-${{ runner.os }}
|
||||||
# collect garbage until the Nix store size (in bytes) is at most this number
|
# collect garbage until the Nix store size (in bytes) is at most this number
|
||||||
# before trying to save a new cache
|
# before trying to save a new cache
|
||||||
# 1G = 1073741824
|
gc-max-store-size-linux: 5G
|
||||||
gc-max-store-size-linux: 1G
|
|
||||||
# do purge caches
|
|
||||||
purge: true
|
|
||||||
# purge all versions of the cache
|
|
||||||
purge-prefixes: nix-${{ runner.os }}-
|
|
||||||
# created more than this number of seconds ago
|
|
||||||
purge-created: 0
|
|
||||||
# or, last accessed more than this number of seconds ago
|
|
||||||
# relative to the start of the `Post Restore and save Nix store` phase
|
|
||||||
purge-last-accessed: 0
|
|
||||||
# except any version with the key that is the same as the `primary-key`
|
|
||||||
purge-primary-key: never
|
|
||||||
|
|
||||||
- name: Update inputs
|
- name: Update inputs
|
||||||
run: nix/update-inputs.sh
|
run: nix/update-inputs.sh
|
||||||
|
|
|
||||||
16
.github/workflows/nix.yml
vendored
16
.github/workflows/nix.yml
vendored
|
|
@ -25,25 +25,13 @@ jobs:
|
||||||
- name: Restore and save Nix store
|
- name: Restore and save Nix store
|
||||||
uses: nix-community/cache-nix-action@v6
|
uses: nix-community/cache-nix-action@v6
|
||||||
with:
|
with:
|
||||||
# restore and save a cache using this key
|
# restore and save a cache using this key (per job)
|
||||||
primary-key: nix-${{ runner.os }}
|
primary-key: nix-${{ runner.os }}-${{ github.job }}
|
||||||
# if there's no cache hit, restore a cache by this prefix
|
# if there's no cache hit, restore a cache by this prefix
|
||||||
restore-prefixes-first-match: nix-${{ runner.os }}
|
restore-prefixes-first-match: nix-${{ runner.os }}
|
||||||
# collect garbage until the Nix store size (in bytes) is at most this number
|
# collect garbage until the Nix store size (in bytes) is at most this number
|
||||||
# before trying to save a new cache
|
# before trying to save a new cache
|
||||||
# 1G = 1073741824
|
|
||||||
gc-max-store-size-linux: 5G
|
gc-max-store-size-linux: 5G
|
||||||
# do purge caches
|
|
||||||
purge: true
|
|
||||||
# purge all versions of the cache
|
|
||||||
purge-prefixes: nix-${{ runner.os }}
|
|
||||||
# created more than this number of seconds ago
|
|
||||||
purge-created: 0
|
|
||||||
# or, last accessed more than this number of seconds ago
|
|
||||||
# relative to the start of the `Post Restore and save Nix store` phase
|
|
||||||
purge-last-accessed: 0
|
|
||||||
# except any version with the key that is the same as the `primary-key`
|
|
||||||
purge-primary-key: never
|
|
||||||
|
|
||||||
- uses: cachix/cachix-action@v15
|
- uses: cachix/cachix-action@v15
|
||||||
with:
|
with:
|
||||||
|
|
|
||||||
154
.github/workflows/translation-ai-check.yml
vendored
Normal file
154
.github/workflows/translation-ai-check.yml
vendored
Normal file
|
|
@ -0,0 +1,154 @@
|
||||||
|
name: AI Translation Check
|
||||||
|
|
||||||
|
on:
|
||||||
|
# pull_request_target:
|
||||||
|
# types:
|
||||||
|
# - opened
|
||||||
|
issue_comment:
|
||||||
|
types:
|
||||||
|
- created
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
issues: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
changes:
|
||||||
|
name: Check i18n changes
|
||||||
|
if: ${{ github.event_name == 'pull_request_target' || (github.event_name == 'issue_comment' && github.event.action == 'created' && github.event.issue.pull_request != null && github.event.comment.user.login == 'vaxerski' && github.event.comment.body == 'ai, please recheck' ) }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- uses: dorny/paths-filter@v3
|
||||||
|
id: changes
|
||||||
|
with:
|
||||||
|
filters: |
|
||||||
|
i18n:
|
||||||
|
- 'src/i18n/**'
|
||||||
|
review:
|
||||||
|
name: Review Translation
|
||||||
|
needs: changes
|
||||||
|
if: ${{ needs.changes.outputs.i18n == 'true' }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
OPENAI_MODEL: gpt-5-mini
|
||||||
|
SYSTEM_PROMPT: |
|
||||||
|
You are a programmer and a translator. Your job is to review the attached patch for adding translation to a piece of software and make sure the submitted translation is not malicious, and that it makes sense. If the translation is not malicious, and doesn't contain obvious grammatical mistakes, say "Translation check OK". Otherwise, say "Translation check not ok" and list bad entries.
|
||||||
|
Examples of bad translations include obvious trolling (slurs, etc) or nonsense sentences. Meaningful improvements may be suggested, but if there are only minor improvements, just reply with "Translation check OK". Do not provide anything but the result and (if applicable) the bad entries or improvements.
|
||||||
|
|
||||||
|
AI_PROMPT: Translation patch below.
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- uses: dorny/paths-filter@v3
|
||||||
|
id: changes
|
||||||
|
with:
|
||||||
|
filters: |
|
||||||
|
i18n:
|
||||||
|
- 'src/i18n/**'
|
||||||
|
|
||||||
|
- name: Stop if i18n not changed
|
||||||
|
if: steps.changes.outputs.i18n != 'true'
|
||||||
|
run: echo "No i18n changes in this PR; skipping." && exit 0
|
||||||
|
|
||||||
|
- name: Determine PR number
|
||||||
|
id: pr
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.event_name }}" = "pull_request_target" ]; then
|
||||||
|
echo "number=${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "number=${{ github.event.issue.number }}" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Download combined PR diff
|
||||||
|
id: get_diff
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
PR_NUMBER: ${{ steps.pr.outputs.number }}
|
||||||
|
run: |
|
||||||
|
# Get the combined diff for the entire PR
|
||||||
|
curl -sSL \
|
||||||
|
-H "Authorization: token $GITHUB_TOKEN" \
|
||||||
|
-H "Accept: application/vnd.github.v3.diff" \
|
||||||
|
"https://api.github.com/repos/${{ github.repository }}/pulls/$PR_NUMBER" \
|
||||||
|
-o pr.diff
|
||||||
|
|
||||||
|
# Compute character length
|
||||||
|
LEN=$(wc -c < pr.diff | tr -d ' ')
|
||||||
|
echo "len=$LEN" >> "$GITHUB_OUTPUT"
|
||||||
|
if [ "$LEN" -gt 25000 ]; then
|
||||||
|
echo "too_long=true" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "too_long=false" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "got diff:"
|
||||||
|
cat pr.diff
|
||||||
|
|
||||||
|
- name: Comment when diff length exceeded
|
||||||
|
if: steps.get_diff.outputs.too_long == 'true'
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
PR_NUMBER: ${{ steps.pr.outputs.number }}
|
||||||
|
run: |
|
||||||
|
jq -n --arg body "Diff length exceeded, can't query API" '{body: ("AI translation check result:\n\n" + $body)}' > body.json
|
||||||
|
curl -sS -X POST \
|
||||||
|
-H "Authorization: token $GITHUB_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
"https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUMBER/comments" \
|
||||||
|
--data @body.json
|
||||||
|
|
||||||
|
- name: Query OpenAI and post review
|
||||||
|
if: steps.get_diff.outputs.too_long == 'false'
|
||||||
|
env:
|
||||||
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||||
|
OPENAI_MODEL: ${{ env.OPENAI_MODEL }}
|
||||||
|
SYSTEM_PROMPT: ${{ env.SYSTEM_PROMPT }}
|
||||||
|
AI_PROMPT: ${{ env.AI_PROMPT }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
PR_NUMBER: ${{ steps.pr.outputs.number }}
|
||||||
|
run: |
|
||||||
|
# Prepare OpenAI chat request payload (embed diff safely)
|
||||||
|
jq -n \
|
||||||
|
--arg model "$OPENAI_MODEL" \
|
||||||
|
--arg sys "$SYSTEM_PROMPT" \
|
||||||
|
--arg prompt "$AI_PROMPT" \
|
||||||
|
--rawfile diff pr.diff \
|
||||||
|
'{model:$model,
|
||||||
|
messages:[
|
||||||
|
{role:"system", content:$sys},
|
||||||
|
{role:"user", content: ($prompt + "\n\n```diff\n" + $diff + "\n```")}
|
||||||
|
]
|
||||||
|
}' > payload.json
|
||||||
|
|
||||||
|
# Call OpenAI
|
||||||
|
curl -sS https://api.openai.com/v1/chat/completions \
|
||||||
|
-H "Authorization: Bearer $OPENAI_API_KEY" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d @payload.json > response.json
|
||||||
|
|
||||||
|
# Extract response text
|
||||||
|
COMMENT=$(jq -r '.choices[0].message.content // empty' response.json)
|
||||||
|
if [ -z "$COMMENT" ]; then
|
||||||
|
COMMENT="AI did not return a response."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If failed, add a note
|
||||||
|
ADDITIONAL_NOTE=""
|
||||||
|
if [[ "$COMMENT" == *"not ok"* ]]; then
|
||||||
|
ADDITIONAL_NOTE=$(echo -ne "\n\nPlease note this check is a guideline, not a hard requirement. It is here to help you translate. If you disagree with some points, just state that. Any typos should be fixed.")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Post the review as a PR comment
|
||||||
|
jq -n --arg body "$COMMENT" --arg note "$ADDITIONAL_NOTE" '{body: ("AI translation check result:\n\n" + $body + $note)}' > body.json
|
||||||
|
echo "CURLing https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUMBER/comments"
|
||||||
|
curl -sS -X POST \
|
||||||
|
-H "Authorization: token $GITHUB_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
"https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUMBER/comments" \
|
||||||
|
--data @body.json
|
||||||
|
|
@ -108,7 +108,7 @@ find_package(OpenGL REQUIRED COMPONENTS ${GLES_VERSION})
|
||||||
pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.9.3)
|
pkg_check_modules(aquamarine_dep REQUIRED IMPORTED_TARGET aquamarine>=0.9.3)
|
||||||
pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2)
|
pkg_check_modules(hyprlang_dep REQUIRED IMPORTED_TARGET hyprlang>=0.3.2)
|
||||||
pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7)
|
pkg_check_modules(hyprcursor_dep REQUIRED IMPORTED_TARGET hyprcursor>=0.1.7)
|
||||||
pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.8.2)
|
pkg_check_modules(hyprutils_dep REQUIRED IMPORTED_TARGET hyprutils>=0.10.2)
|
||||||
pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.6)
|
pkg_check_modules(hyprgraphics_dep REQUIRED IMPORTED_TARGET hyprgraphics>=0.1.6)
|
||||||
|
|
||||||
string(REPLACE "." ";" AQ_VERSION_LIST ${aquamarine_dep_VERSION})
|
string(REPLACE "." ";" AQ_VERSION_LIST ${aquamarine_dep_VERSION})
|
||||||
|
|
@ -128,13 +128,41 @@ set(HYPRGRAPHICS_VERSION "${hyprgraphics_dep_VERSION}")
|
||||||
|
|
||||||
find_package(Git QUIET)
|
find_package(Git QUIET)
|
||||||
|
|
||||||
set(GIT_COMMIT_HASH "unknown")
|
# Populate variables with env vars if present
|
||||||
set(GIT_BRANCH "unknown")
|
set(GIT_COMMIT_HASH "$ENV{GIT_COMMIT_HASH}")
|
||||||
set(GIT_COMMIT_MESSAGE "unknown")
|
if(NOT GIT_COMMIT_HASH)
|
||||||
set(GIT_COMMIT_DATE "unknown")
|
set(GIT_COMMIT_HASH "unknown")
|
||||||
set(GIT_DIRTY "unknown")
|
endif()
|
||||||
set(GIT_TAG "unknown")
|
|
||||||
set(GIT_COMMITS "0")
|
set(GIT_BRANCH "$ENV{GIT_BRANCH}")
|
||||||
|
if(NOT GIT_BRANCH)
|
||||||
|
set(GIT_BRANCH "unknown")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(GIT_COMMIT_MESSAGE "$ENV{GIT_COMMIT_MESSAGE}")
|
||||||
|
if(NOT GIT_COMMIT_MESSAGE)
|
||||||
|
set(GIT_COMMIT_MESSAGE "unknown")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(GIT_COMMIT_DATE "$ENV{GIT_COMMIT_DATE}")
|
||||||
|
if(NOT GIT_COMMIT_DATE)
|
||||||
|
set(GIT_COMMIT_DATE "unknown")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(GIT_DIRTY "$ENV{GIT_DIRTY}")
|
||||||
|
if(NOT GIT_DIRTY)
|
||||||
|
set(GIT_DIRTY "unknown")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(GIT_TAG "$ENV{GIT_TAG}")
|
||||||
|
if(NOT GIT_TAG)
|
||||||
|
set(GIT_TAG "unknown")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(GIT_COMMITS "$ENV{GIT_COMMITS}")
|
||||||
|
if(NOT GIT_COMMITS)
|
||||||
|
set(GIT_COMMITS "0")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(Git_FOUND)
|
if(Git_FOUND)
|
||||||
execute_process(
|
execute_process(
|
||||||
|
|
@ -155,10 +183,10 @@ if(Git_FOUND)
|
||||||
execute_process(COMMAND ${GIT_EXECUTABLE} branch --show-current
|
execute_process(COMMAND ${GIT_EXECUTABLE} branch --show-current
|
||||||
WORKING_DIRECTORY ${GIT_TOPLEVEL}
|
WORKING_DIRECTORY ${GIT_TOPLEVEL}
|
||||||
OUTPUT_VARIABLE GIT_BRANCH OUTPUT_STRIP_TRAILING_WHITESPACE)
|
OUTPUT_VARIABLE GIT_BRANCH OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
execute_process(COMMAND ${GIT_EXECUTABLE} show -s --format=%s
|
execute_process(COMMAND sh "-c" "${GIT_EXECUTABLE} show -s --format=%s --no-show-signature | sed \"s/\\\"/\'/g\""
|
||||||
WORKING_DIRECTORY ${GIT_TOPLEVEL}
|
WORKING_DIRECTORY ${GIT_TOPLEVEL}
|
||||||
OUTPUT_VARIABLE GIT_COMMIT_MESSAGE OUTPUT_STRIP_TRAILING_WHITESPACE)
|
OUTPUT_VARIABLE GIT_COMMIT_MESSAGE OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
execute_process(COMMAND ${GIT_EXECUTABLE} show -s --format=%cd --date=local
|
execute_process(COMMAND ${GIT_EXECUTABLE} show -s --format=%cd --date=local --no-show-signature
|
||||||
WORKING_DIRECTORY ${GIT_TOPLEVEL}
|
WORKING_DIRECTORY ${GIT_TOPLEVEL}
|
||||||
OUTPUT_VARIABLE GIT_COMMIT_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
|
OUTPUT_VARIABLE GIT_COMMIT_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
execute_process(COMMAND ${GIT_EXECUTABLE} diff-index --quiet HEAD --
|
execute_process(COMMAND ${GIT_EXECUTABLE} diff-index --quiet HEAD --
|
||||||
|
|
@ -192,7 +220,7 @@ pkg_check_modules(
|
||||||
deps
|
deps
|
||||||
REQUIRED
|
REQUIRED
|
||||||
IMPORTED_TARGET
|
IMPORTED_TARGET
|
||||||
xkbcommon
|
xkbcommon>=1.11.0
|
||||||
uuid
|
uuid
|
||||||
wayland-server>=1.22.90
|
wayland-server>=1.22.90
|
||||||
wayland-protocols>=1.45
|
wayland-protocols>=1.45
|
||||||
|
|
@ -205,7 +233,8 @@ pkg_check_modules(
|
||||||
libinput>=1.28
|
libinput>=1.28
|
||||||
gbm
|
gbm
|
||||||
gio-2.0
|
gio-2.0
|
||||||
re2)
|
re2
|
||||||
|
muparser)
|
||||||
|
|
||||||
find_package(hyprwayland-scanner 0.3.10 REQUIRED)
|
find_package(hyprwayland-scanner 0.3.10 REQUIRED)
|
||||||
|
|
||||||
|
|
@ -483,7 +512,6 @@ add_compile_definitions(DATAROOTDIR="${CMAKE_INSTALL_FULL_DATAROOTDIR}")
|
||||||
|
|
||||||
# installable assets
|
# installable assets
|
||||||
file(GLOB_RECURSE INSTALLABLE_ASSETS "assets/install/*")
|
file(GLOB_RECURSE INSTALLABLE_ASSETS "assets/install/*")
|
||||||
list(FILTER INSTALLABLE_ASSETS EXCLUDE REGEX "meson.build")
|
|
||||||
install(FILES ${INSTALLABLE_ASSETS}
|
install(FILES ${INSTALLABLE_ASSETS}
|
||||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr)
|
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/hypr)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
install_data(
|
|
||||||
'hyprland-portals.conf',
|
|
||||||
install_dir: join_paths(get_option('datadir'), 'xdg-desktop-portal'),
|
|
||||||
install_tag: 'runtime',
|
|
||||||
)
|
|
||||||
|
|
||||||
subdir('install')
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
install_man('Hyprland.1')
|
|
||||||
install_man('hyprctl.1')
|
|
||||||
|
|
@ -159,10 +159,23 @@ animations {
|
||||||
# uncomment all if you wish to use that.
|
# uncomment all if you wish to use that.
|
||||||
# workspace = w[tv1], gapsout:0, gapsin:0
|
# workspace = w[tv1], gapsout:0, gapsin:0
|
||||||
# workspace = f[1], gapsout:0, gapsin:0
|
# workspace = f[1], gapsout:0, gapsin:0
|
||||||
# windowrule = bordersize 0, floating:0, onworkspace:w[tv1]
|
# windowrule {
|
||||||
# windowrule = rounding 0, floating:0, onworkspace:w[tv1]
|
# name = no-gaps-wtv1
|
||||||
# windowrule = bordersize 0, floating:0, onworkspace:f[1]
|
# match:float = false
|
||||||
# windowrule = rounding 0, floating:0, onworkspace:f[1]
|
# match:workspace = w[tv1]
|
||||||
|
#
|
||||||
|
# border_size = 0
|
||||||
|
# rounding = 0
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# windowrule {
|
||||||
|
# name = no-gaps-f1
|
||||||
|
# match:float = false
|
||||||
|
# match:workspace = f[1]
|
||||||
|
#
|
||||||
|
# border_size = 0
|
||||||
|
# rounding = 0
|
||||||
|
# }
|
||||||
|
|
||||||
# See https://wiki.hypr.land/Configuring/Dwindle-Layout/ for more
|
# See https://wiki.hypr.land/Configuring/Dwindle-Layout/ for more
|
||||||
dwindle {
|
dwindle {
|
||||||
|
|
@ -294,11 +307,25 @@ bindl = , XF86AudioPrev, exec, playerctl previous
|
||||||
# See https://wiki.hypr.land/Configuring/Window-Rules/ for more
|
# See https://wiki.hypr.land/Configuring/Window-Rules/ for more
|
||||||
# See https://wiki.hypr.land/Configuring/Workspace-Rules/ for workspace rules
|
# See https://wiki.hypr.land/Configuring/Workspace-Rules/ for workspace rules
|
||||||
|
|
||||||
# Example windowrule
|
# Example windowrules that are useful
|
||||||
# windowrule = float,class:^(kitty)$,title:^(kitty)$
|
|
||||||
|
|
||||||
# Ignore maximize requests from apps. You'll probably like this.
|
windowrule {
|
||||||
windowrule = suppressevent maximize, class:.*
|
# Ignore maximize requests from all apps. You'll probably like this.
|
||||||
|
name = suppress-maximize-events
|
||||||
|
match:class = .*
|
||||||
|
|
||||||
# Fix some dragging issues with XWayland
|
suppress_event = maximize
|
||||||
windowrule = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0
|
}
|
||||||
|
|
||||||
|
windowrule {
|
||||||
|
# Fix some dragging issues with XWayland
|
||||||
|
name = fix-xwayland-drags
|
||||||
|
match:class = ^$
|
||||||
|
match:title = ^$
|
||||||
|
match:xwayland = true
|
||||||
|
match:float = true
|
||||||
|
match:fullscreen = false
|
||||||
|
match:pin = false
|
||||||
|
|
||||||
|
no_focus = true
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
install_data(
|
|
||||||
'hyprland.conf',
|
|
||||||
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',
|
|
||||||
)
|
|
||||||
24
flake.lock
generated
24
flake.lock
generated
|
|
@ -193,11 +193,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1758927902,
|
"lastModified": 1763254292,
|
||||||
"narHash": "sha256-LZgMds7M94+vuMql2bERQ6LiFFdhgsEFezE4Vn+Ys3A=",
|
"narHash": "sha256-JNgz3Fz2KMzkT7aR72wsgu/xNeJB//LSmdilh8Z/Zao=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprlang",
|
"repo": "hyprlang",
|
||||||
"rev": "4dafa28d4f79877d67a7d1a654cddccf8ebf15da",
|
"rev": "deea98d5b61d066bdc7a68163edd2c4bd28d3a6b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -261,11 +261,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1762387740,
|
"lastModified": 1763323331,
|
||||||
"narHash": "sha256-gQ9zJ+pUI4o+Gh4Z6jhJll7jjCSwi8ZqJIhCE2oqwhQ=",
|
"narHash": "sha256-+Z0OfCo1MS8/aIutSAW5aJR9zTae1wz9kcJYMgpwN6M=",
|
||||||
"owner": "hyprwm",
|
"owner": "hyprwm",
|
||||||
"repo": "hyprutils",
|
"repo": "hyprutils",
|
||||||
"rev": "926689ddb9c0a8787e58c02c765a62e32d63d1f7",
|
"rev": "0c6411851cc779d551edc89b83966696201611aa",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -299,11 +299,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1762363567,
|
"lastModified": 1763283776,
|
||||||
"narHash": "sha256-YRqMDEtSMbitIMj+JLpheSz0pwEr0Rmy5mC7myl17xs=",
|
"narHash": "sha256-Y7TDFPK4GlqrKrivOcsHG8xSGqQx3A6c+i7novT85Uk=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "ae814fd3904b621d8ab97418f1d0f2eb0d3716f4",
|
"rev": "50a96edd8d0db6cc8db57dab6bb6d6ee1f3dc49a",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -322,11 +322,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1762441963,
|
"lastModified": 1763319842,
|
||||||
"narHash": "sha256-j+rNQ119ffYUkYt2YYS6rnd6Jh/crMZmbqpkGLXaEt0=",
|
"narHash": "sha256-YG19IyrTdnVn0l3DvcUYm85u3PaqBt6tI6VvolcuHnA=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "git-hooks.nix",
|
"repo": "git-hooks.nix",
|
||||||
"rev": "8e7576e79b88c16d7ee3bbd112c8d90070832885",
|
"rev": "7275fa67fbbb75891c16d9dee7d88e58aea2d761",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,6 @@
|
||||||
(pkgsFor.${system})
|
(pkgsFor.${system})
|
||||||
# hyprland-packages
|
# hyprland-packages
|
||||||
hyprland
|
hyprland
|
||||||
hyprland-with-hyprtester
|
|
||||||
hyprland-unwrapped
|
hyprland-unwrapped
|
||||||
# hyprland-extras
|
# hyprland-extras
|
||||||
xdg-desktop-portal-hyprland
|
xdg-desktop-portal-hyprland
|
||||||
|
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
executable(
|
|
||||||
'hyprctl',
|
|
||||||
'main.cpp',
|
|
||||||
dependencies: [
|
|
||||||
dependency('hyprutils', version: '>= 0.1.1'),
|
|
||||||
dependency('re2', required: true)
|
|
||||||
],
|
|
||||||
install: true,
|
|
||||||
)
|
|
||||||
|
|
||||||
install_data(
|
|
||||||
'hyprctl.bash',
|
|
||||||
install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'),
|
|
||||||
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',
|
|
||||||
)
|
|
||||||
|
|
@ -25,8 +25,8 @@ 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 confirming successful plugin load.
|
||||||
┣ --notify-fail | -nn → Send a hyprland notification for fail events only.
|
┃ Warnings/Errors trigger notifications regardless of this flag.
|
||||||
┣ --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).
|
||||||
|
|
@ -47,7 +47,7 @@ int main(int argc, char** argv, char** envp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
std::string customHlUrl;
|
std::string customHlUrl;
|
||||||
|
|
||||||
for (int i = 1; i < argc; ++i) {
|
for (int i = 1; i < argc; ++i) {
|
||||||
|
|
@ -58,7 +58,9 @@ int main(int argc, char** argv, char** envp) {
|
||||||
} 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") {
|
} else if (ARGS[i] == "--notify-fail" || ARGS[i] == "-nn") {
|
||||||
notifyFail = notify = true;
|
// TODO: Deprecated since v.053.0. Remove in version>0.56.0
|
||||||
|
std::println(stderr, "{}", failureString("Deprececated flag."));
|
||||||
|
g_pPluginManager->notify(ICON_INFO, 0, 10000, "[hyprpm] -n flag is deprecated, see hyprpm --help.");
|
||||||
} 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") {
|
||||||
|
|
@ -149,8 +151,9 @@ int main(int argc, char** argv, char** envp) {
|
||||||
|
|
||||||
if (ret2 != LOADSTATE_OK)
|
if (ret2 != LOADSTATE_OK)
|
||||||
return 1;
|
return 1;
|
||||||
} else if (notify)
|
} else {
|
||||||
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 (command.size() < 2) {
|
if (command.size() < 2) {
|
||||||
std::println(stderr, "{}", failureString("Not enough args for enable."));
|
std::println(stderr, "{}", failureString("Not enough args for enable."));
|
||||||
|
|
@ -194,7 +197,6 @@ int main(int argc, char** argv, char** envp) {
|
||||||
auto ret = g_pPluginManager->ensurePluginsLoadState(force);
|
auto ret = g_pPluginManager->ensurePluginsLoadState(force);
|
||||||
|
|
||||||
if (ret != LOADSTATE_OK) {
|
if (ret != LOADSTATE_OK) {
|
||||||
if (notify) {
|
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case LOADSTATE_FAIL:
|
case LOADSTATE_FAIL:
|
||||||
case LOADSTATE_PARTIAL_FAIL: g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Failed to load plugins"); break;
|
case LOADSTATE_PARTIAL_FAIL: g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Failed to load plugins"); break;
|
||||||
|
|
@ -203,10 +205,9 @@ int main(int argc, char** argv, char** envp) {
|
||||||
break;
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
} else if (notify && !notifyFail) {
|
} else if (notify) {
|
||||||
g_pPluginManager->notify(ICON_OK, 0, 4000, "[hyprpm] Loaded plugins");
|
g_pPluginManager->notify(ICON_OK, 0, 4000, "[hyprpm] Loaded plugins");
|
||||||
}
|
}
|
||||||
} else if (command[0] == "purge-cache") {
|
} else if (command[0] == "purge-cache") {
|
||||||
|
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true)
|
|
||||||
src = globber.stdout().strip().split('\n')
|
|
||||||
|
|
||||||
executable(
|
|
||||||
'hyprpm',
|
|
||||||
src,
|
|
||||||
dependencies: [
|
|
||||||
dependency('hyprutils', version: '>= 0.1.1'),
|
|
||||||
dependency('threads'),
|
|
||||||
dependency('tomlplusplus'),
|
|
||||||
dependency('glaze', method: 'cmake'),
|
|
||||||
],
|
|
||||||
install: true,
|
|
||||||
)
|
|
||||||
|
|
||||||
install_data(
|
|
||||||
'../hyprpm.bash',
|
|
||||||
install_dir: join_paths(get_option('datadir'), 'bash-completion/completions'),
|
|
||||||
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',
|
|
||||||
)
|
|
||||||
|
|
@ -11,6 +11,8 @@
|
||||||
#include <src/managers/input/InputManager.hpp>
|
#include <src/managers/input/InputManager.hpp>
|
||||||
#include <src/managers/PointerManager.hpp>
|
#include <src/managers/PointerManager.hpp>
|
||||||
#include <src/managers/input/trackpad/TrackpadGestures.hpp>
|
#include <src/managers/input/trackpad/TrackpadGestures.hpp>
|
||||||
|
#include <src/desktop/rule/windowRule/WindowRuleEffectContainer.hpp>
|
||||||
|
#include <src/desktop/rule/windowRule/WindowRuleApplicator.hpp>
|
||||||
#include <src/Compositor.hpp>
|
#include <src/Compositor.hpp>
|
||||||
#undef private
|
#undef private
|
||||||
|
|
||||||
|
|
@ -245,6 +247,30 @@ static SDispatchResult keybind(std::string in) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Desktop::Rule::CWindowRuleEffectContainer::storageType ruleIDX = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
static SDispatchResult addRule(std::string in) {
|
||||||
|
ruleIDX = Desktop::Rule::windowEffects()->registerEffect("plugin_rule");
|
||||||
|
|
||||||
|
if (Desktop::Rule::windowEffects()->registerEffect("plugin_rule") != ruleIDX)
|
||||||
|
return {.success = false, .error = "re-registering returned a different id?"};
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDispatchResult checkRule(std::string in) {
|
||||||
|
if (!g_pCompositor->m_lastWindow)
|
||||||
|
return {.success = false, .error = "No window"};
|
||||||
|
|
||||||
|
if (!g_pCompositor->m_lastWindow->m_ruleApplicator->m_otherProps.props.contains(ruleIDX))
|
||||||
|
return {.success = false, .error = "No rule"};
|
||||||
|
|
||||||
|
if (g_pCompositor->m_lastWindow->m_ruleApplicator->m_otherProps.props[ruleIDX]->effect != "effect")
|
||||||
|
return {.success = false, .error = "Effect isn't \"effect\""};
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
||||||
PHANDLE = handle;
|
PHANDLE = handle;
|
||||||
|
|
||||||
|
|
@ -255,6 +281,8 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
|
||||||
HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:gesture", ::simulateGesture);
|
HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:gesture", ::simulateGesture);
|
||||||
HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:scroll", ::scroll);
|
HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:scroll", ::scroll);
|
||||||
HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:keybind", ::keybind);
|
HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:keybind", ::keybind);
|
||||||
|
HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:add_rule", ::addRule);
|
||||||
|
HyprlandAPI::addDispatcherV2(PHANDLE, "plugin:test:check_rule", ::checkRule);
|
||||||
|
|
||||||
// init mouse
|
// init mouse
|
||||||
g_mouse = CTestMouse::create(false);
|
g_mouse = CTestMouse::create(false);
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ static bool startClient(SClient& client) {
|
||||||
// wait for window to appear
|
// wait for window to appear
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
|
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
|
||||||
|
|
||||||
if (getFromSocket(std::format("/dispatch setprop pid:{} noanim 1", client.proc->pid())) != "ok") {
|
if (getFromSocket(std::format("/dispatch setprop pid:{} no_anim 1", client.proc->pid())) != "ok") {
|
||||||
NLog::log("{}Failed to disable animations for client window", Colors::RED, ret);
|
NLog::log("{}Failed to disable animations for client window", Colors::RED, ret);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -130,7 +130,7 @@ static bool test() {
|
||||||
EXPECT(sendScroll(10), true);
|
EXPECT(sendScroll(10), true);
|
||||||
EXPECT(getLastDelta(client), 30);
|
EXPECT(getLastDelta(client), 30);
|
||||||
|
|
||||||
EXPECT(getFromSocket("r/dispatch setprop active scrollmouse 4"), "ok");
|
EXPECT(getFromSocket("r/dispatch setprop active scroll_mouse 4"), "ok");
|
||||||
EXPECT(sendScroll(10), true);
|
EXPECT(sendScroll(10), true);
|
||||||
EXPECT(getLastDelta(client), 40);
|
EXPECT(getLastDelta(client), 40);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ static bool startClient(SClient& client) {
|
||||||
// wait for window to appear
|
// wait for window to appear
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
|
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
|
||||||
|
|
||||||
if (getFromSocket(std::format("/dispatch setprop pid:{} noanim 1", client.proc->pid())) != "ok") {
|
if (getFromSocket(std::format("/dispatch setprop pid:{} no_anim 1", client.proc->pid())) != "ok") {
|
||||||
NLog::log("{}Failed to disable animations for client window", Colors::RED, ret);
|
NLog::log("{}Failed to disable animations for client window", Colors::RED, ret);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ static void testFloatClamp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
OK(getFromSocket("/keyword dwindle:force_split 2"));
|
OK(getFromSocket("/keyword dwindle:force_split 2"));
|
||||||
|
OK(getFromSocket("/keyword monitor HEADLESS-2, addreserved, 0, 20, 0, 20"));
|
||||||
OK(getFromSocket("/dispatch focuswindow class:c"));
|
OK(getFromSocket("/dispatch focuswindow class:c"));
|
||||||
OK(getFromSocket("/dispatch setfloating class:c"));
|
OK(getFromSocket("/dispatch setfloating class:c"));
|
||||||
OK(getFromSocket("/dispatch resizewindowpixel exact 1200 900,class:c"));
|
OK(getFromSocket("/dispatch resizewindowpixel exact 1200 900,class:c"));
|
||||||
|
|
@ -24,7 +25,7 @@ static void testFloatClamp() {
|
||||||
|
|
||||||
{
|
{
|
||||||
auto str = getFromSocket("/clients");
|
auto str = getFromSocket("/clients");
|
||||||
EXPECT_CONTAINS(str, "at: 718,178");
|
EXPECT_CONTAINS(str, "at: 698,158");
|
||||||
EXPECT_CONTAINS(str, "size: 1200,900");
|
EXPECT_CONTAINS(str, "size: 1200,900");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,82 +56,82 @@ static bool testGetprop() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// animationstyle
|
// animation
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty animationstyle"), "(unset)");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty animation"), "(unset)");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty animationstyle -j"), R"({"animationstyle": ""})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty animation -j"), R"({"animation": ""})");
|
||||||
getFromSocket("/dispatch setprop class:kitty animationstyle teststyle");
|
getFromSocket("/dispatch setprop class:kitty animation teststyle");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty animationstyle"), "teststyle");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty animation"), "teststyle");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty animationstyle -j"), R"({"animationstyle": "teststyle"})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty animation -j"), R"({"animation": "teststyle"})");
|
||||||
|
|
||||||
// maxsize
|
// max_size
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty maxsize"), "inf inf");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty max_size"), "inf inf");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty maxsize -j"), R"({"maxsize": [null,null]})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty max_size -j"), R"({"max_size": [null,null]})");
|
||||||
getFromSocket("/dispatch setprop class:kitty maxsize 200 150");
|
getFromSocket("/dispatch setprop class:kitty max_size 200 150");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty maxsize"), "200 150");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty max_size"), "200 150");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty maxsize -j"), R"({"maxsize": [200,150]})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty max_size -j"), R"({"max_size": [200,150]})");
|
||||||
|
|
||||||
// minsize
|
// min_size
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty minsize"), "20 20");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty min_size"), "20 20");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty minsize -j"), R"({"minsize": [20,20]})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty min_size -j"), R"({"min_size": [20,20]})");
|
||||||
getFromSocket("/dispatch setprop class:kitty minsize 100 50");
|
getFromSocket("/dispatch setprop class:kitty min_size 100 50");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty minsize"), "100 50");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty min_size"), "100 50");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty minsize -j"), R"({"minsize": [100,50]})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty min_size -j"), R"({"min_size": [100,50]})");
|
||||||
|
|
||||||
// alpha
|
// opacity
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alpha"), "1");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity"), "1");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alpha -j"), R"({"alpha": 1})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity -j"), R"({"opacity": 1})");
|
||||||
getFromSocket("/dispatch setprop class:kitty alpha 0.3");
|
getFromSocket("/dispatch setprop class:kitty opacity 0.3");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alpha"), "0.3");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity"), "0.3");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alpha -j"), R"({"alpha": 0.3})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity -j"), R"({"opacity": 0.3})");
|
||||||
|
|
||||||
// alphainactive
|
// opacity_inactive
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphainactive"), "1");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_inactive"), "1");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphainactive -j"), R"({"alphainactive": 1})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_inactive -j"), R"({"opacity_inactive": 1})");
|
||||||
getFromSocket("/dispatch setprop class:kitty alphainactive 0.5");
|
getFromSocket("/dispatch setprop class:kitty opacity_inactive 0.5");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphainactive"), "0.5");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_inactive"), "0.5");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphainactive -j"), R"({"alphainactive": 0.5})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_inactive -j"), R"({"opacity_inactive": 0.5})");
|
||||||
|
|
||||||
// alphafullscreen
|
// opacity_fullscreen
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphafullscreen"), "1");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_fullscreen"), "1");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphafullscreen -j"), R"({"alphafullscreen": 1})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_fullscreen -j"), R"({"opacity_fullscreen": 1})");
|
||||||
getFromSocket("/dispatch setprop class:kitty alphafullscreen 0.75");
|
getFromSocket("/dispatch setprop class:kitty opacity_fullscreen 0.75");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphafullscreen"), "0.75");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_fullscreen"), "0.75");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphafullscreen -j"), R"({"alphafullscreen": 0.75})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_fullscreen -j"), R"({"opacity_fullscreen": 0.75})");
|
||||||
|
|
||||||
// alphaoverride
|
// opacity_override
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphaoverride"), "false");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_override"), "false");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphaoverride -j"), R"({"alphaoverride": false})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_override -j"), R"({"opacity_override": false})");
|
||||||
getFromSocket("/dispatch setprop class:kitty alphaoverride true");
|
getFromSocket("/dispatch setprop class:kitty opacity_override true");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphaoverride"), "true");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_override"), "true");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphaoverride -j"), R"({"alphaoverride": true})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_override -j"), R"({"opacity_override": true})");
|
||||||
|
|
||||||
// alphainactiveoverride
|
// opacity_inactive_override
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphainactiveoverride"), "false");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_inactive_override"), "false");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphainactiveoverride -j"), R"({"alphainactiveoverride": false})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_inactive_override -j"), R"({"opacity_inactive_override": false})");
|
||||||
getFromSocket("/dispatch setprop class:kitty alphainactiveoverride true");
|
getFromSocket("/dispatch setprop class:kitty opacity_inactive_override true");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphainactiveoverride"), "true");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_inactive_override"), "true");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphainactiveoverride -j"), R"({"alphainactiveoverride": true})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_inactive_override -j"), R"({"opacity_inactive_override": true})");
|
||||||
|
|
||||||
// alphafullscreenoverride
|
// opacity_fullscreen_override
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphafullscreenoverride"), "false");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_fullscreen_override"), "false");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphafullscreenoverride -j"), R"({"alphafullscreenoverride": false})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_fullscreen_override -j"), R"({"opacity_fullscreen_override": false})");
|
||||||
getFromSocket("/dispatch setprop class:kitty alphafullscreenoverride true");
|
getFromSocket("/dispatch setprop class:kitty opacity_fullscreen_override true");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphafullscreenoverride"), "true");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_fullscreen_override"), "true");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty alphafullscreenoverride -j"), R"({"alphafullscreenoverride": true})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty opacity_fullscreen_override -j"), R"({"opacity_fullscreen_override": true})");
|
||||||
|
|
||||||
// activebordercolor
|
// active_border_color
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty activebordercolor"), "ee33ccff ee00ff99 45deg");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty active_border_color"), "ee33ccff ee00ff99 45deg");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty activebordercolor -j"), R"({"activebordercolor": "ee33ccff ee00ff99 45deg"})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty active_border_color -j"), R"({"active_border_color": "ee33ccff ee00ff99 45deg"})");
|
||||||
getFromSocket("/dispatch setprop class:kitty activebordercolor rgb(abcdef)");
|
getFromSocket("/dispatch setprop class:kitty active_border_color rgb(abcdef)");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty activebordercolor"), "ffabcdef 0deg");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty active_border_color"), "ffabcdef 0deg");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty activebordercolor -j"), R"({"activebordercolor": "ffabcdef 0deg"})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty active_border_color -j"), R"({"active_border_color": "ffabcdef 0deg"})");
|
||||||
|
|
||||||
// bool window properties
|
// bool window properties
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty allowsinput"), "false");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty allows_input"), "false");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty allowsinput -j"), R"({"allowsinput": false})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty allows_input -j"), R"({"allows_input": false})");
|
||||||
getFromSocket("/dispatch setprop class:kitty allowsinput true");
|
getFromSocket("/dispatch setprop class:kitty allows_input true");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty allowsinput"), "true");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty allows_input"), "true");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty allowsinput -j"), R"({"allowsinput": true})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty allows_input -j"), R"({"allows_input": true})");
|
||||||
|
|
||||||
// int window properties
|
// int window properties
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty rounding"), "10");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty rounding"), "10");
|
||||||
|
|
@ -141,16 +141,16 @@ static bool testGetprop() {
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty rounding -j"), R"({"rounding": 4})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty rounding -j"), R"({"rounding": 4})");
|
||||||
|
|
||||||
// float window properties
|
// float window properties
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty roundingpower"), "2");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty rounding_power"), "2");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty roundingpower -j"), R"({"roundingpower": 2})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty rounding_power -j"), R"({"rounding_power": 2})");
|
||||||
getFromSocket("/dispatch setprop class:kitty roundingpower 1.25");
|
getFromSocket("/dispatch setprop class:kitty rounding_power 1.25");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty roundingpower"), "1.25");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty rounding_power"), "1.25");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty roundingpower -j"), R"({"roundingpower": 1.25})");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty rounding_power -j"), R"({"rounding_power": 1.25})");
|
||||||
|
|
||||||
// errors
|
// errors
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop"), "not enough args");
|
EXPECT(getCommandStdOut("hyprctl getprop"), "not enough args");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty"), "not enough args");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty"), "not enough args");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:nonexistantclass animationstyle"), "window not found");
|
EXPECT(getCommandStdOut("hyprctl getprop class:nonexistantclass animation"), "window not found");
|
||||||
EXPECT(getCommandStdOut("hyprctl getprop class:kitty nonexistantprop"), "prop not found");
|
EXPECT(getCommandStdOut("hyprctl getprop class:kitty nonexistantprop"), "prop not found");
|
||||||
|
|
||||||
// kill all
|
// kill all
|
||||||
|
|
|
||||||
|
|
@ -21,21 +21,24 @@ static bool testTags() {
|
||||||
|
|
||||||
NLog::log("{}Testing testTag tags", Colors::YELLOW);
|
NLog::log("{}Testing testTag tags", Colors::YELLOW);
|
||||||
|
|
||||||
OK(getFromSocket("/keyword windowrule tag +testTag, class:tagged"));
|
OK(getFromSocket("/keyword windowrule[tag-test-1]:tag +testTag"));
|
||||||
OK(getFromSocket("/keyword windowrule noshadow, tag:negative:testTag"));
|
OK(getFromSocket("/keyword windowrule[tag-test-1]:match:class tagged"));
|
||||||
OK(getFromSocket("/keyword windowrule noborder, tag:testTag"));
|
OK(getFromSocket("/keyword windowrule[tag-test-2]:match:tag negative:testTag"));
|
||||||
|
OK(getFromSocket("/keyword windowrule[tag-test-2]:no_shadow true"));
|
||||||
|
OK(getFromSocket("/keyword windowrule[tag-test-3]:match:tag testTag"));
|
||||||
|
OK(getFromSocket("/keyword windowrule[tag-test-3]:no_dim true"));
|
||||||
|
|
||||||
EXPECT(Tests::windowCount(), 2);
|
EXPECT(Tests::windowCount(), 2);
|
||||||
OK(getFromSocket("/dispatch focuswindow class:tagged"));
|
OK(getFromSocket("/dispatch focuswindow class:tagged"));
|
||||||
NLog::log("{}Testing tagged window for noborder & noshadow", Colors::YELLOW);
|
NLog::log("{}Testing tagged window for no_dim 0 & no_shadow", Colors::YELLOW);
|
||||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "testTag");
|
EXPECT_CONTAINS(getFromSocket("/activewindow"), "testTag");
|
||||||
EXPECT_CONTAINS(getFromSocket("/getprop activewindow noborder"), "true");
|
EXPECT_CONTAINS(getFromSocket("/getprop activewindow no_dim"), "true");
|
||||||
EXPECT_CONTAINS(getFromSocket("/getprop activewindow noshadow"), "false");
|
EXPECT_CONTAINS(getFromSocket("/getprop activewindow no_shadow"), "false");
|
||||||
NLog::log("{}Testing untagged window for noborder & noshadow", Colors::YELLOW);
|
NLog::log("{}Testing untagged window for no_dim & no_shadow", Colors::YELLOW);
|
||||||
OK(getFromSocket("/dispatch focuswindow class:untagged"));
|
OK(getFromSocket("/dispatch focuswindow class:untagged"));
|
||||||
EXPECT_NOT_CONTAINS(getFromSocket("/activewindow"), "testTag");
|
EXPECT_NOT_CONTAINS(getFromSocket("/activewindow"), "testTag");
|
||||||
EXPECT_CONTAINS(getFromSocket("/getprop activewindow noborder"), "false");
|
EXPECT_CONTAINS(getFromSocket("/getprop activewindow no_shadow"), "true");
|
||||||
EXPECT_CONTAINS(getFromSocket("/getprop activewindow noshadow"), "true");
|
EXPECT_CONTAINS(getFromSocket("/getprop activewindow no_dim"), "false");
|
||||||
|
|
||||||
Tests::killAllWindows();
|
Tests::killAllWindows();
|
||||||
EXPECT(Tests::windowCount(), 0);
|
EXPECT(Tests::windowCount(), 0);
|
||||||
|
|
|
||||||
|
|
@ -152,40 +152,22 @@ static bool test() {
|
||||||
|
|
||||||
NLog::log("{}Testing window split ratios", Colors::YELLOW);
|
NLog::log("{}Testing window split ratios", Colors::YELLOW);
|
||||||
{
|
{
|
||||||
const double INITIAL_RATIO = 1.25;
|
const double RATIO = 1.25;
|
||||||
|
const double PERCENT = RATIO / 2.0 * 100.0;
|
||||||
const int GAPSIN = 5;
|
const int GAPSIN = 5;
|
||||||
const int GAPSOUT = 20;
|
const int GAPSOUT = 20;
|
||||||
const int BORDERSIZE = 2;
|
const int BORDERS = 2 * 2;
|
||||||
const int BORDERS = BORDERSIZE * 2;
|
const int WTRIM = BORDERS + GAPSIN + GAPSOUT;
|
||||||
const int MONITOR_W = 1920;
|
const int HEIGHT = 1080 - (BORDERS + (GAPSOUT * 2));
|
||||||
const int MONITOR_H = 1080;
|
const int WIDTH1 = std::round(1920.0 / 2.0 * (2 - RATIO)) - WTRIM;
|
||||||
|
const int WIDTH2 = std::round(1920.0 / 2.0 * RATIO) - WTRIM;
|
||||||
const float totalAvailableHeight = MONITOR_H - (GAPSOUT * 2);
|
|
||||||
const int HEIGHT = std::round(totalAvailableHeight) - BORDERS;
|
|
||||||
const float availableWidthForSplit = MONITOR_W - (GAPSOUT * 2) - GAPSIN;
|
|
||||||
|
|
||||||
auto calculateFinalWidth = [&](double boxWidth, bool isLeftWindow) {
|
|
||||||
double gapLeft = isLeftWindow ? GAPSOUT : GAPSIN;
|
|
||||||
double gapRight = isLeftWindow ? GAPSIN : GAPSOUT;
|
|
||||||
return std::round(boxWidth - gapLeft - gapRight - BORDERS);
|
|
||||||
};
|
|
||||||
|
|
||||||
double geomBoxWidthA_R1 = (availableWidthForSplit * INITIAL_RATIO / 2.0) + GAPSOUT + (GAPSIN / 2.0);
|
|
||||||
double geomBoxWidthB_R1 = MONITOR_W - geomBoxWidthA_R1;
|
|
||||||
const int WIDTH1 = calculateFinalWidth(geomBoxWidthB_R1, false);
|
|
||||||
|
|
||||||
const double INVERTED_RATIO = 0.75;
|
|
||||||
double geomBoxWidthA_R2 = (availableWidthForSplit * INVERTED_RATIO / 2.0) + GAPSOUT + (GAPSIN / 2.0);
|
|
||||||
double geomBoxWidthB_R2 = MONITOR_W - geomBoxWidthA_R2;
|
|
||||||
const int WIDTH2 = calculateFinalWidth(geomBoxWidthB_R2, false);
|
|
||||||
const int WIDTH_A_FINAL = calculateFinalWidth(geomBoxWidthA_R2, true);
|
|
||||||
|
|
||||||
OK(getFromSocket("/keyword dwindle:default_split_ratio 1.25"));
|
OK(getFromSocket("/keyword dwindle:default_split_ratio 1.25"));
|
||||||
|
|
||||||
if (!spawnKitty("kitty_B"))
|
if (!spawnKitty("kitty_B"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
NLog::log("{}Expecting kitty_B size: {},{}", Colors::YELLOW, WIDTH1, HEIGHT);
|
NLog::log("{}Expecting kitty_B to take up roughly {}% of screen width", Colors::YELLOW, 100 - PERCENT);
|
||||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("size: {},{}", WIDTH1, HEIGHT));
|
EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("size: {},{}", WIDTH1, HEIGHT));
|
||||||
|
|
||||||
OK(getFromSocket("/dispatch killwindow activewindow"));
|
OK(getFromSocket("/dispatch killwindow activewindow"));
|
||||||
|
|
@ -197,12 +179,12 @@ static bool test() {
|
||||||
if (!spawnKitty("kitty_B"))
|
if (!spawnKitty("kitty_B"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
NLog::log("{}Expecting kitty_B size: {},{}", Colors::YELLOW, WIDTH2, HEIGHT);
|
NLog::log("{}Expecting kitty_B to take up roughly {}% of screen width", Colors::YELLOW, PERCENT);
|
||||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("size: {},{}", WIDTH2, HEIGHT));
|
EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("size: {},{}", WIDTH2, HEIGHT));
|
||||||
|
|
||||||
OK(getFromSocket("/dispatch focuswindow class:kitty_A"));
|
OK(getFromSocket("/dispatch focuswindow class:kitty_A"));
|
||||||
NLog::log("{}Expecting kitty_A size: {},{}", Colors::YELLOW, WIDTH_A_FINAL, HEIGHT);
|
NLog::log("{}Expecting kitty_A to have the same width as the previous kitty_B", Colors::YELLOW);
|
||||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("size: {},{}", WIDTH_A_FINAL, HEIGHT));
|
EXPECT_CONTAINS(getFromSocket("/activewindow"), std::format("size: {},{}", WIDTH1, HEIGHT));
|
||||||
|
|
||||||
OK(getFromSocket("/keyword dwindle:default_split_ratio 1"));
|
OK(getFromSocket("/keyword dwindle:default_split_ratio 1"));
|
||||||
}
|
}
|
||||||
|
|
@ -246,12 +228,15 @@ static bool test() {
|
||||||
|
|
||||||
testSwapWindow();
|
testSwapWindow();
|
||||||
|
|
||||||
|
getFromSocket("/dispatch workspace 1");
|
||||||
|
|
||||||
NLog::log("{}Testing minsize/maxsize rules for tiled windows", Colors::YELLOW);
|
NLog::log("{}Testing minsize/maxsize rules for tiled windows", Colors::YELLOW);
|
||||||
{
|
{
|
||||||
// Enable the config for testing, test max/minsize for tiled windows and centering
|
// Enable the config for testing, test max/minsize for tiled windows and centering
|
||||||
OK(getFromSocket("/keyword misc:size_limits_tiled 1"));
|
OK(getFromSocket("/keyword misc:size_limits_tiled 1"));
|
||||||
OK(getFromSocket("/keyword windowrule maxsize 1500 500, class:kitty_maxsize"));
|
OK(getFromSocket("/keyword windowrule[kitty-max-rule]:match:class kitty_maxsize"));
|
||||||
OK(getFromSocket("/keyword windowrule minsize 1200 500, class:kitty_maxsize"));
|
OK(getFromSocket("/keyword windowrule[kitty-max-rule]:max_size 1500 500"));
|
||||||
|
OK(getFromSocket("r/keyword windowrule[kitty-max-rule]:min_size 1200 500"));
|
||||||
if (!spawnKitty("kitty_maxsize"))
|
if (!spawnKitty("kitty_maxsize"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
@ -297,29 +282,127 @@ static bool test() {
|
||||||
EXPECT_CONTAINS(str, "floating: 1");
|
EXPECT_CONTAINS(str, "floating: 1");
|
||||||
EXPECT_CONTAINS(str, std::format("size: {},{}", SIZE, SIZE));
|
EXPECT_CONTAINS(str, std::format("size: {},{}", SIZE, SIZE));
|
||||||
EXPECT_NOT_CONTAINS(str, "pinned: 1");
|
EXPECT_NOT_CONTAINS(str, "pinned: 1");
|
||||||
OK(getFromSocket("/keyword windowrule plugin:someplugin:variable, class:wr_kitty"));
|
}
|
||||||
OK(getFromSocket("/keyword windowrule plugin:someplugin:variable 10, class:wr_kitty"));
|
|
||||||
OK(getFromSocket("/keyword windowrule workspace 1, class:wr_kitty"));
|
OK(getFromSocket("/keyword windowrule[wr-kitty-stuff]:opacity 0.5 0.5 override"));
|
||||||
OK(getFromSocket("/keyword windowrule workspace special:magic, class:magic_kitty"));
|
|
||||||
|
{
|
||||||
|
auto str = getFromSocket("/getprop active opacity");
|
||||||
|
EXPECT_CONTAINS(str, "0.5");
|
||||||
|
}
|
||||||
|
|
||||||
|
OK(getFromSocket("/keyword windowrule[special-magic-kitty]:match:class magic_kitty"));
|
||||||
|
OK(getFromSocket("/keyword windowrule[special-magic-kitty]:workspace special:magic"));
|
||||||
|
|
||||||
if (!spawnKitty("magic_kitty"))
|
if (!spawnKitty("magic_kitty"))
|
||||||
return false;
|
return false;
|
||||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "special:magic");
|
|
||||||
|
{
|
||||||
|
auto str = getFromSocket("/activewindow");
|
||||||
|
EXPECT_CONTAINS(str, "special:magic");
|
||||||
EXPECT_NOT_CONTAINS(str, "workspace: 9");
|
EXPECT_NOT_CONTAINS(str, "workspace: 9");
|
||||||
}
|
}
|
||||||
|
|
||||||
NLog::log("{}Testing faulty rules", Colors::YELLOW);
|
if (auto str = getFromSocket("/monitors"); str.contains("magic)")) {
|
||||||
{
|
OK(getFromSocket("/dispatch togglespecialworkspace magic"));
|
||||||
const auto PARAM = "Invalid parameter";
|
|
||||||
const auto RULE = "Invalid value";
|
|
||||||
const auto NORULE = "no rules provided";
|
|
||||||
EXPECT_CONTAINS(getFromSocket("/keyword windowrule notarule, class:wr_kitty"), RULE)
|
|
||||||
EXPECT_CONTAINS(getFromSocket("/keyword windowrule class:wr_kitty"), NORULE)
|
|
||||||
EXPECT_CONTAINS(getFromSocket("/keyword windowrule float, class:wr_kitty, size"), PARAM)
|
|
||||||
EXPECT_CONTAINS(getFromSocket("/keyword windowrule float, classI:wr_kitty"), PARAM)
|
|
||||||
EXPECT_CONTAINS(getFromSocket("/keyword windowrule workspace:, class:wr_kitty"), NORULE)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tests::killAllWindows();
|
||||||
|
|
||||||
|
if (!spawnKitty("tag_kitty"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto str = getFromSocket("/activewindow");
|
||||||
|
EXPECT_CONTAINS(str, "floating: 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
OK(getFromSocket("/reload"));
|
||||||
|
Tests::killAllWindows();
|
||||||
|
|
||||||
|
// test rules that overlap effects but don't overlap props
|
||||||
|
OK(getFromSocket("/keyword windowrule match:class overlap_kitty, border_size 0"));
|
||||||
|
OK(getFromSocket("/keyword windowrule match:fullscreen false, border_size 10"));
|
||||||
|
|
||||||
|
if (!spawnKitty("overlap_kitty"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto str = getFromSocket("/getprop active border_size");
|
||||||
|
EXPECT_CONTAINS(str, "10");
|
||||||
|
}
|
||||||
|
|
||||||
|
OK(getFromSocket("/reload"));
|
||||||
|
Tests::killAllWindows();
|
||||||
|
|
||||||
|
OK(getFromSocket("/keyword general:border_size 0"));
|
||||||
|
OK(getFromSocket("/keyword windowrule match:float true, border_size 10"));
|
||||||
|
|
||||||
|
if (!spawnKitty("border_kitty"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto str = getFromSocket("/getprop active border_size");
|
||||||
|
EXPECT_CONTAINS(str, "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
OK(getFromSocket("/dispatch togglefloating"));
|
||||||
|
|
||||||
|
{
|
||||||
|
auto str = getFromSocket("/getprop active border_size");
|
||||||
|
EXPECT_CONTAINS(str, "10");
|
||||||
|
}
|
||||||
|
|
||||||
|
OK(getFromSocket("/dispatch togglefloating"));
|
||||||
|
|
||||||
|
{
|
||||||
|
auto str = getFromSocket("/getprop active border_size");
|
||||||
|
EXPECT_CONTAINS(str, "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
OK(getFromSocket("/reload"));
|
||||||
|
Tests::killAllWindows();
|
||||||
|
|
||||||
|
// test expression rules
|
||||||
|
OK(getFromSocket("/keyword windowrule match:class expr_kitty, float yes, size monitor_w*0.5 monitor_h*0.5, move 20+(monitor_w*0.1) monitor_h*0.5"));
|
||||||
|
|
||||||
|
if (!spawnKitty("expr_kitty"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto str = getFromSocket("/activewindow");
|
||||||
|
EXPECT_CONTAINS(str, "floating: 1");
|
||||||
|
EXPECT_CONTAINS(str, "at: 212,540");
|
||||||
|
EXPECT_CONTAINS(str, "size: 960,540");
|
||||||
|
}
|
||||||
|
|
||||||
|
OK(getFromSocket("/reload"));
|
||||||
|
Tests::killAllWindows();
|
||||||
|
|
||||||
|
OK(getFromSocket("/dispatch plugin:test:add_rule"));
|
||||||
|
OK(getFromSocket("/reload"));
|
||||||
|
|
||||||
|
OK(getFromSocket("/keyword windowrule match:class plugin_kitty, plugin_rule effect"));
|
||||||
|
|
||||||
|
if (!spawnKitty("plugin_kitty"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
OK(getFromSocket("/dispatch plugin:test:check_rule"));
|
||||||
|
|
||||||
|
OK(getFromSocket("/reload"));
|
||||||
|
Tests::killAllWindows();
|
||||||
|
|
||||||
|
OK(getFromSocket("/dispatch plugin:test:add_rule"));
|
||||||
|
OK(getFromSocket("/reload"));
|
||||||
|
|
||||||
|
OK(getFromSocket("/keyword windowrule[test-plugin-rule]:match:class plugin_kitty"));
|
||||||
|
OK(getFromSocket("/keyword windowrule[test-plugin-rule]:plugin_rule effect"));
|
||||||
|
|
||||||
|
if (!spawnKitty("plugin_kitty"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
OK(getFromSocket("/dispatch plugin:test:check_rule"));
|
||||||
|
|
||||||
NLog::log("{}Reloading config", Colors::YELLOW);
|
NLog::log("{}Reloading config", Colors::YELLOW);
|
||||||
OK(getFromSocket("/reload"));
|
OK(getFromSocket("/reload"));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <hyprutils/os/Process.hpp>
|
#include <hyprutils/os/Process.hpp>
|
||||||
#include <hyprutils/memory/WeakPtr.hpp>
|
#include <hyprutils/memory/WeakPtr.hpp>
|
||||||
#include <hyprutils/utils/ScopeGuard.hpp>
|
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include "../shared.hpp"
|
#include "../shared.hpp"
|
||||||
|
|
@ -15,7 +14,6 @@ static int ret = 0;
|
||||||
|
|
||||||
using namespace Hyprutils::OS;
|
using namespace Hyprutils::OS;
|
||||||
using namespace Hyprutils::Memory;
|
using namespace Hyprutils::Memory;
|
||||||
using namespace Hyprutils::Utils;
|
|
||||||
|
|
||||||
#define UP CUniquePointer
|
#define UP CUniquePointer
|
||||||
#define SP CSharedPointer
|
#define SP CSharedPointer
|
||||||
|
|
@ -27,7 +25,7 @@ static bool test() {
|
||||||
|
|
||||||
// test on workspace "window"
|
// test on workspace "window"
|
||||||
NLog::log("{}Switching to workspace 1", Colors::YELLOW);
|
NLog::log("{}Switching to workspace 1", Colors::YELLOW);
|
||||||
OK(getFromSocket("/dispatch workspace 1"));
|
getFromSocket("/dispatch workspace 1");
|
||||||
|
|
||||||
NLog::log("{}Checking persistent no-mon", Colors::YELLOW);
|
NLog::log("{}Checking persistent no-mon", Colors::YELLOW);
|
||||||
OK(getFromSocket("r/keyword workspace 966,persistent:1"));
|
OK(getFromSocket("r/keyword workspace 966,persistent:1"));
|
||||||
|
|
@ -361,95 +359,6 @@ static bool test() {
|
||||||
NLog::log("{}Killing all windows", Colors::YELLOW);
|
NLog::log("{}Killing all windows", Colors::YELLOW);
|
||||||
Tests::killAllWindows();
|
Tests::killAllWindows();
|
||||||
|
|
||||||
NLog::log("{}Testing asymmetric gap splits", Colors::YELLOW);
|
|
||||||
{
|
|
||||||
|
|
||||||
CScopeGuard guard = {[&]() {
|
|
||||||
NLog::log("{}Cleaning up asymmetric gap test", Colors::YELLOW);
|
|
||||||
Tests::killAllWindows();
|
|
||||||
OK(getFromSocket("/reload"));
|
|
||||||
}};
|
|
||||||
|
|
||||||
OK(getFromSocket("/dispatch workspace name:gap_split_test"));
|
|
||||||
OK(getFromSocket("r/keyword general:gaps_in 0"));
|
|
||||||
OK(getFromSocket("r/keyword general:border_size 0"));
|
|
||||||
OK(getFromSocket("r/keyword dwindle:split_width_multiplier 1.0"));
|
|
||||||
OK(getFromSocket("r/keyword workspace name:gap_split_test,gapsout:0 1000 0 0"));
|
|
||||||
|
|
||||||
NLog::log("{}Testing default split (force_split = 0)", Colors::YELLOW);
|
|
||||||
OK(getFromSocket("r/keyword dwindle:force_split 0"));
|
|
||||||
|
|
||||||
if (!Tests::spawnKitty("gaps_kitty_A") || !Tests::spawnKitty("gaps_kitty_B")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
NLog::log("{}Expecting vertical split (B below A)", Colors::YELLOW);
|
|
||||||
OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_A"));
|
|
||||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 0,0");
|
|
||||||
OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_B"));
|
|
||||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 0,540");
|
|
||||||
|
|
||||||
Tests::killAllWindows();
|
|
||||||
EXPECT(Tests::windowCount(), 0);
|
|
||||||
|
|
||||||
NLog::log("{}Testing force_split = 1", Colors::YELLOW);
|
|
||||||
OK(getFromSocket("r/keyword dwindle:force_split 1"));
|
|
||||||
|
|
||||||
if (!Tests::spawnKitty("gaps_kitty_A") || !Tests::spawnKitty("gaps_kitty_B")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
NLog::log("{}Expecting vertical split (B above A)", Colors::YELLOW);
|
|
||||||
OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_B"));
|
|
||||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 0,0");
|
|
||||||
OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_A"));
|
|
||||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 0,540");
|
|
||||||
|
|
||||||
NLog::log("{}Expecting horizontal split (C left of B)", Colors::YELLOW);
|
|
||||||
OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_B"));
|
|
||||||
|
|
||||||
if (!Tests::spawnKitty("gaps_kitty_C")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_C"));
|
|
||||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 0,0");
|
|
||||||
OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_B"));
|
|
||||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 460,0");
|
|
||||||
|
|
||||||
Tests::killAllWindows();
|
|
||||||
EXPECT(Tests::windowCount(), 0);
|
|
||||||
|
|
||||||
NLog::log("{}Testing force_split = 2", Colors::YELLOW);
|
|
||||||
OK(getFromSocket("r/keyword dwindle:force_split 2"));
|
|
||||||
|
|
||||||
if (!Tests::spawnKitty("gaps_kitty_A") || !Tests::spawnKitty("gaps_kitty_B")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
NLog::log("{}Expecting vertical split (B below A)", Colors::YELLOW);
|
|
||||||
OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_A"));
|
|
||||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 0,0");
|
|
||||||
OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_B"));
|
|
||||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 0,540");
|
|
||||||
|
|
||||||
NLog::log("{}Expecting horizontal split (C right of A)", Colors::YELLOW);
|
|
||||||
OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_A"));
|
|
||||||
|
|
||||||
if (!Tests::spawnKitty("gaps_kitty_C")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_A"));
|
|
||||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 0,0");
|
|
||||||
OK(getFromSocket("/dispatch focuswindow class:gaps_kitty_C"));
|
|
||||||
EXPECT_CONTAINS(getFromSocket("/activewindow"), "at: 460,0");
|
|
||||||
}
|
|
||||||
|
|
||||||
// kill all
|
|
||||||
NLog::log("{}Killing all windows", Colors::YELLOW);
|
|
||||||
Tests::killAllWindows();
|
|
||||||
|
|
||||||
NLog::log("{}Expecting 0 windows", Colors::YELLOW);
|
NLog::log("{}Expecting 0 windows", Colors::YELLOW);
|
||||||
EXPECT(Tests::windowCount(), 0);
|
EXPECT(Tests::windowCount(), 0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -318,28 +318,70 @@ submap = reset
|
||||||
### WINDOWS AND WORKSPACES ###
|
### WINDOWS AND WORKSPACES ###
|
||||||
##############################
|
##############################
|
||||||
|
|
||||||
# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
|
windowrule {
|
||||||
# See https://wiki.hyprland.org/Configuring/Workspace-Rules/ for workspace rules
|
# Ignore maximize requests from apps. You'll probably like this.
|
||||||
|
name = suppress-maximize-events
|
||||||
|
match:class = .*
|
||||||
|
|
||||||
# Example windowrule v1
|
suppress_event = maximize
|
||||||
# windowrule = float, ^(kitty)$
|
}
|
||||||
|
|
||||||
# Example windowrule v2
|
windowrule {
|
||||||
# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
|
# Fix some dragging issues with XWayland
|
||||||
|
name = fix-xwayland-drags
|
||||||
|
match:class = ^$
|
||||||
|
match:title = ^$
|
||||||
|
match:xwayland = true
|
||||||
|
match:float = true
|
||||||
|
match:fullscreen = false
|
||||||
|
match:pin = false
|
||||||
|
|
||||||
# Ignore maximize requests from apps. You'll probably like this.
|
no_focus = true
|
||||||
windowrulev2 = suppressevent maximize, class:.*
|
}
|
||||||
|
|
||||||
# Fix some dragging issues with XWayland
|
|
||||||
windowrulev2 = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0
|
|
||||||
|
|
||||||
# Workspace "windows" is a smart gaps one
|
|
||||||
workspace = n[s:window] w[tv1], gapsout:0, gapsin:0
|
workspace = n[s:window] w[tv1], gapsout:0, gapsin:0
|
||||||
workspace = n[s:window] f[1], gapsout:0, gapsin:0
|
workspace = n[s:window] f[1], gapsout:0, gapsin:0
|
||||||
windowrulev2 = bordersize 0, floating:0, onworkspace:n[s:window] w[tv1]
|
|
||||||
windowrulev2 = rounding 0, floating:0, onworkspace:n[s:window] w[tv1]
|
windowrule {
|
||||||
windowrulev2 = bordersize 0, floating:0, onworkspace:n[s:window] f[1]
|
name = smart-gaps-1
|
||||||
windowrulev2 = rounding 0, floating:0, onworkspace:n[s:window] f[1]
|
match:float = false
|
||||||
|
match:workspace = n[s:window] w[tv1]
|
||||||
|
|
||||||
|
border_size = 0
|
||||||
|
rounding = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
windowrule {
|
||||||
|
name = smart-gaps-2
|
||||||
|
match:float = false
|
||||||
|
match:workspace = n[s:window] f[1]
|
||||||
|
|
||||||
|
border_size = 0
|
||||||
|
rounding = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
windowrule {
|
||||||
|
name = wr-kitty-stuff
|
||||||
|
match:class = wr_kitty
|
||||||
|
|
||||||
|
float = true
|
||||||
|
size = 200 200
|
||||||
|
pin = false
|
||||||
|
}
|
||||||
|
|
||||||
|
windowrule {
|
||||||
|
name = tagged-kitty-floats
|
||||||
|
match:tag = tag_kitty
|
||||||
|
|
||||||
|
float = true
|
||||||
|
}
|
||||||
|
|
||||||
|
windowrule {
|
||||||
|
name = static-kitty-tag
|
||||||
|
match:class = tag_kitty
|
||||||
|
|
||||||
|
tag = +tag_kitty
|
||||||
|
}
|
||||||
|
|
||||||
gesture = 3, left, dispatcher, exec, kitty
|
gesture = 3, left, dispatcher, exec, kitty
|
||||||
gesture = 3, right, float
|
gesture = 3, right, float
|
||||||
|
|
@ -356,7 +398,3 @@ gesture = 5, left, dispatcher, sendshortcut, , i, activewindow
|
||||||
gesture = 5, right, dispatcher, sendshortcut, , t, activewindow
|
gesture = 5, right, dispatcher, sendshortcut, , t, activewindow
|
||||||
gesture = 4, right, dispatcher, sendshortcut, , return, activewindow
|
gesture = 4, right, dispatcher, sendshortcut, , return, activewindow
|
||||||
gesture = 4, left, dispatcher, movecursortocorner, 1
|
gesture = 4, left, dispatcher, movecursortocorner, 1
|
||||||
|
|
||||||
windowrule = float, pin, class:wr_kitty
|
|
||||||
windowrule = size 200 200, class:wr_kitty
|
|
||||||
windowrule = unset pin, class:wr_kitty
|
|
||||||
|
|
|
||||||
151
meson.build
151
meson.build
|
|
@ -1,151 +0,0 @@
|
||||||
project(
|
|
||||||
'Hyprland',
|
|
||||||
'cpp',
|
|
||||||
'c',
|
|
||||||
version: run_command('cat', join_paths(meson.project_source_root(), 'VERSION'), check: true).stdout().strip(),
|
|
||||||
default_options: [
|
|
||||||
'warning_level=2',
|
|
||||||
'default_library=static',
|
|
||||||
'optimization=3',
|
|
||||||
'buildtype=release',
|
|
||||||
'debug=false',
|
|
||||||
'b_lto=false',
|
|
||||||
'cpp_std=c++26',
|
|
||||||
],
|
|
||||||
meson_version: '>= 1.1.0',
|
|
||||||
)
|
|
||||||
|
|
||||||
datarootdir = '-DDATAROOTDIR="' + get_option('prefix') / get_option('datadir') + '"'
|
|
||||||
add_project_arguments(
|
|
||||||
[
|
|
||||||
'-Wno-unused-parameter',
|
|
||||||
'-Wno-unused-value',
|
|
||||||
'-Wno-missing-field-initializers',
|
|
||||||
'-Wno-narrowing',
|
|
||||||
'-Wno-pointer-arith',
|
|
||||||
datarootdir,
|
|
||||||
'-DHYPRLAND_VERSION="' + meson.project_version() + '"',
|
|
||||||
],
|
|
||||||
language: 'cpp',
|
|
||||||
)
|
|
||||||
|
|
||||||
cpp_compiler = meson.get_compiler('cpp')
|
|
||||||
if cpp_compiler.check_header('execinfo.h')
|
|
||||||
add_project_arguments('-DHAS_EXECINFO', language: 'cpp')
|
|
||||||
endif
|
|
||||||
|
|
||||||
aquamarine = dependency('aquamarine', version: '>=0.9.3')
|
|
||||||
hyprcursor = dependency('hyprcursor', version: '>=0.1.7')
|
|
||||||
hyprgraphics = dependency('hyprgraphics', version: '>=0.1.6')
|
|
||||||
hyprlang = dependency('hyprlang', version: '>=0.3.2')
|
|
||||||
hyprutils = dependency('hyprutils', version: '>=0.8.2')
|
|
||||||
|
|
||||||
aq_ver_list = aquamarine.version().split('.')
|
|
||||||
git = find_program('git', required: false)
|
|
||||||
|
|
||||||
if git.found()
|
|
||||||
git_hash = run_command(git, 'rev-parse', 'HEAD').stdout().strip()
|
|
||||||
git_branch = run_command(git, 'branch', '--show-current').stdout().strip()
|
|
||||||
git_message = run_command(git, 'show', '-s', '--format=%s').stdout().strip()
|
|
||||||
git_date = run_command(git, 'show', '-s', '--format=%cd', '--date=local').stdout().strip()
|
|
||||||
git_dirty = run_command(git, 'diff-index', '--quiet', 'HEAD', '--', check: false).returncode() != 0 ? 'dirty' : 'clean'
|
|
||||||
git_tag = run_command(git, 'describe', '--tags').stdout().strip()
|
|
||||||
git_commits = run_command(git, 'rev-list', '--count', 'HEAD').stdout().strip()
|
|
||||||
else
|
|
||||||
git_hash = 'unknown'
|
|
||||||
git_branch = 'unknown'
|
|
||||||
git_message = 'unknown'
|
|
||||||
git_date = 'unknown'
|
|
||||||
git_dirty = 'unknown'
|
|
||||||
git_tag = 'unknown'
|
|
||||||
git_commits = '0'
|
|
||||||
endif
|
|
||||||
|
|
||||||
cfg = configuration_data()
|
|
||||||
cfg.set('GIT_COMMIT_HASH', git_hash)
|
|
||||||
cfg.set('GIT_BRANCH', git_branch)
|
|
||||||
cfg.set('GIT_COMMIT_MESSAGE', git_message)
|
|
||||||
cfg.set('GIT_COMMIT_DATE', git_date)
|
|
||||||
cfg.set('GIT_DIRTY', git_dirty)
|
|
||||||
cfg.set('GIT_TAG', git_tag)
|
|
||||||
cfg.set('GIT_COMMITS', git_commits)
|
|
||||||
cfg.set('AQUAMARINE_VERSION', aquamarine.version())
|
|
||||||
cfg.set('AQUAMARINE_VERSION_MAJOR', aq_ver_list[0])
|
|
||||||
cfg.set('AQUAMARINE_VERSION_MINOR', aq_ver_list[1])
|
|
||||||
cfg.set('AQUAMARINE_VERSION_PATCH', aq_ver_list[2])
|
|
||||||
cfg.set('HYPRLANG_VERSION', hyprlang.version())
|
|
||||||
cfg.set('HYPRUTILS_VERSION', hyprutils.version())
|
|
||||||
cfg.set('HYPRCURSOR_VERSION', hyprcursor.version())
|
|
||||||
cfg.set('HYPRGRAPHICS_VERSION', hyprgraphics.version())
|
|
||||||
|
|
||||||
version_h = configure_file(
|
|
||||||
input: 'src/version.h.in',
|
|
||||||
output: 'version.h',
|
|
||||||
configuration: cfg
|
|
||||||
)
|
|
||||||
|
|
||||||
install_headers(version_h, subdir: 'hyprland/src')
|
|
||||||
|
|
||||||
xcb_dep = dependency('xcb', 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_icccm_dep = dependency('xcb-icccm', required: get_option('xwayland'))
|
|
||||||
xcb_render_dep = dependency('xcb-render', required: get_option('xwayland'))
|
|
||||||
xcb_res_dep = dependency('xcb-res', required: get_option('xwayland'))
|
|
||||||
xcb_xfixes_dep = dependency('xcb-xfixes', required: get_option('xwayland'))
|
|
||||||
gio_dep = dependency('gio-2.0', required: true)
|
|
||||||
|
|
||||||
if not xcb_dep.found()
|
|
||||||
add_project_arguments('-DNO_XWAYLAND', language: 'cpp')
|
|
||||||
endif
|
|
||||||
|
|
||||||
backtrace_dep = cpp_compiler.find_library('execinfo', required: false)
|
|
||||||
epoll_dep = dependency('epoll-shim', required: false)
|
|
||||||
inotify_dep = dependency('libinotify', required: false)
|
|
||||||
re2 = dependency('re2', required: true)
|
|
||||||
|
|
||||||
systemd_option = get_option('systemd')
|
|
||||||
systemd = dependency('systemd', required: systemd_option)
|
|
||||||
systemd_option.enable_auto_if(systemd.found())
|
|
||||||
if (systemd_option.enabled())
|
|
||||||
add_project_arguments('-DUSES_SYSTEMD', language: 'cpp')
|
|
||||||
subdir('systemd')
|
|
||||||
endif
|
|
||||||
|
|
||||||
if get_option('buildtype') == 'debug'
|
|
||||||
add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp')
|
|
||||||
endif
|
|
||||||
|
|
||||||
run_command('sh', '-c', 'scripts/generateShaderIncludes.sh', check: true)
|
|
||||||
|
|
||||||
globber = run_command('find', 'src', '-name', '*.h*', '-o', '-name', '*.inc', check: true)
|
|
||||||
headers = globber.stdout().strip().split('\n')
|
|
||||||
foreach file : headers
|
|
||||||
install_headers(file, subdir: 'hyprland', preserve_path: true)
|
|
||||||
endforeach
|
|
||||||
install_headers(version_h, subdir: 'src')
|
|
||||||
|
|
||||||
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('src')
|
|
||||||
subdir('hyprctl')
|
|
||||||
subdir('assets')
|
|
||||||
subdir('example')
|
|
||||||
subdir('docs')
|
|
||||||
if get_option('hyprpm').enabled()
|
|
||||||
subdir('hyprpm/src')
|
|
||||||
endif
|
|
||||||
|
|
||||||
pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig')
|
|
||||||
import('pkgconfig').generate(
|
|
||||||
name: 'Hyprland',
|
|
||||||
filebase: 'hyprland',
|
|
||||||
url: 'https://github.com/hyprwm/Hyprland',
|
|
||||||
description: 'Hyprland header files',
|
|
||||||
install_dir: pkg_install_dir,
|
|
||||||
subdirs: ['', 'hyprland/protocols', 'hyprland'],
|
|
||||||
)
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
option('xwayland', type: 'feature', value: 'auto', description: 'Enable support for X11 applications')
|
|
||||||
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('hyprpm', type: 'feature', value: 'enabled', description: 'Enable hyprpm')
|
|
||||||
option('tracy_enable', type: 'boolean', value: false , description: 'Enable profiling')
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
libxkbcommon,
|
libxkbcommon,
|
||||||
libuuid,
|
libuuid,
|
||||||
libgbm,
|
libgbm,
|
||||||
|
muparser,
|
||||||
pango,
|
pango,
|
||||||
pciutils,
|
pciutils,
|
||||||
re2,
|
re2,
|
||||||
|
|
@ -45,12 +46,12 @@
|
||||||
commit,
|
commit,
|
||||||
revCount,
|
revCount,
|
||||||
date,
|
date,
|
||||||
withHyprtester ? false,
|
|
||||||
# deprecated flags
|
# deprecated flags
|
||||||
enableNvidiaPatches ? false,
|
enableNvidiaPatches ? false,
|
||||||
nvidiaPatches ? false,
|
nvidiaPatches ? false,
|
||||||
hidpiXWayland ? false,
|
hidpiXWayland ? false,
|
||||||
legacyRenderer ? false,
|
legacyRenderer ? false,
|
||||||
|
withHyprtester ? false,
|
||||||
}: let
|
}: let
|
||||||
inherit (builtins) foldl' readFile;
|
inherit (builtins) foldl' readFile;
|
||||||
inherit (lib.asserts) assertMsg;
|
inherit (lib.asserts) assertMsg;
|
||||||
|
|
@ -70,6 +71,7 @@ in
|
||||||
assert assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` 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.hypr.land/Configuring/XWayland";
|
assert assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hypr.land/Configuring/XWayland";
|
||||||
assert assertMsg (!legacyRenderer) "The option `legacyRenderer` has been removed. Legacy renderer is no longer supported.";
|
assert assertMsg (!legacyRenderer) "The option `legacyRenderer` has been removed. Legacy renderer is no longer supported.";
|
||||||
|
assert assertMsg (!withHyprtester) "The option `withHyprtester` has been removed. Hyprtester is always built now.";
|
||||||
customStdenv.mkDerivation (finalAttrs: {
|
customStdenv.mkDerivation (finalAttrs: {
|
||||||
pname = "hyprland${optionalString debug "-debug"}";
|
pname = "hyprland${optionalString debug "-debug"}";
|
||||||
inherit version;
|
inherit version;
|
||||||
|
|
@ -85,6 +87,7 @@ in
|
||||||
../assets/install
|
../assets/install
|
||||||
../hyprctl
|
../hyprctl
|
||||||
../hyprland.pc.in
|
../hyprland.pc.in
|
||||||
|
../hyprtester
|
||||||
../LICENSE
|
../LICENSE
|
||||||
../protocols
|
../protocols
|
||||||
../src
|
../src
|
||||||
|
|
@ -94,7 +97,6 @@ in
|
||||||
(fs.fileFilter (file: file.hasExt "conf" || file.hasExt "desktop") ../example)
|
(fs.fileFilter (file: file.hasExt "conf" || file.hasExt "desktop") ../example)
|
||||||
(fs.fileFilter (file: file.hasExt "sh") ../scripts)
|
(fs.fileFilter (file: file.hasExt "sh") ../scripts)
|
||||||
(fs.fileFilter (file: file.name == "CMakeLists.txt") ../.)
|
(fs.fileFilter (file: file.name == "CMakeLists.txt") ../.)
|
||||||
(optional withHyprtester ../hyprtester)
|
|
||||||
]));
|
]));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -106,11 +108,13 @@ in
|
||||||
sed -i "s#@PREFIX@/##g" hyprland.pc.in
|
sed -i "s#@PREFIX@/##g" hyprland.pc.in
|
||||||
'';
|
'';
|
||||||
|
|
||||||
COMMITS = revCount;
|
env = {
|
||||||
DATE = date;
|
GIT_COMMITS = revCount;
|
||||||
DIRTY = optionalString (commit == "") "dirty";
|
GIT_COMMIT_DATE = date;
|
||||||
HASH = commit;
|
GIT_COMMIT_HASH = commit;
|
||||||
TAG = "v${trim (readFile "${finalAttrs.src}/VERSION")}";
|
GIT_DIRTY = if (commit == "") then "clean" else "dirty";
|
||||||
|
GIT_TAG = "v${trim (readFile "${finalAttrs.src}/VERSION")}";
|
||||||
|
};
|
||||||
|
|
||||||
depsBuildBuild = [
|
depsBuildBuild = [
|
||||||
pkg-config
|
pkg-config
|
||||||
|
|
@ -146,6 +150,7 @@ in
|
||||||
libuuid
|
libuuid
|
||||||
libxkbcommon
|
libxkbcommon
|
||||||
libgbm
|
libgbm
|
||||||
|
muparser
|
||||||
pango
|
pango
|
||||||
pciutils
|
pciutils
|
||||||
re2
|
re2
|
||||||
|
|
@ -187,7 +192,7 @@ in
|
||||||
"NO_UWSM" = true;
|
"NO_UWSM" = true;
|
||||||
"NO_HYPRPM" = true;
|
"NO_HYPRPM" = true;
|
||||||
"TRACY_ENABLE" = false;
|
"TRACY_ENABLE" = false;
|
||||||
"BUILD_HYPRTESTER" = withHyprtester;
|
"BUILD_HYPRTESTER" = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
preConfigure = ''
|
preConfigure = ''
|
||||||
|
|
@ -206,7 +211,7 @@ in
|
||||||
pkgconf
|
pkgconf
|
||||||
]}
|
]}
|
||||||
''}
|
''}
|
||||||
'' + optionalString withHyprtester ''
|
|
||||||
install hyprtester/pointer-warp -t $out/bin
|
install hyprtester/pointer-warp -t $out/bin
|
||||||
install hyprtester/pointer-scroll -t $out/bin
|
install hyprtester/pointer-scroll -t $out/bin
|
||||||
'';
|
'';
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,12 @@ in {
|
||||||
};
|
};
|
||||||
hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;};
|
hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;};
|
||||||
|
|
||||||
hyprland-with-hyprtester = final.hyprland.override {withHyprtester = true;};
|
hyprland-with-hyprtester =
|
||||||
|
builtins.trace ''
|
||||||
|
hyprland-with-hyprtester was removed. Please use the hyprland package.
|
||||||
|
Hyprtester is always built now.
|
||||||
|
''
|
||||||
|
final.hyprland;
|
||||||
|
|
||||||
# deprecated packages
|
# deprecated packages
|
||||||
hyprland-legacy-renderer =
|
hyprland-legacy-renderer =
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
inputs: pkgs: let
|
inputs: pkgs: let
|
||||||
flake = inputs.self.packages.${pkgs.stdenv.hostPlatform.system};
|
flake = inputs.self.packages.${pkgs.stdenv.hostPlatform.system};
|
||||||
hyprland = flake.hyprland-with-hyprtester;
|
hyprland = flake.hyprland;
|
||||||
in {
|
in {
|
||||||
tests = pkgs.testers.runNixOSTest {
|
tests = pkgs.testers.runNixOSTest {
|
||||||
name = "hyprland-tests";
|
name = "hyprland-tests";
|
||||||
|
|
|
||||||
|
|
@ -1,119 +0,0 @@
|
||||||
wayland_protos = dependency(
|
|
||||||
'wayland-protocols',
|
|
||||||
version: '>=1.45',
|
|
||||||
fallback: 'wayland-protocols',
|
|
||||||
default_options: ['tests=false'],
|
|
||||||
)
|
|
||||||
|
|
||||||
hyprland_protos = dependency(
|
|
||||||
'hyprland-protocols',
|
|
||||||
version: '>=0.6.4',
|
|
||||||
fallback: 'hyprland-protocols',
|
|
||||||
)
|
|
||||||
|
|
||||||
wayland_protocol_dir = wayland_protos.get_variable('pkgdatadir')
|
|
||||||
hyprland_protocol_dir = hyprland_protos.get_variable('pkgdatadir')
|
|
||||||
|
|
||||||
hyprwayland_scanner_dep = dependency('hyprwayland-scanner', version: '>=0.3.10', native: true)
|
|
||||||
hyprwayland_scanner = find_program(
|
|
||||||
hyprwayland_scanner_dep.get_variable('hyprwayland_scanner'),
|
|
||||||
native: true,
|
|
||||||
)
|
|
||||||
|
|
||||||
protocols = [
|
|
||||||
'wlr-gamma-control-unstable-v1.xml',
|
|
||||||
'wlr-foreign-toplevel-management-unstable-v1.xml',
|
|
||||||
'wlr-output-power-management-unstable-v1.xml',
|
|
||||||
'input-method-unstable-v2.xml',
|
|
||||||
'virtual-keyboard-unstable-v1.xml',
|
|
||||||
'wlr-virtual-pointer-unstable-v1.xml',
|
|
||||||
'wlr-output-management-unstable-v1.xml',
|
|
||||||
'kde-server-decoration.xml',
|
|
||||||
'wlr-layer-shell-unstable-v1.xml',
|
|
||||||
'wayland-drm.xml',
|
|
||||||
'wlr-data-control-unstable-v1.xml',
|
|
||||||
'wlr-screencopy-unstable-v1.xml',
|
|
||||||
'xx-color-management-v4.xml',
|
|
||||||
'frog-color-management-v1.xml',
|
|
||||||
hyprland_protocol_dir / 'protocols/hyprland-global-shortcuts-v1.xml',
|
|
||||||
hyprland_protocol_dir / 'protocols/hyprland-toplevel-export-v1.xml',
|
|
||||||
hyprland_protocol_dir / 'protocols/hyprland-toplevel-mapping-v1.xml',
|
|
||||||
hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml',
|
|
||||||
hyprland_protocol_dir / 'protocols/hyprland-ctm-control-v1.xml',
|
|
||||||
hyprland_protocol_dir / 'protocols/hyprland-surface-v1.xml',
|
|
||||||
hyprland_protocol_dir / 'protocols/hyprland-lock-notify-v1.xml',
|
|
||||||
wayland_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',
|
|
||||||
wayland_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml',
|
|
||||||
wayland_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
|
|
||||||
wayland_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml',
|
|
||||||
wayland_protocol_dir / 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml',
|
|
||||||
wayland_protocol_dir / 'unstable/relative-pointer/relative-pointer-unstable-v1.xml',
|
|
||||||
wayland_protocol_dir / 'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml',
|
|
||||||
wayland_protocol_dir / 'staging/alpha-modifier/alpha-modifier-v1.xml',
|
|
||||||
wayland_protocol_dir / 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml',
|
|
||||||
wayland_protocol_dir / 'unstable/pointer-gestures/pointer-gestures-unstable-v1.xml',
|
|
||||||
wayland_protocol_dir / 'unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml',
|
|
||||||
wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v3.xml',
|
|
||||||
wayland_protocol_dir / 'unstable/text-input/text-input-unstable-v1.xml',
|
|
||||||
wayland_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml',
|
|
||||||
wayland_protocol_dir / 'staging/xdg-activation/xdg-activation-v1.xml',
|
|
||||||
wayland_protocol_dir / 'staging/ext-idle-notify/ext-idle-notify-v1.xml',
|
|
||||||
wayland_protocol_dir / 'staging/ext-session-lock/ext-session-lock-v1.xml',
|
|
||||||
wayland_protocol_dir / 'stable/tablet/tablet-v2.xml',
|
|
||||||
wayland_protocol_dir / 'stable/presentation-time/presentation-time.xml',
|
|
||||||
wayland_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
|
|
||||||
wayland_protocol_dir / 'unstable/primary-selection/primary-selection-unstable-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',
|
|
||||||
wayland_protocol_dir / 'staging/content-type/content-type-v1.xml',
|
|
||||||
wayland_protocol_dir / 'staging/color-management/color-management-v1.xml',
|
|
||||||
wayland_protocol_dir / 'staging/xdg-toplevel-tag/xdg-toplevel-tag-v1.xml',
|
|
||||||
wayland_protocol_dir / 'staging/xdg-system-bell/xdg-system-bell-v1.xml',
|
|
||||||
wayland_protocol_dir / 'staging/ext-workspace/ext-workspace-v1.xml',
|
|
||||||
wayland_protocol_dir / 'staging/ext-data-control/ext-data-control-v1.xml',
|
|
||||||
wayland_protocol_dir / 'staging/pointer-warp/pointer-warp-v1.xml',
|
|
||||||
wayland_protocol_dir / 'staging/fifo/fifo-v1.xml',
|
|
||||||
wayland_protocol_dir / 'staging/commit-timing/commit-timing-v1.xml',
|
|
||||||
]
|
|
||||||
|
|
||||||
wl_protocols = []
|
|
||||||
foreach protocol : protocols
|
|
||||||
wl_protocols += custom_target(
|
|
||||||
protocol.underscorify(),
|
|
||||||
input: protocol,
|
|
||||||
install: true,
|
|
||||||
install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
|
|
||||||
output: ['@BASENAME@.cpp', '@BASENAME@.hpp'],
|
|
||||||
command: [hyprwayland_scanner, '@INPUT@', '@OUTDIR@'],
|
|
||||||
)
|
|
||||||
endforeach
|
|
||||||
|
|
||||||
# wayland.xml generation
|
|
||||||
wayland_scanner = dependency('wayland-scanner', native: true)
|
|
||||||
wayland_scanner_datadir = wayland_scanner.get_variable('pkgdatadir')
|
|
||||||
|
|
||||||
wayland_xml = wayland_scanner_datadir / 'wayland.xml'
|
|
||||||
wayland_protocol = custom_target(
|
|
||||||
wayland_xml.underscorify(),
|
|
||||||
input: wayland_xml,
|
|
||||||
install: true,
|
|
||||||
install_dir: [false, join_paths(get_option('includedir'), 'hyprland/protocols')],
|
|
||||||
output: ['@BASENAME@.cpp', '@BASENAME@.hpp'],
|
|
||||||
command: [hyprwayland_scanner, '--wayland-enums', '@INPUT@', '@OUTDIR@'],
|
|
||||||
)
|
|
||||||
|
|
||||||
lib_server_protos = static_library(
|
|
||||||
'server_protos',
|
|
||||||
wl_protocols + wayland_protocol,
|
|
||||||
)
|
|
||||||
|
|
||||||
server_protos = declare_dependency(
|
|
||||||
link_with: lib_server_protos,
|
|
||||||
sources: wl_protocols + wayland_protocol,
|
|
||||||
)
|
|
||||||
|
|
@ -65,6 +65,7 @@
|
||||||
#include "debug/HyprNotificationOverlay.hpp"
|
#include "debug/HyprNotificationOverlay.hpp"
|
||||||
#include "debug/HyprDebugOverlay.hpp"
|
#include "debug/HyprDebugOverlay.hpp"
|
||||||
#include "helpers/MonitorFrameScheduler.hpp"
|
#include "helpers/MonitorFrameScheduler.hpp"
|
||||||
|
#include "i18n/Engine.hpp"
|
||||||
|
|
||||||
#include <hyprutils/string/String.hpp>
|
#include <hyprutils/string/String.hpp>
|
||||||
#include <aquamarine/input/Input.hpp>
|
#include <aquamarine/input/Input.hpp>
|
||||||
|
|
@ -900,8 +901,8 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
|
||||||
if (ONLY_PRIORITY && !w->priorityFocus())
|
if (ONLY_PRIORITY && !w->priorityFocus())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (w->m_isFloating && w->m_isMapped && !w->isHidden() && !w->m_X11ShouldntFocus && w->m_pinned && !w->m_windowData.noFocus.valueOrDefault() && w != pIgnoreWindow &&
|
if (w->m_isFloating && w->m_isMapped && !w->isHidden() && !w->m_X11ShouldntFocus && w->m_pinned && !w->m_ruleApplicator->noFocus().valueOrDefault() &&
|
||||||
!isShadowedByModal(w)) {
|
w != pIgnoreWindow && !isShadowedByModal(w)) {
|
||||||
const auto BB = w->getWindowBoxUnified(properties);
|
const auto BB = w->getWindowBoxUnified(properties);
|
||||||
CBox box = BB.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0);
|
CBox box = BB.copy().expand(!w->isX11OverrideRedirect() ? BORDER_GRAB_AREA : 0);
|
||||||
if (box.containsPoint(g_pPointerManager->position()))
|
if (box.containsPoint(g_pPointerManager->position()))
|
||||||
|
|
@ -938,7 +939,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w->m_isFloating && w->m_isMapped && w->m_workspace->isVisible() && !w->isHidden() && !w->m_pinned && !w->m_windowData.noFocus.valueOrDefault() &&
|
if (w->m_isFloating && w->m_isMapped && w->m_workspace->isVisible() && !w->isHidden() && !w->m_pinned && !w->m_ruleApplicator->noFocus().valueOrDefault() &&
|
||||||
w != pIgnoreWindow && (!aboveFullscreen || w->m_createdOverFullscreen) && !isShadowedByModal(w)) {
|
w != pIgnoreWindow && (!aboveFullscreen || w->m_createdOverFullscreen) && !isShadowedByModal(w)) {
|
||||||
// OR windows should add focus to parent
|
// OR windows should add focus to parent
|
||||||
if (w->m_X11ShouldntFocus && !w->isX11OverrideRedirect())
|
if (w->m_X11ShouldntFocus && !w->isX11OverrideRedirect())
|
||||||
|
|
@ -999,7 +1000,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!w->m_isX11 && !w->m_isFloating && w->m_isMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_X11ShouldntFocus &&
|
if (!w->m_isX11 && !w->m_isFloating && w->m_isMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_X11ShouldntFocus &&
|
||||||
!w->m_windowData.noFocus.valueOrDefault() && w != pIgnoreWindow && !isShadowedByModal(w)) {
|
!w->m_ruleApplicator->noFocus().valueOrDefault() && w != pIgnoreWindow && !isShadowedByModal(w)) {
|
||||||
if (w->hasPopupAt(pos))
|
if (w->hasPopupAt(pos))
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
@ -1015,7 +1016,7 @@ PHLWINDOW CCompositor::vectorToWindowUnified(const Vector2D& pos, uint8_t proper
|
||||||
if (!w->m_workspace)
|
if (!w->m_workspace)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!w->m_isFloating && w->m_isMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_X11ShouldntFocus && !w->m_windowData.noFocus.valueOrDefault() &&
|
if (!w->m_isFloating && w->m_isMapped && w->workspaceID() == WSPID && !w->isHidden() && !w->m_X11ShouldntFocus && !w->m_ruleApplicator->noFocus().valueOrDefault() &&
|
||||||
w != pIgnoreWindow && !isShadowedByModal(w)) {
|
w != pIgnoreWindow && !isShadowedByModal(w)) {
|
||||||
CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_position, w->m_size};
|
CBox box = (properties & USE_PROP_TILED) ? w->getWindowBoxUnified(properties) : CBox{w->m_position, w->m_size};
|
||||||
if (box.containsPoint(pos))
|
if (box.containsPoint(pos))
|
||||||
|
|
@ -1151,7 +1152,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface
|
||||||
m_lastWindow.reset();
|
m_lastWindow.reset();
|
||||||
|
|
||||||
if (PLASTWINDOW && PLASTWINDOW->m_isMapped) {
|
if (PLASTWINDOW && PLASTWINDOW->m_isMapped) {
|
||||||
updateWindowAnimatedDecorationValues(PLASTWINDOW);
|
PLASTWINDOW->updateDecorationValues();
|
||||||
|
|
||||||
g_pXWaylandManager->activateWindow(PLASTWINDOW, false);
|
g_pXWaylandManager->activateWindow(PLASTWINDOW, false);
|
||||||
}
|
}
|
||||||
|
|
@ -1171,7 +1172,7 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pWindow->m_windowData.noFocus.valueOrDefault()) {
|
if (pWindow->m_ruleApplicator->noFocus().valueOrDefault()) {
|
||||||
Debug::log(LOG, "Ignoring focus to nofocus window!");
|
Debug::log(LOG, "Ignoring focus to nofocus window!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1208,9 +1209,9 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface
|
||||||
|
|
||||||
// we need to make the PLASTWINDOW not equal to m_pLastWindow so that RENDERDATA is correct for an unfocused window
|
// we need to make the PLASTWINDOW not equal to m_pLastWindow so that RENDERDATA is correct for an unfocused window
|
||||||
if (PLASTWINDOW && PLASTWINDOW->m_isMapped) {
|
if (PLASTWINDOW && PLASTWINDOW->m_isMapped) {
|
||||||
PLASTWINDOW->updateDynamicRules();
|
PLASTWINDOW->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_FOCUS);
|
||||||
|
|
||||||
updateWindowAnimatedDecorationValues(PLASTWINDOW);
|
PLASTWINDOW->updateDecorationValues();
|
||||||
|
|
||||||
if (!pWindow->m_isX11 || !pWindow->isX11OverrideRedirect())
|
if (!pWindow->m_isX11 || !pWindow->isX11OverrideRedirect())
|
||||||
g_pXWaylandManager->activateWindow(PLASTWINDOW, false);
|
g_pXWaylandManager->activateWindow(PLASTWINDOW, false);
|
||||||
|
|
@ -1224,10 +1225,10 @@ void CCompositor::focusWindow(PHLWINDOW pWindow, SP<CWLSurfaceResource> pSurface
|
||||||
|
|
||||||
g_pXWaylandManager->activateWindow(pWindow, true); // sets the m_pLastWindow
|
g_pXWaylandManager->activateWindow(pWindow, true); // sets the m_pLastWindow
|
||||||
|
|
||||||
pWindow->updateDynamicRules();
|
pWindow->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_FOCUS);
|
||||||
pWindow->onFocusAnimUpdate();
|
pWindow->onFocusAnimUpdate();
|
||||||
|
|
||||||
updateWindowAnimatedDecorationValues(pWindow);
|
pWindow->updateDecorationValues();
|
||||||
|
|
||||||
if (pWindow->m_isUrgent)
|
if (pWindow->m_isUrgent)
|
||||||
pWindow->m_isUrgent = false;
|
pWindow->m_isUrgent = false;
|
||||||
|
|
@ -1333,7 +1334,7 @@ SP<CWLSurfaceResource> CCompositor::vectorToLayerSurface(const Vector2D& pos, st
|
||||||
|
|
||||||
for (auto const& ls : *layerSurfaces | std::views::reverse) {
|
for (auto const& ls : *layerSurfaces | std::views::reverse) {
|
||||||
if (!ls->m_mapped || ls->m_fadingOut || !ls->m_layerSurface || (ls->m_layerSurface && !ls->m_layerSurface->m_surface->m_mapped) || ls->m_alpha->value() == 0.f ||
|
if (!ls->m_mapped || ls->m_fadingOut || !ls->m_layerSurface || (ls->m_layerSurface && !ls->m_layerSurface->m_surface->m_mapped) || ls->m_alpha->value() == 0.f ||
|
||||||
(aboveLockscreen && (!ls->m_aboveLockscreen || !ls->m_aboveLockscreenInteractable)))
|
(aboveLockscreen && ls->m_ruleApplicator->aboveLock().valueOrDefault() != 2))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto [surf, local] = ls->m_layerSurface->m_surface->at(pos - ls->m_geometry.pos(), true);
|
auto [surf, local] = ls->m_layerSurface->m_surface->at(pos - ls->m_geometry.pos(), true);
|
||||||
|
|
@ -1714,7 +1715,7 @@ static bool isFloatingMatches(WINDOWPTR w, std::optional<bool> floating) {
|
||||||
template <typename WINDOWPTR>
|
template <typename WINDOWPTR>
|
||||||
static bool isWindowAvailableForCycle(WINDOWPTR pWindow, WINDOWPTR w, bool focusableOnly, std::optional<bool> floating, bool anyWorkspace = false) {
|
static bool isWindowAvailableForCycle(WINDOWPTR pWindow, WINDOWPTR w, bool focusableOnly, std::optional<bool> floating, bool anyWorkspace = false) {
|
||||||
return isFloatingMatches(w, floating) &&
|
return isFloatingMatches(w, floating) &&
|
||||||
(w != pWindow && isWorkspaceMatches(pWindow, w, anyWorkspace) && w->m_isMapped && !w->isHidden() && (!focusableOnly || !w->m_windowData.noFocus.valueOrDefault()));
|
(w != pWindow && isWorkspaceMatches(pWindow, w, anyWorkspace) && w->m_isMapped && !w->isHidden() && (!focusableOnly || !w->m_ruleApplicator->noFocus().valueOrDefault()));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Iterator>
|
template <typename Iterator>
|
||||||
|
|
@ -1905,103 +1906,10 @@ void CCompositor::updateAllWindowsAnimatedDecorationValues() {
|
||||||
if (!w->m_isMapped)
|
if (!w->m_isMapped)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
updateWindowAnimatedDecorationValues(w);
|
w->updateDecorationValues();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::updateWindowAnimatedDecorationValues(PHLWINDOW pWindow) {
|
|
||||||
// optimization
|
|
||||||
static auto PACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.active_border");
|
|
||||||
static auto PINACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.inactive_border");
|
|
||||||
static auto PNOGROUPACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.nogroup_border_active");
|
|
||||||
static auto PNOGROUPINACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.nogroup_border");
|
|
||||||
static auto PGROUPACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_active");
|
|
||||||
static auto PGROUPINACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_inactive");
|
|
||||||
static auto PGROUPACTIVELOCKEDCOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_locked_active");
|
|
||||||
static auto PGROUPINACTIVELOCKEDCOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_locked_inactive");
|
|
||||||
static auto PINACTIVEALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:inactive_opacity");
|
|
||||||
static auto PACTIVEALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:active_opacity");
|
|
||||||
static auto PFULLSCREENALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:fullscreen_opacity");
|
|
||||||
static auto PSHADOWCOL = CConfigValue<Hyprlang::INT>("decoration:shadow:color");
|
|
||||||
static auto PSHADOWCOLINACTIVE = CConfigValue<Hyprlang::INT>("decoration:shadow:color_inactive");
|
|
||||||
static auto PDIMSTRENGTH = CConfigValue<Hyprlang::FLOAT>("decoration:dim_strength");
|
|
||||||
static auto PDIMENABLED = CConfigValue<Hyprlang::INT>("decoration:dim_inactive");
|
|
||||||
static auto PDIMMODAL = CConfigValue<Hyprlang::INT>("decoration:dim_modal");
|
|
||||||
|
|
||||||
auto* const ACTIVECOL = sc<CGradientValueData*>((PACTIVECOL.ptr())->getData());
|
|
||||||
auto* const INACTIVECOL = sc<CGradientValueData*>((PINACTIVECOL.ptr())->getData());
|
|
||||||
auto* const NOGROUPACTIVECOL = sc<CGradientValueData*>((PNOGROUPACTIVECOL.ptr())->getData());
|
|
||||||
auto* const NOGROUPINACTIVECOL = sc<CGradientValueData*>((PNOGROUPINACTIVECOL.ptr())->getData());
|
|
||||||
auto* const GROUPACTIVECOL = sc<CGradientValueData*>((PGROUPACTIVECOL.ptr())->getData());
|
|
||||||
auto* const GROUPINACTIVECOL = sc<CGradientValueData*>((PGROUPINACTIVECOL.ptr())->getData());
|
|
||||||
auto* const GROUPACTIVELOCKEDCOL = sc<CGradientValueData*>((PGROUPACTIVELOCKEDCOL.ptr())->getData());
|
|
||||||
auto* const GROUPINACTIVELOCKEDCOL = sc<CGradientValueData*>((PGROUPINACTIVELOCKEDCOL.ptr())->getData());
|
|
||||||
|
|
||||||
auto setBorderColor = [&](CGradientValueData grad) -> void {
|
|
||||||
if (grad == pWindow->m_realBorderColor)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pWindow->m_realBorderColorPrevious = pWindow->m_realBorderColor;
|
|
||||||
pWindow->m_realBorderColor = grad;
|
|
||||||
pWindow->m_borderFadeAnimationProgress->setValueAndWarp(0.f);
|
|
||||||
*pWindow->m_borderFadeAnimationProgress = 1.f;
|
|
||||||
};
|
|
||||||
|
|
||||||
const bool IS_SHADOWED_BY_MODAL = pWindow->m_xdgSurface && pWindow->m_xdgSurface->m_toplevel && pWindow->m_xdgSurface->m_toplevel->anyChildModal();
|
|
||||||
|
|
||||||
// border
|
|
||||||
const auto RENDERDATA = g_pLayoutManager->getCurrentLayout()->requestRenderHints(pWindow);
|
|
||||||
if (RENDERDATA.isBorderGradient)
|
|
||||||
setBorderColor(*RENDERDATA.borderGradient);
|
|
||||||
else {
|
|
||||||
const bool GROUPLOCKED = pWindow->m_groupData.pNextWindow.lock() ? pWindow->getGroupHead()->m_groupData.locked : false;
|
|
||||||
if (pWindow == m_lastWindow) {
|
|
||||||
const auto* const ACTIVECOLOR =
|
|
||||||
!pWindow->m_groupData.pNextWindow.lock() ? (!pWindow->m_groupData.deny ? ACTIVECOL : NOGROUPACTIVECOL) : (GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL);
|
|
||||||
setBorderColor(pWindow->m_windowData.activeBorderColor.valueOr(*ACTIVECOLOR));
|
|
||||||
} else {
|
|
||||||
const auto* const INACTIVECOLOR = !pWindow->m_groupData.pNextWindow.lock() ? (!pWindow->m_groupData.deny ? INACTIVECOL : NOGROUPINACTIVECOL) :
|
|
||||||
(GROUPLOCKED ? GROUPINACTIVELOCKEDCOL : GROUPINACTIVECOL);
|
|
||||||
setBorderColor(pWindow->m_windowData.inactiveBorderColor.valueOr(*INACTIVECOLOR));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// opacity
|
|
||||||
const auto PWORKSPACE = pWindow->m_workspace;
|
|
||||||
if (pWindow->isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) {
|
|
||||||
*pWindow->m_activeInactiveAlpha = pWindow->m_windowData.alphaFullscreen.valueOrDefault().applyAlpha(*PFULLSCREENALPHA);
|
|
||||||
} else {
|
|
||||||
if (pWindow == m_lastWindow)
|
|
||||||
*pWindow->m_activeInactiveAlpha = pWindow->m_windowData.alpha.valueOrDefault().applyAlpha(*PACTIVEALPHA);
|
|
||||||
else
|
|
||||||
*pWindow->m_activeInactiveAlpha = pWindow->m_windowData.alphaInactive.valueOrDefault().applyAlpha(*PINACTIVEALPHA);
|
|
||||||
}
|
|
||||||
|
|
||||||
// dim
|
|
||||||
float goalDim = 1.F;
|
|
||||||
if (pWindow == m_lastWindow.lock() || pWindow->m_windowData.noDim.valueOrDefault() || !*PDIMENABLED)
|
|
||||||
goalDim = 0;
|
|
||||||
else
|
|
||||||
goalDim = *PDIMSTRENGTH;
|
|
||||||
|
|
||||||
if (IS_SHADOWED_BY_MODAL && *PDIMMODAL)
|
|
||||||
goalDim += (1.F - goalDim) / 2.F;
|
|
||||||
|
|
||||||
*pWindow->m_dimPercent = goalDim;
|
|
||||||
|
|
||||||
// shadow
|
|
||||||
if (!pWindow->isX11OverrideRedirect() && !pWindow->m_X11DoesntWantBorders) {
|
|
||||||
if (pWindow == m_lastWindow)
|
|
||||||
*pWindow->m_realShadowColor = CHyprColor(*PSHADOWCOL);
|
|
||||||
else
|
|
||||||
*pWindow->m_realShadowColor = CHyprColor(*PSHADOWCOLINACTIVE != -1 ? *PSHADOWCOLINACTIVE : *PSHADOWCOL);
|
|
||||||
} else {
|
|
||||||
pWindow->m_realShadowColor->setValueAndWarp(CHyprColor(0, 0, 0, 0)); // no shadow
|
|
||||||
}
|
|
||||||
|
|
||||||
pWindow->updateWindowDecos();
|
|
||||||
}
|
|
||||||
|
|
||||||
MONITORID CCompositor::getNextAvailableMonitorID(std::string const& name) {
|
MONITORID CCompositor::getNextAvailableMonitorID(std::string const& name) {
|
||||||
// reuse ID if it's already in the map, and the monitor with that ID is not being used by another monitor
|
// reuse ID if it's already in the map, and the monitor with that ID is not being used by another monitor
|
||||||
if (m_monitorIDMap.contains(name) && !std::ranges::any_of(m_realMonitors, [&](auto m) { return m->m_id == m_monitorIDMap[name]; }))
|
if (m_monitorIDMap.contains(name) && !std::ranges::any_of(m_realMonitors, [&](auto m) { return m->m_id == m_monitorIDMap[name]; }))
|
||||||
|
|
@ -2340,14 +2248,14 @@ void CCompositor::changeWindowFullscreenModeClient(const PHLWINDOW PWINDOW, cons
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE) {
|
void CCompositor::setWindowFullscreenInternal(const PHLWINDOW PWINDOW, const eFullscreenMode MODE) {
|
||||||
if (PWINDOW->m_windowData.syncFullscreen.valueOrDefault())
|
if (PWINDOW->m_ruleApplicator->syncFullscreen().valueOrDefault())
|
||||||
setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = MODE, .client = MODE});
|
setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = MODE, .client = MODE});
|
||||||
else
|
else
|
||||||
setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = MODE, .client = PWINDOW->m_fullscreenState.client});
|
setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = MODE, .client = PWINDOW->m_fullscreenState.client});
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE) {
|
void CCompositor::setWindowFullscreenClient(const PHLWINDOW PWINDOW, const eFullscreenMode MODE) {
|
||||||
if (PWINDOW->m_windowData.syncFullscreen.valueOrDefault())
|
if (PWINDOW->m_ruleApplicator->syncFullscreen().valueOrDefault())
|
||||||
setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = MODE, .client = MODE});
|
setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = MODE, .client = MODE});
|
||||||
else
|
else
|
||||||
setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = PWINDOW->m_fullscreenState.internal, .client = MODE});
|
setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = PWINDOW->m_fullscreenState.internal, .client = MODE});
|
||||||
|
|
@ -2388,15 +2296,16 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, SFullscreenS
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: update the state on syncFullscreen changes
|
// TODO: update the state on syncFullscreen changes
|
||||||
if (!CHANGEINTERNAL && PWINDOW->m_windowData.syncFullscreen.valueOrDefault())
|
if (!CHANGEINTERNAL && PWINDOW->m_ruleApplicator->syncFullscreen().valueOrDefault())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PWINDOW->m_fullscreenState.client = state.client;
|
PWINDOW->m_fullscreenState.client = state.client;
|
||||||
g_pXWaylandManager->setWindowFullscreen(PWINDOW, state.client & FSMODE_FULLSCREEN);
|
g_pXWaylandManager->setWindowFullscreen(PWINDOW, state.client & FSMODE_FULLSCREEN);
|
||||||
|
|
||||||
if (!CHANGEINTERNAL) {
|
if (!CHANGEINTERNAL) {
|
||||||
PWINDOW->updateDynamicRules();
|
PWINDOW->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_FULLSCREEN | Desktop::Rule::RULE_PROP_FULLSCREENSTATE_CLIENT |
|
||||||
updateWindowAnimatedDecorationValues(PWINDOW);
|
Desktop::Rule::RULE_PROP_FULLSCREENSTATE_INTERNAL | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||||
|
PWINDOW->updateDecorationValues();
|
||||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID());
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -2410,8 +2319,10 @@ void CCompositor::setWindowFullscreenState(const PHLWINDOW PWINDOW, SFullscreenS
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "fullscreen", .data = std::to_string(sc<int>(EFFECTIVE_MODE) != FSMODE_NONE)});
|
g_pEventManager->postEvent(SHyprIPCEvent{.event = "fullscreen", .data = std::to_string(sc<int>(EFFECTIVE_MODE) != FSMODE_NONE)});
|
||||||
EMIT_HOOK_EVENT("fullscreen", PWINDOW);
|
EMIT_HOOK_EVENT("fullscreen", PWINDOW);
|
||||||
|
|
||||||
PWINDOW->updateDynamicRules();
|
PWINDOW->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_FULLSCREEN | Desktop::Rule::RULE_PROP_FULLSCREENSTATE_CLIENT |
|
||||||
updateWindowAnimatedDecorationValues(PWINDOW);
|
Desktop::Rule::RULE_PROP_FULLSCREENSTATE_INTERNAL | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||||
|
|
||||||
|
PWINDOW->updateDecorationValues();
|
||||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID());
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PWINDOW->monitorID());
|
||||||
|
|
||||||
// make all windows on the same workspace under the fullscreen window
|
// make all windows on the same workspace under the fullscreen window
|
||||||
|
|
@ -2551,7 +2462,7 @@ PHLWINDOW CCompositor::getWindowByRegex(const std::string& regexp_) {
|
||||||
}
|
}
|
||||||
case MODE_TAG_REGEX: {
|
case MODE_TAG_REGEX: {
|
||||||
bool tagMatched = false;
|
bool tagMatched = false;
|
||||||
for (auto const& t : w->m_tags.getTags()) {
|
for (auto const& t : w->m_ruleApplicator->m_tagKeeper.getTags()) {
|
||||||
if (RE2::FullMatch(t, regexCheck)) {
|
if (RE2::FullMatch(t, regexCheck)) {
|
||||||
tagMatched = true;
|
tagMatched = true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -2765,22 +2676,19 @@ void CCompositor::performUserChecks() {
|
||||||
const auto CURRENT_DESKTOP_ENV = getenv("XDG_CURRENT_DESKTOP");
|
const auto CURRENT_DESKTOP_ENV = getenv("XDG_CURRENT_DESKTOP");
|
||||||
if (!CURRENT_DESKTOP_ENV || std::string{CURRENT_DESKTOP_ENV} != "Hyprland") {
|
if (!CURRENT_DESKTOP_ENV || std::string{CURRENT_DESKTOP_ENV} != "Hyprland") {
|
||||||
g_pHyprNotificationOverlay->addNotification(
|
g_pHyprNotificationOverlay->addNotification(
|
||||||
std::format("Your XDG_CURRENT_DESKTOP environment seems to be managed externally, and the current value is {}.\nThis might cause issues unless it's intentional.",
|
I18n::i18nEngine()->localize(I18n::TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP, {{"value", CURRENT_DESKTOP_ENV ? CURRENT_DESKTOP_ENV : "unset"}}), CHyprColor{}, 15000,
|
||||||
CURRENT_DESKTOP_ENV ? CURRENT_DESKTOP_ENV : "unset"),
|
ICON_WARNING);
|
||||||
CHyprColor{}, 15000, ICON_WARNING);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!*PNOCHECKGUIUTILS) {
|
if (!*PNOCHECKGUIUTILS) {
|
||||||
if (!NFsUtils::executableExistsInPath("hyprland-dialog")) {
|
if (!NFsUtils::executableExistsInPath("hyprland-dialog")) {
|
||||||
g_pHyprNotificationOverlay->addNotification(
|
g_pHyprNotificationOverlay->addNotification(I18n::i18nEngine()->localize(I18n::TXT_KEY_NOTIF_NO_GUIUTILS), CHyprColor{}, 15000, ICON_WARNING);
|
||||||
"Your system does not have hyprland-guiutils installed. This is a runtime dependency for some dialogs. Consider installing it.", CHyprColor{}, 15000, ICON_WARNING);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_pHyprOpenGL->m_failedAssetsNo > 0) {
|
if (g_pHyprOpenGL->m_failedAssetsNo > 0) {
|
||||||
g_pHyprNotificationOverlay->addNotification(std::format("Hyprland failed to load {} essential asset{}, blame your distro's packager for doing a bad job at packaging!",
|
g_pHyprNotificationOverlay->addNotification(I18n::i18nEngine()->localize(I18n::TXT_KEY_NOTIF_FAILED_ASSETS, {{"count", std::to_string(g_pHyprOpenGL->m_failedAssetsNo)}}),
|
||||||
g_pHyprOpenGL->m_failedAssetsNo, g_pHyprOpenGL->m_failedAssetsNo > 1 ? "s" : ""),
|
|
||||||
CHyprColor{1.0, 0.1, 0.1, 1.0}, 15000, ICON_ERROR);
|
CHyprColor{1.0, 0.1, 0.1, 1.0}, 15000, ICON_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2845,7 +2753,7 @@ void CCompositor::moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWor
|
||||||
}
|
}
|
||||||
|
|
||||||
pWindow->updateToplevel();
|
pWindow->updateToplevel();
|
||||||
pWindow->updateDynamicRules();
|
pWindow->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||||
pWindow->uncacheWindowDecos();
|
pWindow->uncacheWindowDecos();
|
||||||
pWindow->updateGroupOutputs();
|
pWindow->updateGroupOutputs();
|
||||||
|
|
||||||
|
|
@ -2876,7 +2784,7 @@ PHLWINDOW CCompositor::getForceFocus() {
|
||||||
if (!w->m_isMapped || w->isHidden() || !w->m_workspace || !w->m_workspace->isVisible())
|
if (!w->m_isMapped || w->isHidden() || !w->m_workspace || !w->m_workspace->isVisible())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!w->m_stayFocused)
|
if (!w->m_ruleApplicator->stayFocused().valueOrDefault())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
return w;
|
return w;
|
||||||
|
|
@ -2905,10 +2813,8 @@ void CCompositor::checkMonitorOverlaps() {
|
||||||
for (const auto& m : m_monitors) {
|
for (const auto& m : m_monitors) {
|
||||||
if (!monitorRegion.copy().intersect(m->logicalBox()).empty()) {
|
if (!monitorRegion.copy().intersect(m->logicalBox()).empty()) {
|
||||||
Debug::log(ERR, "Monitor {}: detected overlap with layout", m->m_name);
|
Debug::log(ERR, "Monitor {}: detected overlap with layout", m->m_name);
|
||||||
g_pHyprNotificationOverlay->addNotification(std::format("Your monitor layout is set up incorrectly. Monitor {} overlaps with other monitor(s) in the "
|
g_pHyprNotificationOverlay->addNotification(I18n::i18nEngine()->localize(I18n::TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT, {{"name", m->m_name}}), CHyprColor{}, 15000,
|
||||||
"layout.\nPlease see the wiki (Monitors page) for more. This will cause issues.",
|
ICON_WARNING);
|
||||||
m->m_name),
|
|
||||||
CHyprColor{}, 15000, ICON_WARNING);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -3029,6 +2935,8 @@ void CCompositor::arrangeMonitors() {
|
||||||
|
|
||||||
#ifndef NO_XWAYLAND
|
#ifndef NO_XWAYLAND
|
||||||
CBox box = g_pCompositor->calculateX11WorkArea();
|
CBox box = g_pCompositor->calculateX11WorkArea();
|
||||||
|
if (!g_pXWayland || !g_pXWayland->m_wm)
|
||||||
|
return;
|
||||||
g_pXWayland->m_wm->updateWorkArea(box.x, box.y, box.w, box.h);
|
g_pXWayland->m_wm->updateWorkArea(box.x, box.y, box.w, box.h);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,6 @@ class CCompositor {
|
||||||
PHLMONITOR getMonitorInDirection(const char&);
|
PHLMONITOR getMonitorInDirection(const char&);
|
||||||
PHLMONITOR getMonitorInDirection(PHLMONITOR, const char&);
|
PHLMONITOR getMonitorInDirection(PHLMONITOR, const char&);
|
||||||
void updateAllWindowsAnimatedDecorationValues();
|
void updateAllWindowsAnimatedDecorationValues();
|
||||||
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, PHLMONITOR, bool noWarpCursor = false);
|
||||||
void swapActiveWorkspaces(PHLMONITOR, PHLMONITOR);
|
void swapActiveWorkspaces(PHLMONITOR, PHLMONITOR);
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,6 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||||
.type = CONFIG_OPTION_INT,
|
.type = CONFIG_OPTION_INT,
|
||||||
.data = SConfigOptionDescription::SRangeData{1, 0, 20},
|
.data = SConfigOptionDescription::SRangeData{1, 0, 20},
|
||||||
},
|
},
|
||||||
SConfigOptionDescription{
|
|
||||||
.value = "general:no_border_on_floating",
|
|
||||||
.description = "disable borders for floating windows",
|
|
||||||
.type = CONFIG_OPTION_BOOL,
|
|
||||||
.data = SConfigOptionDescription::SBoolData{false},
|
|
||||||
},
|
|
||||||
SConfigOptionDescription{
|
SConfigOptionDescription{
|
||||||
.value = "general:gaps_in",
|
.value = "general:gaps_in",
|
||||||
.description = "gaps between windows\n\nsupports css style gaps (top, right, bottom, left -> 5 10 15 20)",
|
.description = "gaps between windows\n\nsupports css style gaps (top, right, bottom, left -> 5 10 15 20)",
|
||||||
|
|
@ -1115,6 +1109,12 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
||||||
.type = CONFIG_OPTION_BOOL,
|
.type = CONFIG_OPTION_BOOL,
|
||||||
.data = SConfigOptionDescription::SRangeData{0, -20, 20},
|
.data = SConfigOptionDescription::SRangeData{0, -20, 20},
|
||||||
},
|
},
|
||||||
|
SConfigOptionDescription{
|
||||||
|
.value = "group:groupbar:blur",
|
||||||
|
.description = "enable background blur for groupbars",
|
||||||
|
.type = CONFIG_OPTION_BOOL,
|
||||||
|
.data = SConfigOptionDescription::SBoolData{false},
|
||||||
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* misc:
|
* misc:
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,15 @@
|
||||||
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
||||||
#include "config/ConfigDataValues.hpp"
|
#include "config/ConfigDataValues.hpp"
|
||||||
#include "config/ConfigValue.hpp"
|
#include "config/ConfigValue.hpp"
|
||||||
#include "../desktop/WindowRule.hpp"
|
|
||||||
#include "../protocols/LayerShell.hpp"
|
#include "../protocols/LayerShell.hpp"
|
||||||
#include "../xwayland/XWayland.hpp"
|
#include "../xwayland/XWayland.hpp"
|
||||||
#include "../protocols/OutputManagement.hpp"
|
#include "../protocols/OutputManagement.hpp"
|
||||||
#include "../managers/animation/AnimationManager.hpp"
|
#include "../managers/animation/AnimationManager.hpp"
|
||||||
#include "../desktop/LayerSurface.hpp"
|
#include "../desktop/LayerSurface.hpp"
|
||||||
|
#include "../desktop/rule/Engine.hpp"
|
||||||
|
#include "../desktop/rule/windowRule/WindowRule.hpp"
|
||||||
|
#include "../desktop/rule/layerRule/LayerRule.hpp"
|
||||||
|
#include "../debug/HyprCtl.hpp"
|
||||||
#include "defaultConfig.hpp"
|
#include "defaultConfig.hpp"
|
||||||
|
|
||||||
#include "../render/Renderer.hpp"
|
#include "../render/Renderer.hpp"
|
||||||
|
|
@ -299,54 +302,6 @@ static Hyprlang::CParseResult handleUnbind(const char* c, const char* v) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Hyprlang::CParseResult handleWindowRule(const char* c, const char* v) {
|
|
||||||
const std::string VALUE = v;
|
|
||||||
const std::string COMMAND = c;
|
|
||||||
|
|
||||||
const auto RESULT = g_pConfigManager->handleWindowRule(COMMAND, VALUE);
|
|
||||||
|
|
||||||
Hyprlang::CParseResult result;
|
|
||||||
if (RESULT.has_value())
|
|
||||||
result.setError(RESULT.value().c_str());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Hyprlang::CParseResult handleLayerRule(const char* c, const char* v) {
|
|
||||||
const std::string VALUE = v;
|
|
||||||
const std::string COMMAND = c;
|
|
||||||
|
|
||||||
const auto RESULT = g_pConfigManager->handleLayerRule(COMMAND, VALUE);
|
|
||||||
|
|
||||||
Hyprlang::CParseResult result;
|
|
||||||
if (RESULT.has_value())
|
|
||||||
result.setError(RESULT.value().c_str());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Hyprlang::CParseResult handleWindowRuleV2(const char* c, const char* v) {
|
|
||||||
const std::string VALUE = v;
|
|
||||||
const std::string COMMAND = c;
|
|
||||||
|
|
||||||
const auto RESULT = g_pConfigManager->handleWindowRule(COMMAND, VALUE);
|
|
||||||
|
|
||||||
Hyprlang::CParseResult result;
|
|
||||||
if (RESULT.has_value())
|
|
||||||
result.setError(RESULT.value().c_str());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Hyprlang::CParseResult handleBlurLS(const char* c, const char* v) {
|
|
||||||
const std::string VALUE = v;
|
|
||||||
const std::string COMMAND = c;
|
|
||||||
|
|
||||||
const auto RESULT = g_pConfigManager->handleBlurLS(COMMAND, VALUE);
|
|
||||||
|
|
||||||
Hyprlang::CParseResult result;
|
|
||||||
if (RESULT.has_value())
|
|
||||||
result.setError(RESULT.value().c_str());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Hyprlang::CParseResult handleWorkspaceRules(const char* c, const char* v) {
|
static Hyprlang::CParseResult handleWorkspaceRules(const char* c, const char* v) {
|
||||||
const std::string VALUE = v;
|
const std::string VALUE = v;
|
||||||
const std::string COMMAND = c;
|
const std::string COMMAND = c;
|
||||||
|
|
@ -431,6 +386,30 @@ static Hyprlang::CParseResult handleGesture(const char* c, const char* v) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Hyprlang::CParseResult handleWindowrule(const char* c, const char* v) {
|
||||||
|
const std::string VALUE = v;
|
||||||
|
const std::string COMMAND = c;
|
||||||
|
|
||||||
|
const auto RESULT = g_pConfigManager->handleWindowrule(COMMAND, VALUE);
|
||||||
|
|
||||||
|
Hyprlang::CParseResult result;
|
||||||
|
if (RESULT.has_value())
|
||||||
|
result.setError(RESULT.value().c_str());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Hyprlang::CParseResult handleLayerrule(const char* c, const char* v) {
|
||||||
|
const std::string VALUE = v;
|
||||||
|
const std::string COMMAND = c;
|
||||||
|
|
||||||
|
const auto RESULT = g_pConfigManager->handleLayerrule(COMMAND, VALUE);
|
||||||
|
|
||||||
|
Hyprlang::CParseResult result;
|
||||||
|
if (RESULT.has_value())
|
||||||
|
result.setError(RESULT.value().c_str());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void CConfigManager::registerConfigVar(const char* name, const Hyprlang::INT& val) {
|
void CConfigManager::registerConfigVar(const char* name, const Hyprlang::INT& val) {
|
||||||
m_configValueNumber++;
|
m_configValueNumber++;
|
||||||
m_config->addConfigValue(name, val);
|
m_config->addConfigValue(name, val);
|
||||||
|
|
@ -463,7 +442,6 @@ CConfigManager::CConfigManager() {
|
||||||
m_config = makeUnique<Hyprlang::CConfig>(m_configPaths.begin()->c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true});
|
m_config = makeUnique<Hyprlang::CConfig>(m_configPaths.begin()->c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, .allowMissingConfig = true});
|
||||||
|
|
||||||
registerConfigVar("general:border_size", Hyprlang::INT{1});
|
registerConfigVar("general:border_size", Hyprlang::INT{1});
|
||||||
registerConfigVar("general:no_border_on_floating", Hyprlang::INT{0});
|
|
||||||
registerConfigVar("general:gaps_in", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "5"});
|
registerConfigVar("general:gaps_in", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "5"});
|
||||||
registerConfigVar("general:gaps_out", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "20"});
|
registerConfigVar("general:gaps_out", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "20"});
|
||||||
registerConfigVar("general:float_gaps", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "0"});
|
registerConfigVar("general:float_gaps", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "0"});
|
||||||
|
|
@ -560,6 +538,7 @@ CConfigManager::CConfigManager() {
|
||||||
registerConfigVar("group:groupbar:gaps_in", Hyprlang::INT{2});
|
registerConfigVar("group:groupbar:gaps_in", Hyprlang::INT{2});
|
||||||
registerConfigVar("group:groupbar:keep_upper_gap", Hyprlang::INT{1});
|
registerConfigVar("group:groupbar:keep_upper_gap", Hyprlang::INT{1});
|
||||||
registerConfigVar("group:groupbar:text_offset", Hyprlang::INT{0});
|
registerConfigVar("group:groupbar:text_offset", Hyprlang::INT{0});
|
||||||
|
registerConfigVar("group:groupbar:blur", Hyprlang::INT{0});
|
||||||
|
|
||||||
registerConfigVar("debug:log_damage", Hyprlang::INT{0});
|
registerConfigVar("debug:log_damage", Hyprlang::INT{0});
|
||||||
registerConfigVar("debug:overlay", Hyprlang::INT{0});
|
registerConfigVar("debug:overlay", Hyprlang::INT{0});
|
||||||
|
|
@ -857,6 +836,16 @@ CConfigManager::CConfigManager() {
|
||||||
m_config->addSpecialConfigValue("monitorv2", "max_luminance", Hyprlang::INT{-1});
|
m_config->addSpecialConfigValue("monitorv2", "max_luminance", Hyprlang::INT{-1});
|
||||||
m_config->addSpecialConfigValue("monitorv2", "max_avg_luminance", Hyprlang::INT{-1});
|
m_config->addSpecialConfigValue("monitorv2", "max_avg_luminance", Hyprlang::INT{-1});
|
||||||
|
|
||||||
|
// windowrule v3
|
||||||
|
m_config->addSpecialCategory("windowrule", {.key = "name"});
|
||||||
|
m_config->addSpecialConfigValue("windowrule", "enable", Hyprlang::INT{1});
|
||||||
|
|
||||||
|
// layerrule v2
|
||||||
|
m_config->addSpecialCategory("layerrule", {.key = "name"});
|
||||||
|
m_config->addSpecialConfigValue("layerrule", "enable", Hyprlang::INT{1});
|
||||||
|
|
||||||
|
reloadRuleConfigs();
|
||||||
|
|
||||||
// keywords
|
// keywords
|
||||||
m_config->registerHandler(&::handleExec, "exec", {false});
|
m_config->registerHandler(&::handleExec, "exec", {false});
|
||||||
m_config->registerHandler(&::handleRawExec, "execr", {false});
|
m_config->registerHandler(&::handleRawExec, "execr", {false});
|
||||||
|
|
@ -867,14 +856,12 @@ CConfigManager::CConfigManager() {
|
||||||
m_config->registerHandler(&::handleBind, "bind", {true});
|
m_config->registerHandler(&::handleBind, "bind", {true});
|
||||||
m_config->registerHandler(&::handleUnbind, "unbind", {false});
|
m_config->registerHandler(&::handleUnbind, "unbind", {false});
|
||||||
m_config->registerHandler(&::handleWorkspaceRules, "workspace", {false});
|
m_config->registerHandler(&::handleWorkspaceRules, "workspace", {false});
|
||||||
m_config->registerHandler(&::handleWindowRule, "windowrule", {false});
|
m_config->registerHandler(&::handleWindowrule, "windowrule", {false});
|
||||||
m_config->registerHandler(&::handleLayerRule, "layerrule", {false});
|
m_config->registerHandler(&::handleLayerrule, "layerrule", {false});
|
||||||
m_config->registerHandler(&::handleWindowRuleV2, "windowrulev2", {false});
|
|
||||||
m_config->registerHandler(&::handleBezier, "bezier", {false});
|
m_config->registerHandler(&::handleBezier, "bezier", {false});
|
||||||
m_config->registerHandler(&::handleAnimation, "animation", {false});
|
m_config->registerHandler(&::handleAnimation, "animation", {false});
|
||||||
m_config->registerHandler(&::handleSource, "source", {false});
|
m_config->registerHandler(&::handleSource, "source", {false});
|
||||||
m_config->registerHandler(&::handleSubmap, "submap", {false});
|
m_config->registerHandler(&::handleSubmap, "submap", {false});
|
||||||
m_config->registerHandler(&::handleBlurLS, "blurls", {false});
|
|
||||||
m_config->registerHandler(&::handlePlugin, "plugin", {false});
|
m_config->registerHandler(&::handlePlugin, "plugin", {false});
|
||||||
m_config->registerHandler(&::handlePermission, "permission", {false});
|
m_config->registerHandler(&::handlePermission, "permission", {false});
|
||||||
m_config->registerHandler(&::handleGesture, "gesture", {false});
|
m_config->registerHandler(&::handleGesture, "gesture", {false});
|
||||||
|
|
@ -904,6 +891,26 @@ CConfigManager::CConfigManager() {
|
||||||
g_pEventLoopManager->doLater([ERR] { g_pHyprError->queueCreate(ERR.value(), CHyprColor{1.0, 0.1, 0.1, 1.0}); });
|
g_pEventLoopManager->doLater([ERR] { g_pHyprError->queueCreate(ERR.value(), CHyprColor{1.0, 0.1, 0.1, 1.0}); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CConfigManager::reloadRuleConfigs() {
|
||||||
|
// FIXME: this should also remove old values if they are removed
|
||||||
|
|
||||||
|
for (const auto& r : Desktop::Rule::allMatchPropStrings()) {
|
||||||
|
m_config->addSpecialConfigValue("windowrule", ("match:" + r).c_str(), Hyprlang::STRING{""});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& r : Desktop::Rule::windowEffects()->allEffectStrings()) {
|
||||||
|
m_config->addSpecialConfigValue("windowrule", r.c_str(), Hyprlang::STRING{""});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& r : Desktop::Rule::allMatchPropStrings()) {
|
||||||
|
m_config->addSpecialConfigValue("layerrule", ("match:" + r).c_str(), Hyprlang::STRING{""});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& r : Desktop::Rule::layerEffects()->allEffectStrings()) {
|
||||||
|
m_config->addSpecialConfigValue("layerrule", r.c_str(), Hyprlang::STRING{""});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<std::string> CConfigManager::generateConfig(std::string configPath) {
|
std::optional<std::string> CConfigManager::generateConfig(std::string configPath) {
|
||||||
std::string parentPath = std::filesystem::path(configPath).parent_path();
|
std::string parentPath = std::filesystem::path(configPath).parent_path();
|
||||||
|
|
||||||
|
|
@ -983,13 +990,36 @@ std::string CConfigManager::getErrors() {
|
||||||
return m_configErrors;
|
return m_configErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::vector<const char*> HL_VERSION_VARS = {
|
||||||
|
"HYPRLAND_V_0_53",
|
||||||
|
};
|
||||||
|
|
||||||
|
static void exportHlVersionVars() {
|
||||||
|
for (const auto& v : HL_VERSION_VARS) {
|
||||||
|
setenv(v, "1", 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clearHlVersionVars() {
|
||||||
|
for (const auto& v : HL_VERSION_VARS) {
|
||||||
|
unsetenv(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CConfigManager::reload() {
|
void CConfigManager::reload() {
|
||||||
EMIT_HOOK_EVENT("preConfigReload", nullptr);
|
EMIT_HOOK_EVENT("preConfigReload", nullptr);
|
||||||
setDefaultAnimationVars();
|
setDefaultAnimationVars();
|
||||||
resetHLConfig();
|
resetHLConfig();
|
||||||
m_configCurrentPath = getMainConfigPath();
|
m_configCurrentPath = getMainConfigPath();
|
||||||
|
|
||||||
|
exportHlVersionVars();
|
||||||
|
|
||||||
const auto ERR = m_config->parse();
|
const auto ERR = m_config->parse();
|
||||||
|
|
||||||
|
clearHlVersionVars();
|
||||||
|
|
||||||
const auto monitorError = handleMonitorv2();
|
const auto monitorError = handleMonitorv2();
|
||||||
|
const auto ruleError = reloadRules();
|
||||||
m_lastConfigVerificationWasSuccessful = !ERR.error && !monitorError.error;
|
m_lastConfigVerificationWasSuccessful = !ERR.error && !monitorError.error;
|
||||||
postConfigReload(ERR.error || !monitorError.error ? ERR : monitorError);
|
postConfigReload(ERR.error || !monitorError.error ? ERR : monitorError);
|
||||||
}
|
}
|
||||||
|
|
@ -1057,20 +1087,18 @@ void CConfigManager::setDefaultAnimationVars() {
|
||||||
|
|
||||||
std::optional<std::string> CConfigManager::resetHLConfig() {
|
std::optional<std::string> CConfigManager::resetHLConfig() {
|
||||||
m_monitorRules.clear();
|
m_monitorRules.clear();
|
||||||
m_windowRules.clear();
|
|
||||||
g_pKeybindManager->clearKeybinds();
|
g_pKeybindManager->clearKeybinds();
|
||||||
g_pAnimationManager->removeAllBeziers();
|
g_pAnimationManager->removeAllBeziers();
|
||||||
g_pAnimationManager->addBezierWithName("linear", Vector2D(0.0, 0.0), Vector2D(1.0, 1.0));
|
g_pAnimationManager->addBezierWithName("linear", Vector2D(0.0, 0.0), Vector2D(1.0, 1.0));
|
||||||
g_pTrackpadGestures->clearGestures();
|
g_pTrackpadGestures->clearGestures();
|
||||||
|
|
||||||
m_mAdditionalReservedAreas.clear();
|
m_mAdditionalReservedAreas.clear();
|
||||||
m_blurLSNamespaces.clear();
|
|
||||||
m_workspaceRules.clear();
|
m_workspaceRules.clear();
|
||||||
setDefaultAnimationVars(); // reset anims
|
setDefaultAnimationVars(); // reset anims
|
||||||
m_declaredPlugins.clear();
|
m_declaredPlugins.clear();
|
||||||
m_layerRules.clear();
|
|
||||||
m_failedPluginConfigValues.clear();
|
m_failedPluginConfigValues.clear();
|
||||||
m_finalExecRequests.clear();
|
m_finalExecRequests.clear();
|
||||||
|
m_keywordRules.clear();
|
||||||
|
|
||||||
// paths
|
// paths
|
||||||
m_configPaths.clear();
|
m_configPaths.clear();
|
||||||
|
|
@ -1080,6 +1108,8 @@ std::optional<std::string> CConfigManager::resetHLConfig() {
|
||||||
|
|
||||||
const auto RET = verifyConfigExists();
|
const auto RET = verifyConfigExists();
|
||||||
|
|
||||||
|
reloadRuleConfigs();
|
||||||
|
|
||||||
return RET;
|
return RET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1178,6 +1208,77 @@ Hyprlang::CParseResult CConfigManager::handleMonitorv2() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> CConfigManager::addRuleFromConfigKey(const std::string& name) {
|
||||||
|
const auto ENABLED = m_config->getSpecialConfigValuePtr("windowrule", "enable", name.c_str());
|
||||||
|
if (ENABLED && ENABLED->m_bSetByUser && std::any_cast<Hyprlang::INT>(ENABLED->getValue()) == 0)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
SP<Desktop::Rule::CWindowRule> rule = makeShared<Desktop::Rule::CWindowRule>(name);
|
||||||
|
|
||||||
|
for (const auto& r : Desktop::Rule::allMatchPropStrings()) {
|
||||||
|
auto VAL = m_config->getSpecialConfigValuePtr("windowrule", ("match:" + r).c_str(), name.c_str());
|
||||||
|
if (VAL && VAL->m_bSetByUser)
|
||||||
|
rule->registerMatch(Desktop::Rule::matchPropFromString(r).value_or(Desktop::Rule::RULE_PROP_NONE), std::any_cast<Hyprlang::STRING>(VAL->getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& e : Desktop::Rule::windowEffects()->allEffectStrings()) {
|
||||||
|
auto VAL = m_config->getSpecialConfigValuePtr("windowrule", e.c_str(), name.c_str());
|
||||||
|
if (VAL && VAL->m_bSetByUser)
|
||||||
|
rule->addEffect(Desktop::Rule::windowEffects()->get(e).value_or(Desktop::Rule::WINDOW_RULE_EFFECT_NONE), std::any_cast<Hyprlang::STRING>(VAL->getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Desktop::Rule::ruleEngine()->registerRule(std::move(rule));
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> CConfigManager::addLayerRuleFromConfigKey(const std::string& name) {
|
||||||
|
|
||||||
|
const auto ENABLED = m_config->getSpecialConfigValuePtr("layerrule", "enable", name.c_str());
|
||||||
|
if (ENABLED && ENABLED->m_bSetByUser && std::any_cast<Hyprlang::INT>(ENABLED->getValue()) != 0)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
SP<Desktop::Rule::CLayerRule> rule = makeShared<Desktop::Rule::CLayerRule>(name);
|
||||||
|
|
||||||
|
for (const auto& r : Desktop::Rule::allMatchPropStrings()) {
|
||||||
|
auto VAL = m_config->getSpecialConfigValuePtr("layerrule", ("match:" + r).c_str(), name.c_str());
|
||||||
|
if (VAL && VAL->m_bSetByUser)
|
||||||
|
rule->registerMatch(Desktop::Rule::matchPropFromString(r).value_or(Desktop::Rule::RULE_PROP_NONE), std::any_cast<Hyprlang::STRING>(VAL->getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& e : Desktop::Rule::layerEffects()->allEffectStrings()) {
|
||||||
|
auto VAL = m_config->getSpecialConfigValuePtr("layerrule", e.c_str(), name.c_str());
|
||||||
|
if (VAL && VAL->m_bSetByUser)
|
||||||
|
rule->addEffect(Desktop::Rule::layerEffects()->get(e).value_or(Desktop::Rule::LAYER_RULE_EFFECT_NONE), std::any_cast<Hyprlang::STRING>(VAL->getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Desktop::Rule::ruleEngine()->registerRule(std::move(rule));
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
Hyprlang::CParseResult CConfigManager::reloadRules() {
|
||||||
|
Desktop::Rule::ruleEngine()->clearAllRules();
|
||||||
|
|
||||||
|
Hyprlang::CParseResult result;
|
||||||
|
for (const auto& name : m_config->listKeysForSpecialCategory("windowrule")) {
|
||||||
|
const auto error = addRuleFromConfigKey(name);
|
||||||
|
if (error.has_value())
|
||||||
|
result.setError(error.value().c_str());
|
||||||
|
}
|
||||||
|
for (const auto& name : m_config->listKeysForSpecialCategory("layerrule")) {
|
||||||
|
const auto error = addLayerRuleFromConfigKey(name);
|
||||||
|
if (error.has_value())
|
||||||
|
result.setError(error.value().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& rule : m_keywordRules) {
|
||||||
|
Desktop::Rule::ruleEngine()->registerRule(SP<Desktop::Rule::IRule>{rule});
|
||||||
|
}
|
||||||
|
|
||||||
|
Desktop::Rule::ruleEngine()->updateAllRules();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
|
void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
|
||||||
updateWatcher();
|
updateWatcher();
|
||||||
|
|
||||||
|
|
@ -1503,229 +1604,6 @@ SWorkspaceRule CConfigManager::mergeWorkspaceRules(const SWorkspaceRule& rule1,
|
||||||
return mergedRule;
|
return mergedRule;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<SP<CWindowRule>> CConfigManager::getMatchingRules(PHLWINDOW pWindow, bool dynamic, bool shadowExec) {
|
|
||||||
if (!valid(pWindow))
|
|
||||||
return std::vector<SP<CWindowRule>>();
|
|
||||||
|
|
||||||
// if the window is unmapped, don't process exec rules yet.
|
|
||||||
shadowExec = shadowExec || !pWindow->m_isMapped;
|
|
||||||
|
|
||||||
std::vector<SP<CWindowRule>> returns;
|
|
||||||
|
|
||||||
Debug::log(LOG, "Searching for matching rules for {} (title: {})", pWindow->m_class, pWindow->m_title);
|
|
||||||
|
|
||||||
// since some rules will be applied later, we need to store some flags
|
|
||||||
bool hasFloating = pWindow->m_isFloating;
|
|
||||||
bool hasFullscreen = pWindow->isFullscreen();
|
|
||||||
bool isGrouped = pWindow->m_groupData.pNextWindow;
|
|
||||||
|
|
||||||
// local tags for dynamic tag rule match
|
|
||||||
auto tags = pWindow->m_tags;
|
|
||||||
|
|
||||||
for (auto const& rule : m_windowRules) {
|
|
||||||
// check if we have a matching rule
|
|
||||||
if (!rule->m_v2) {
|
|
||||||
try {
|
|
||||||
if (rule->m_value.starts_with("tag:") && !tags.isTagged(rule->m_value.substr(4)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (rule->m_value.starts_with("title:") && !rule->m_v1Regex.passes(pWindow->m_title))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!rule->m_v1Regex.passes(pWindow->m_class))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
} catch (...) {
|
|
||||||
Debug::log(ERR, "Regex error at {}", rule->m_value);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
if (rule->m_X11 != -1) {
|
|
||||||
if (pWindow->m_isX11 != rule->m_X11)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rule->m_floating != -1) {
|
|
||||||
if (hasFloating != rule->m_floating)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rule->m_fullscreen != -1) {
|
|
||||||
if (hasFullscreen != rule->m_fullscreen)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rule->m_pinned != -1) {
|
|
||||||
if (pWindow->m_pinned != rule->m_pinned)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rule->m_focus != -1) {
|
|
||||||
if (rule->m_focus != (g_pCompositor->m_lastWindow.lock() == pWindow))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rule->m_group != -1) {
|
|
||||||
if (rule->m_group != isGrouped)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rule->m_modal != -1) {
|
|
||||||
if (rule->m_modal != pWindow->isModal())
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rule->m_fullscreenState.empty()) {
|
|
||||||
const auto ARGS = CVarList(rule->m_fullscreenState, 2, ' ');
|
|
||||||
//
|
|
||||||
std::optional<eFullscreenMode> internalMode, clientMode;
|
|
||||||
|
|
||||||
if (ARGS[0] == "*")
|
|
||||||
internalMode = std::nullopt;
|
|
||||||
else if (isNumber(ARGS[0]))
|
|
||||||
internalMode = sc<eFullscreenMode>(std::stoi(ARGS[0]));
|
|
||||||
else
|
|
||||||
throw std::runtime_error("szFullscreenState internal mode not valid");
|
|
||||||
|
|
||||||
if (ARGS[1] == "*")
|
|
||||||
clientMode = std::nullopt;
|
|
||||||
else if (isNumber(ARGS[1]))
|
|
||||||
clientMode = sc<eFullscreenMode>(std::stoi(ARGS[1]));
|
|
||||||
else
|
|
||||||
throw std::runtime_error("szFullscreenState client mode not valid");
|
|
||||||
|
|
||||||
if (internalMode.has_value() && pWindow->m_fullscreenState.internal != internalMode)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (clientMode.has_value() && pWindow->m_fullscreenState.client != clientMode)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rule->m_onWorkspace.empty()) {
|
|
||||||
const auto PWORKSPACE = pWindow->m_workspace;
|
|
||||||
if (!PWORKSPACE || !PWORKSPACE->matchesStaticSelector(rule->m_onWorkspace))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rule->m_contentType.empty()) {
|
|
||||||
try {
|
|
||||||
const auto contentType = NContentType::fromString(rule->m_contentType);
|
|
||||||
if (pWindow->getContentType() != contentType)
|
|
||||||
continue;
|
|
||||||
} catch (std::exception& e) { Debug::log(ERR, "Rule \"content:{}\" failed with: {}", rule->m_contentType, e.what()); }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rule->m_xdgTag.empty()) {
|
|
||||||
if (pWindow->xdgTag().value_or("") != rule->m_xdgTag)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rule->m_workspace.empty()) {
|
|
||||||
const auto PWORKSPACE = pWindow->m_workspace;
|
|
||||||
|
|
||||||
if (!PWORKSPACE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (rule->m_workspace.starts_with("name:")) {
|
|
||||||
if (PWORKSPACE->m_name != rule->m_workspace.substr(5))
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
// number
|
|
||||||
if (!isNumber(rule->m_workspace))
|
|
||||||
throw std::runtime_error("szWorkspace not name: or number");
|
|
||||||
|
|
||||||
const int64_t ID = std::stoll(rule->m_workspace);
|
|
||||||
|
|
||||||
if (PWORKSPACE->m_id != ID)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rule->m_tag.empty() && !tags.isTagged(rule->m_tag))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!rule->m_class.empty() && !rule->m_classRegex.passes(pWindow->m_class))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!rule->m_title.empty() && !rule->m_titleRegex.passes(pWindow->m_title))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!rule->m_initialTitle.empty() && !rule->m_initialTitleRegex.passes(pWindow->m_initialTitle))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!rule->m_initialClass.empty() && !rule->m_initialClassRegex.passes(pWindow->m_initialClass))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
} catch (std::exception& e) {
|
|
||||||
Debug::log(ERR, "Regex error at {} ({})", rule->m_value, e.what());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// applies. Read the rule and behave accordingly
|
|
||||||
Debug::log(LOG, "Window rule {} -> {} matched {}", rule->m_rule, rule->m_value, pWindow);
|
|
||||||
|
|
||||||
returns.emplace_back(rule);
|
|
||||||
|
|
||||||
// apply tag with local tags
|
|
||||||
if (rule->m_ruleType == CWindowRule::RULE_TAG) {
|
|
||||||
CVarList vars{rule->m_rule, 0, 's', true};
|
|
||||||
if (vars.size() == 2 && vars[0] == "tag")
|
|
||||||
tags.applyTag(vars[1], true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dynamic)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (rule->m_rule == "float")
|
|
||||||
hasFloating = true;
|
|
||||||
else if (rule->m_rule == "fullscreen")
|
|
||||||
hasFullscreen = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint64_t> PIDs = {sc<uint64_t>(pWindow->getPID())};
|
|
||||||
while (getPPIDof(PIDs.back()) > 10)
|
|
||||||
PIDs.push_back(getPPIDof(PIDs.back()));
|
|
||||||
|
|
||||||
bool anyExecFound = false;
|
|
||||||
|
|
||||||
for (auto const& er : m_execRequestedRules) {
|
|
||||||
if (std::ranges::any_of(PIDs, [&](const auto& pid) { return pid == er.iPid; })) {
|
|
||||||
returns.emplace_back(makeShared<CWindowRule>(er.szRule, "", false, true));
|
|
||||||
anyExecFound = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (anyExecFound && !shadowExec) // remove exec rules to unclog searches in the future, why have the garbage here.
|
|
||||||
std::erase_if(m_execRequestedRules, [&](const SExecRequestedRule& other) { return std::ranges::any_of(PIDs, [&](const auto& pid) { return pid == other.iPid; }); });
|
|
||||||
|
|
||||||
return returns;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<SP<CLayerRule>> CConfigManager::getMatchingRules(PHLLS pLS) {
|
|
||||||
std::vector<SP<CLayerRule>> returns;
|
|
||||||
|
|
||||||
if (!pLS->m_layerSurface || pLS->m_fadingOut)
|
|
||||||
return returns;
|
|
||||||
|
|
||||||
for (auto const& lr : m_layerRules) {
|
|
||||||
if (lr->m_targetNamespace.starts_with("address:0x")) {
|
|
||||||
if (std::format("address:0x{:x}", rc<uintptr_t>(pLS.get())) != lr->m_targetNamespace)
|
|
||||||
continue;
|
|
||||||
} else if (!lr->m_targetNamespaceRegex.passes(pLS->m_layerSurface->m_layerNamespace))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// hit
|
|
||||||
returns.emplace_back(lr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldBlurLS(pLS->m_layerSurface->m_layerNamespace))
|
|
||||||
returns.emplace_back(makeShared<CLayerRule>(pLS->m_layerSurface->m_layerNamespace, "blur"));
|
|
||||||
|
|
||||||
return returns;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CConfigManager::dispatchExecOnce() {
|
void CConfigManager::dispatchExecOnce() {
|
||||||
if (m_firstExecDispatched || m_isFirstLaunch)
|
if (m_firstExecDispatched || m_isFirstLaunch)
|
||||||
return;
|
return;
|
||||||
|
|
@ -1831,16 +1709,6 @@ bool CConfigManager::deviceConfigExists(const std::string& dev) {
|
||||||
return m_config->specialCategoryExistsForKey("device", copy.c_str());
|
return m_config->specialCategoryExistsForKey("device", copy.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CConfigManager::shouldBlurLS(const std::string& ns) {
|
|
||||||
for (auto const& bls : m_blurLSNamespaces) {
|
|
||||||
if (bls == ns) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CConfigManager::ensureMonitorStatus() {
|
void CConfigManager::ensureMonitorStatus() {
|
||||||
for (auto const& rm : g_pCompositor->m_realMonitors) {
|
for (auto const& rm : g_pCompositor->m_realMonitors) {
|
||||||
if (!rm->m_output || rm->m_isUnsafeFallback)
|
if (!rm->m_output || rm->m_isUnsafeFallback)
|
||||||
|
|
@ -1894,7 +1762,7 @@ void CConfigManager::ensureVRR(PHLMONITOR pMonitor) {
|
||||||
return; // ???
|
return; // ???
|
||||||
|
|
||||||
bool wantVRR = PWORKSPACE->m_hasFullscreenWindow && (PWORKSPACE->m_fullscreenMode & FSMODE_FULLSCREEN);
|
bool wantVRR = PWORKSPACE->m_hasFullscreenWindow && (PWORKSPACE->m_fullscreenMode & FSMODE_FULLSCREEN);
|
||||||
if (wantVRR && PWORKSPACE->getFullscreenWindow()->m_windowData.noVRR.valueOrDefault())
|
if (wantVRR && PWORKSPACE->getFullscreenWindow()->m_ruleApplicator->noVRR().valueOrDefault())
|
||||||
wantVRR = false;
|
wantVRR = false;
|
||||||
|
|
||||||
if (wantVRR && USEVRR == 3) {
|
if (wantVRR && USEVRR == 3) {
|
||||||
|
|
@ -1963,10 +1831,6 @@ const std::vector<SWorkspaceRule>& CConfigManager::getAllWorkspaceRules() {
|
||||||
return m_workspaceRules;
|
return m_workspaceRules;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConfigManager::addExecRule(const SExecRequestedRule& rule) {
|
|
||||||
m_execRequestedRules.push_back(rule);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CConfigManager::handlePluginLoads() {
|
void CConfigManager::handlePluginLoads() {
|
||||||
if (!g_pPluginSystem)
|
if (!g_pPluginSystem)
|
||||||
return;
|
return;
|
||||||
|
|
@ -2675,239 +2539,6 @@ std::optional<std::string> CConfigManager::handleUnbind(const std::string& comma
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> CConfigManager::handleWindowRule(const std::string& command, const std::string& value) {
|
|
||||||
const auto VARLIST = CVarList(value, 0, ',', true);
|
|
||||||
|
|
||||||
std::vector<std::string_view> tokens;
|
|
||||||
std::unordered_map<std::string_view, std::string_view> params;
|
|
||||||
|
|
||||||
bool parsingParams = false;
|
|
||||||
|
|
||||||
for (const auto& varStr : VARLIST) {
|
|
||||||
std::string_view var = varStr;
|
|
||||||
auto sep = var.find(':');
|
|
||||||
std::string_view key = (sep != std::string_view::npos) ? var.substr(0, sep) : var;
|
|
||||||
bool isParam = (sep != std::string_view::npos && !(key.starts_with("workspace ") || (key.starts_with("monitor ")) || key.ends_with("plugin")));
|
|
||||||
|
|
||||||
if (!parsingParams) {
|
|
||||||
if (!isParam) {
|
|
||||||
tokens.emplace_back(var);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
parsingParams = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sep == std::string_view::npos)
|
|
||||||
return std::format("Invalid rule: {}, Invalid parameter: {}", value, std::string(var));
|
|
||||||
|
|
||||||
auto pos = var.find_first_not_of(' ', sep + 1);
|
|
||||||
std::string_view val = (pos != std::string_view::npos) ? var.substr(pos) : std::string_view{};
|
|
||||||
params[key] = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto get = [&](std::string_view key) -> std::string_view {
|
|
||||||
if (auto it = params.find(key); it != params.end())
|
|
||||||
return it->second;
|
|
||||||
return {};
|
|
||||||
};
|
|
||||||
|
|
||||||
auto applyParams = [&](SP<CWindowRule> rule) -> bool {
|
|
||||||
bool set = false;
|
|
||||||
|
|
||||||
if (auto v = get("class"); !v.empty()) {
|
|
||||||
set |= (rule->m_class = v, true);
|
|
||||||
rule->m_classRegex = {std::string(v)};
|
|
||||||
}
|
|
||||||
if (auto v = get("title"); !v.empty()) {
|
|
||||||
set |= (rule->m_title = v, true);
|
|
||||||
rule->m_titleRegex = {std::string(v)};
|
|
||||||
}
|
|
||||||
if (auto v = get("tag"); !v.empty())
|
|
||||||
set |= (rule->m_tag = v, true);
|
|
||||||
if (auto v = get("initialClass"); !v.empty()) {
|
|
||||||
set |= (rule->m_initialClass = v, true);
|
|
||||||
rule->m_initialClassRegex = {std::string(v)};
|
|
||||||
}
|
|
||||||
if (auto v = get("initialTitle"); !v.empty()) {
|
|
||||||
set |= (rule->m_initialTitle = v, true);
|
|
||||||
rule->m_initialTitleRegex = {std::string(v)};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto v = get("xwayland"); !v.empty())
|
|
||||||
set |= (rule->m_X11 = (v == "1"), true);
|
|
||||||
if (auto v = get("floating"); !v.empty())
|
|
||||||
set |= (rule->m_floating = (v == "1"), true);
|
|
||||||
if (auto v = get("fullscreen"); !v.empty())
|
|
||||||
set |= (rule->m_fullscreen = (v == "1"), true);
|
|
||||||
if (auto v = get("pinned"); !v.empty())
|
|
||||||
set |= (rule->m_pinned = (v == "1"), true);
|
|
||||||
if (auto v = get("focus"); !v.empty())
|
|
||||||
set |= (rule->m_focus = (v == "1"), true);
|
|
||||||
if (auto v = get("group"); !v.empty())
|
|
||||||
set |= (rule->m_group = (v == "1"), true);
|
|
||||||
if (auto v = get("modal"); !v.empty())
|
|
||||||
set |= (rule->m_modal = (v == "1"), true);
|
|
||||||
|
|
||||||
if (auto v = get("fullscreenstate"); !v.empty())
|
|
||||||
set |= (rule->m_fullscreenState = v, true);
|
|
||||||
if (auto v = get("workspace"); !v.empty())
|
|
||||||
set |= (rule->m_workspace = v, true);
|
|
||||||
if (auto v = get("onworkspace"); !v.empty())
|
|
||||||
set |= (rule->m_onWorkspace = v, true);
|
|
||||||
if (auto v = get("content"); !v.empty())
|
|
||||||
set |= (rule->m_contentType = v, true);
|
|
||||||
if (auto v = get("xdgTag"); !v.empty())
|
|
||||||
set |= (rule->m_xdgTag = v, true);
|
|
||||||
|
|
||||||
return set;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<SP<CWindowRule>> rules;
|
|
||||||
|
|
||||||
for (auto token : tokens) {
|
|
||||||
if (token.starts_with("unset")) {
|
|
||||||
std::string ruleName = "";
|
|
||||||
if (token.size() <= 6 || token.contains("all"))
|
|
||||||
ruleName = "all";
|
|
||||||
else
|
|
||||||
ruleName = std::string(token.substr(6));
|
|
||||||
auto rule = makeShared<CWindowRule>(ruleName, value, true);
|
|
||||||
applyParams(rule);
|
|
||||||
std::erase_if(m_windowRules, [&](const auto& other) {
|
|
||||||
if (!other->m_v2)
|
|
||||||
return other->m_class == rule->m_class && !rule->m_class.empty();
|
|
||||||
|
|
||||||
if (rule->m_ruleType != other->m_ruleType && ruleName != "all")
|
|
||||||
return false;
|
|
||||||
if (!rule->m_tag.empty() && rule->m_tag != other->m_tag)
|
|
||||||
return false;
|
|
||||||
if (!rule->m_class.empty() && rule->m_class != other->m_class)
|
|
||||||
return false;
|
|
||||||
if (!rule->m_title.empty() && rule->m_title != other->m_title)
|
|
||||||
return false;
|
|
||||||
if (!rule->m_initialClass.empty() && rule->m_initialClass != other->m_initialClass)
|
|
||||||
return false;
|
|
||||||
if (!rule->m_initialTitle.empty() && rule->m_initialTitle != other->m_initialTitle)
|
|
||||||
return false;
|
|
||||||
if (rule->m_X11 != -1 && rule->m_X11 != other->m_X11)
|
|
||||||
return false;
|
|
||||||
if (rule->m_floating != -1 && rule->m_floating != other->m_floating)
|
|
||||||
return false;
|
|
||||||
if (rule->m_fullscreen != -1 && rule->m_fullscreen != other->m_fullscreen)
|
|
||||||
return false;
|
|
||||||
if (rule->m_pinned != -1 && rule->m_pinned != other->m_pinned)
|
|
||||||
return false;
|
|
||||||
if (!rule->m_fullscreenState.empty() && rule->m_fullscreenState != other->m_fullscreenState)
|
|
||||||
return false;
|
|
||||||
if (!rule->m_workspace.empty() && rule->m_workspace != other->m_workspace)
|
|
||||||
return false;
|
|
||||||
if (rule->m_focus != -1 && rule->m_focus != other->m_focus)
|
|
||||||
return false;
|
|
||||||
if (!rule->m_onWorkspace.empty() && rule->m_onWorkspace != other->m_onWorkspace)
|
|
||||||
return false;
|
|
||||||
if (!rule->m_contentType.empty() && rule->m_contentType != other->m_contentType)
|
|
||||||
return false;
|
|
||||||
if (rule->m_group != -1 && rule->m_group != other->m_group)
|
|
||||||
return false;
|
|
||||||
if (rule->m_modal != -1 && rule->m_modal != other->m_modal)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
auto rule = makeShared<CWindowRule>(std::string(token), value, true);
|
|
||||||
if (rule->m_ruleType == CWindowRule::RULE_INVALID) {
|
|
||||||
Debug::log(ERR, "Invalid rule found: {}, Invalid value: {}", value, token);
|
|
||||||
return std::format("Invalid rule found: {}, Invalid value: {}", value, token);
|
|
||||||
}
|
|
||||||
if (applyParams(rule))
|
|
||||||
rules.emplace_back(rule);
|
|
||||||
else {
|
|
||||||
Debug::log(INFO, "===== Skipping rule: {}, Invalid parameters", rule->m_value);
|
|
||||||
return std::format("Invalid parameters found in: {}", value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rules.empty() && tokens.empty())
|
|
||||||
return "Invalid rule syntax: no rules provided";
|
|
||||||
|
|
||||||
for (auto& rule : rules) {
|
|
||||||
if (rule->m_ruleType == CWindowRule::RULE_SIZE || rule->m_ruleType == CWindowRule::RULE_MAXSIZE || rule->m_ruleType == CWindowRule::RULE_MINSIZE)
|
|
||||||
m_windowRules.insert(m_windowRules.begin(), rule);
|
|
||||||
else
|
|
||||||
m_windowRules.emplace_back(rule);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<std::string> CConfigManager::handleLayerRule(const std::string& command, const std::string& value) {
|
|
||||||
const auto RULE = trim(value.substr(0, value.find_first_of(',')));
|
|
||||||
const auto VALUE = trim(value.substr(value.find_first_of(',') + 1));
|
|
||||||
|
|
||||||
// check rule and value
|
|
||||||
if (RULE.empty() || VALUE.empty())
|
|
||||||
return "empty rule?";
|
|
||||||
|
|
||||||
if (RULE == "unset") {
|
|
||||||
std::erase_if(m_layerRules, [&](const auto& other) { return other->m_targetNamespace == VALUE; });
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto rule = makeShared<CLayerRule>(RULE, VALUE);
|
|
||||||
|
|
||||||
if (rule->m_ruleType == CLayerRule::RULE_INVALID) {
|
|
||||||
Debug::log(ERR, "Invalid rule found: {}", RULE);
|
|
||||||
return "Invalid rule found: " + RULE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rule->m_targetNamespaceRegex = {VALUE};
|
|
||||||
|
|
||||||
m_layerRules.emplace_back(rule);
|
|
||||||
|
|
||||||
for (auto const& m : g_pCompositor->m_monitors)
|
|
||||||
for (auto const& lsl : m->m_layerSurfaceLayers)
|
|
||||||
for (auto const& ls : lsl)
|
|
||||||
ls->applyRules();
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
void CConfigManager::updateBlurredLS(const std::string& name, const bool forceBlur) {
|
|
||||||
const bool BYADDRESS = name.starts_with("address:");
|
|
||||||
std::string matchName = name;
|
|
||||||
|
|
||||||
if (BYADDRESS)
|
|
||||||
matchName = matchName.substr(8);
|
|
||||||
|
|
||||||
for (auto const& m : g_pCompositor->m_monitors) {
|
|
||||||
for (auto const& lsl : m->m_layerSurfaceLayers) {
|
|
||||||
for (auto const& ls : lsl) {
|
|
||||||
if (BYADDRESS) {
|
|
||||||
if (std::format("0x{:x}", rc<uintptr_t>(ls.get())) == matchName)
|
|
||||||
ls->m_forceBlur = forceBlur;
|
|
||||||
} else if (ls->m_namespace == matchName)
|
|
||||||
ls->m_forceBlur = forceBlur;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<std::string> CConfigManager::handleBlurLS(const std::string& command, const std::string& value) {
|
|
||||||
if (value.starts_with("remove,")) {
|
|
||||||
const auto TOREMOVE = trim(value.substr(7));
|
|
||||||
if (std::erase_if(m_blurLSNamespaces, [&](const auto& other) { return other == TOREMOVE; }))
|
|
||||||
updateBlurredLS(TOREMOVE, false);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
m_blurLSNamespaces.emplace_back(value);
|
|
||||||
updateBlurredLS(value, true);
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<std::string> CConfigManager::handleWorkspaceRules(const std::string& command, const std::string& value) {
|
std::optional<std::string> CConfigManager::handleWorkspaceRules(const std::string& command, const std::string& value) {
|
||||||
// This can either be the monitor or the workspace identifier
|
// This can either be the monitor or the workspace identifier
|
||||||
const auto FIRST_DELIM = value.find_first_of(',');
|
const auto FIRST_DELIM = value.find_first_of(',');
|
||||||
|
|
@ -3228,6 +2859,82 @@ std::optional<std::string> CConfigManager::handleGesture(const std::string& comm
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> CConfigManager::handleWindowrule(const std::string& command, const std::string& value) {
|
||||||
|
CVarList2 data(std::string{value}, 0, ',');
|
||||||
|
|
||||||
|
SP<Desktop::Rule::CWindowRule> rule = makeShared<Desktop::Rule::CWindowRule>();
|
||||||
|
|
||||||
|
const auto& PROPS = Desktop::Rule::allMatchPropStrings();
|
||||||
|
const auto& EFFECTS = Desktop::Rule::windowEffects()->allEffectStrings();
|
||||||
|
|
||||||
|
for (const auto& el : data) {
|
||||||
|
// split on space, no need for a CVarList here
|
||||||
|
size_t spacePos = el.find(' ');
|
||||||
|
if (spacePos == std::string::npos)
|
||||||
|
return std::format("invalid field {}: missing a value", el);
|
||||||
|
|
||||||
|
const bool FIRST_IS_PROP = el.starts_with("match:");
|
||||||
|
const auto FIRST = FIRST_IS_PROP ? el.substr(6, spacePos - 6) : el.substr(0, spacePos);
|
||||||
|
if (FIRST_IS_PROP && std::ranges::contains(PROPS, FIRST)) {
|
||||||
|
// it's a prop
|
||||||
|
const auto PROP = Desktop::Rule::matchPropFromString(FIRST);
|
||||||
|
if (!PROP.has_value())
|
||||||
|
return std::format("invalid prop {}", el);
|
||||||
|
rule->registerMatch(*PROP, std::string{el.substr(spacePos + 1)});
|
||||||
|
} else if (!FIRST_IS_PROP && std::ranges::contains(EFFECTS, FIRST)) {
|
||||||
|
// it's an effect
|
||||||
|
const auto EFFECT = Desktop::Rule::windowEffects()->get(FIRST);
|
||||||
|
if (!EFFECT.has_value())
|
||||||
|
return std::format("invalid effect {}", el);
|
||||||
|
rule->addEffect(*EFFECT, std::string{el.substr(spacePos + 1)});
|
||||||
|
} else
|
||||||
|
return std::format("invalid field type {}", FIRST);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_keywordRules.emplace_back(std::move(rule));
|
||||||
|
if (g_pHyprCtl && g_pHyprCtl->m_currentRequestParams.isDynamicKeyword)
|
||||||
|
Desktop::Rule::ruleEngine()->registerRule(SP<Desktop::Rule::IRule>{m_keywordRules.back()});
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> CConfigManager::handleLayerrule(const std::string& command, const std::string& value) {
|
||||||
|
CVarList2 data(std::string{value}, 0, ',');
|
||||||
|
|
||||||
|
SP<Desktop::Rule::CLayerRule> rule = makeShared<Desktop::Rule::CLayerRule>();
|
||||||
|
|
||||||
|
const auto& PROPS = Desktop::Rule::allMatchPropStrings();
|
||||||
|
const auto& EFFECTS = Desktop::Rule::layerEffects()->allEffectStrings();
|
||||||
|
|
||||||
|
for (const auto& el : data) {
|
||||||
|
// split on space, no need for a CVarList here
|
||||||
|
size_t spacePos = el.find(' ');
|
||||||
|
if (spacePos == std::string::npos)
|
||||||
|
return std::format("invalid field {}: missing a value", el);
|
||||||
|
|
||||||
|
const bool FIRST_IS_PROP = el.starts_with("match:");
|
||||||
|
const auto FIRST = FIRST_IS_PROP ? el.substr(6, spacePos - 6) : el.substr(0, spacePos);
|
||||||
|
if (FIRST_IS_PROP && std::ranges::contains(PROPS, FIRST)) {
|
||||||
|
// it's a prop
|
||||||
|
const auto PROP = Desktop::Rule::matchPropFromString(FIRST);
|
||||||
|
if (!PROP.has_value())
|
||||||
|
return std::format("invalid prop {}", el);
|
||||||
|
rule->registerMatch(*PROP, std::string{el.substr(spacePos + 1)});
|
||||||
|
} else if (!FIRST_IS_PROP && std::ranges::contains(EFFECTS, FIRST)) {
|
||||||
|
// it's an effect
|
||||||
|
const auto EFFECT = Desktop::Rule::layerEffects()->get(FIRST);
|
||||||
|
if (!EFFECT.has_value())
|
||||||
|
return std::format("invalid effect {}", el);
|
||||||
|
rule->addEffect(*EFFECT, std::string{el.substr(spacePos + 1)});
|
||||||
|
} else
|
||||||
|
return std::format("invalid field type {}", FIRST);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_keywordRules.emplace_back(std::move(rule));
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<SConfigOptionDescription>& CConfigManager::getAllDescriptions() {
|
const std::vector<SConfigOptionDescription>& CConfigManager::getAllDescriptions() {
|
||||||
return CONFIG_OPTIONS;
|
return CONFIG_OPTIONS;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,12 @@
|
||||||
#include <xf86drmMode.h>
|
#include <xf86drmMode.h>
|
||||||
#include "../helpers/Monitor.hpp"
|
#include "../helpers/Monitor.hpp"
|
||||||
#include "../desktop/Window.hpp"
|
#include "../desktop/Window.hpp"
|
||||||
#include "../desktop/LayerRule.hpp"
|
|
||||||
|
|
||||||
#include "ConfigDataValues.hpp"
|
#include "ConfigDataValues.hpp"
|
||||||
#include "../SharedDefs.hpp"
|
#include "../SharedDefs.hpp"
|
||||||
#include "../helpers/Color.hpp"
|
#include "../helpers/Color.hpp"
|
||||||
#include "../desktop/DesktopTypes.hpp"
|
#include "../desktop/DesktopTypes.hpp"
|
||||||
#include "../helpers/memory/Memory.hpp"
|
#include "../helpers/memory/Memory.hpp"
|
||||||
#include "../desktop/WindowRule.hpp"
|
|
||||||
#include "../managers/XWaylandManager.hpp"
|
#include "../managers/XWaylandManager.hpp"
|
||||||
#include "../managers/KeybindManager.hpp"
|
#include "../managers/KeybindManager.hpp"
|
||||||
|
|
||||||
|
|
@ -68,11 +66,6 @@ struct SPluginVariable {
|
||||||
std::string name = "";
|
std::string name = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SExecRequestedRule {
|
|
||||||
std::string szRule = "";
|
|
||||||
uint64_t iPid = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum eConfigOptionType : uint8_t {
|
enum eConfigOptionType : uint8_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*/
|
||||||
|
|
@ -214,7 +207,6 @@ class CConfigManager {
|
||||||
bool deviceConfigExplicitlySet(const std::string&, const std::string&);
|
bool deviceConfigExplicitlySet(const std::string&, const std::string&);
|
||||||
bool deviceConfigExists(const std::string&);
|
bool deviceConfigExists(const std::string&);
|
||||||
Hyprlang::CConfigValue* getConfigValueSafeDevice(const std::string& dev, const std::string& val, const std::string& fallback);
|
Hyprlang::CConfigValue* getConfigValueSafeDevice(const std::string& dev, const std::string& val, const std::string& fallback);
|
||||||
bool shouldBlurLS(const std::string&);
|
|
||||||
|
|
||||||
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 = "");
|
||||||
|
|
@ -229,8 +221,6 @@ class CConfigManager {
|
||||||
std::string getBoundMonitorStringForWS(const std::string&);
|
std::string getBoundMonitorStringForWS(const std::string&);
|
||||||
const std::vector<SWorkspaceRule>& getAllWorkspaceRules();
|
const std::vector<SWorkspaceRule>& getAllWorkspaceRules();
|
||||||
|
|
||||||
std::vector<SP<CWindowRule>> getMatchingRules(PHLWINDOW, bool dynamic = true, bool shadowExec = false);
|
|
||||||
std::vector<SP<CLayerRule>> getMatchingRules(PHLLS);
|
|
||||||
void ensurePersistentWorkspacesPresent();
|
void ensurePersistentWorkspacesPresent();
|
||||||
|
|
||||||
const std::vector<SConfigOptionDescription>& getAllDescriptions();
|
const std::vector<SConfigOptionDescription>& getAllDescriptions();
|
||||||
|
|
@ -260,8 +250,6 @@ class CConfigManager {
|
||||||
|
|
||||||
SP<Hyprutils::Animation::SAnimationPropertyConfig> getAnimationPropertyConfig(const std::string&);
|
SP<Hyprutils::Animation::SAnimationPropertyConfig> getAnimationPropertyConfig(const std::string&);
|
||||||
|
|
||||||
void addExecRule(const SExecRequestedRule&);
|
|
||||||
|
|
||||||
void handlePluginLoads();
|
void handlePluginLoads();
|
||||||
std::string getErrors();
|
std::string getErrors();
|
||||||
|
|
||||||
|
|
@ -274,22 +262,24 @@ class CConfigManager {
|
||||||
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&);
|
||||||
std::optional<std::string> handleWindowRule(const std::string&, const std::string&);
|
|
||||||
std::optional<std::string> handleLayerRule(const std::string&, const std::string&);
|
|
||||||
std::optional<std::string> handleWorkspaceRules(const std::string&, const std::string&);
|
std::optional<std::string> handleWorkspaceRules(const std::string&, const std::string&);
|
||||||
std::optional<std::string> handleBezier(const std::string&, const std::string&);
|
std::optional<std::string> handleBezier(const std::string&, const std::string&);
|
||||||
std::optional<std::string> handleAnimation(const std::string&, const std::string&);
|
std::optional<std::string> handleAnimation(const std::string&, const std::string&);
|
||||||
std::optional<std::string> handleSource(const std::string&, const std::string&);
|
std::optional<std::string> handleSource(const std::string&, const std::string&);
|
||||||
std::optional<std::string> handleSubmap(const std::string&, const std::string&);
|
std::optional<std::string> handleSubmap(const std::string&, const std::string&);
|
||||||
std::optional<std::string> handleBlurLS(const std::string&, const std::string&);
|
|
||||||
std::optional<std::string> handleBindWS(const std::string&, const std::string&);
|
std::optional<std::string> handleBindWS(const std::string&, const std::string&);
|
||||||
std::optional<std::string> handleEnv(const std::string&, const std::string&);
|
std::optional<std::string> handleEnv(const std::string&, const std::string&);
|
||||||
std::optional<std::string> handlePlugin(const std::string&, const std::string&);
|
std::optional<std::string> handlePlugin(const std::string&, const std::string&);
|
||||||
std::optional<std::string> handlePermission(const std::string&, const std::string&);
|
std::optional<std::string> handlePermission(const std::string&, const std::string&);
|
||||||
std::optional<std::string> handleGesture(const std::string&, const std::string&);
|
std::optional<std::string> handleGesture(const std::string&, const std::string&);
|
||||||
|
std::optional<std::string> handleWindowrule(const std::string&, const std::string&);
|
||||||
|
std::optional<std::string> handleLayerrule(const std::string&, const std::string&);
|
||||||
|
|
||||||
std::optional<std::string> handleMonitorv2(const std::string& output);
|
std::optional<std::string> handleMonitorv2(const std::string& output);
|
||||||
Hyprlang::CParseResult handleMonitorv2();
|
Hyprlang::CParseResult handleMonitorv2();
|
||||||
|
std::optional<std::string> addRuleFromConfigKey(const std::string& name);
|
||||||
|
std::optional<std::string> addLayerRuleFromConfigKey(const std::string& name);
|
||||||
|
Hyprlang::CParseResult reloadRules();
|
||||||
|
|
||||||
std::string m_configCurrentPath;
|
std::string m_configCurrentPath;
|
||||||
|
|
||||||
|
|
@ -310,19 +300,16 @@ class CConfigManager {
|
||||||
|
|
||||||
SSubmap m_currentSubmap;
|
SSubmap m_currentSubmap;
|
||||||
|
|
||||||
std::vector<SExecRequestedRule> m_execRequestedRules; // rules requested with exec, e.g. [workspace 2] kitty
|
|
||||||
|
|
||||||
std::vector<std::string> m_declaredPlugins;
|
std::vector<std::string> m_declaredPlugins;
|
||||||
std::vector<SPluginKeyword> m_pluginKeywords;
|
std::vector<SPluginKeyword> m_pluginKeywords;
|
||||||
std::vector<SPluginVariable> m_pluginVariables;
|
std::vector<SPluginVariable> m_pluginVariables;
|
||||||
|
|
||||||
|
std::vector<SP<Desktop::Rule::IRule>> m_keywordRules;
|
||||||
|
|
||||||
bool m_isFirstLaunch = true; // For exec-once
|
bool m_isFirstLaunch = true; // For exec-once
|
||||||
|
|
||||||
std::vector<SMonitorRule> m_monitorRules;
|
std::vector<SMonitorRule> m_monitorRules;
|
||||||
std::vector<SWorkspaceRule> m_workspaceRules;
|
std::vector<SWorkspaceRule> m_workspaceRules;
|
||||||
std::vector<SP<CWindowRule>> m_windowRules;
|
|
||||||
std::vector<SP<CLayerRule>> m_layerRules;
|
|
||||||
std::vector<std::string> m_blurLSNamespaces;
|
|
||||||
|
|
||||||
bool m_firstExecDispatched = false;
|
bool m_firstExecDispatched = false;
|
||||||
bool m_manualCrashInitiated = false;
|
bool m_manualCrashInitiated = false;
|
||||||
|
|
@ -336,11 +323,11 @@ class CConfigManager {
|
||||||
uint32_t m_configValueNumber = 0;
|
uint32_t m_configValueNumber = 0;
|
||||||
|
|
||||||
// internal methods
|
// internal methods
|
||||||
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);
|
std::optional<std::string> generateConfig(std::string configPath);
|
||||||
std::optional<std::string> verifyConfigExists();
|
std::optional<std::string> verifyConfigExists();
|
||||||
|
void reloadRuleConfigs();
|
||||||
|
|
||||||
void postConfigReload(const Hyprlang::CParseResult& result);
|
void postConfigReload(const Hyprlang::CParseResult& result);
|
||||||
SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&);
|
SWorkspaceRule mergeWorkspaceRules(const SWorkspaceRule&, const SWorkspaceRule&);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#include "ConfigWatcher.hpp"
|
#include "ConfigWatcher.hpp"
|
||||||
|
#if defined(__linux__)
|
||||||
#include <linux/limits.h>
|
#include <linux/limits.h>
|
||||||
|
#endif
|
||||||
#include <sys/inotify.h>
|
#include <sys/inotify.h>
|
||||||
#include "../debug/Log.hpp"
|
#include "../debug/Log.hpp"
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ using namespace Hyprutils::OS;
|
||||||
#include "config/ConfigManager.hpp"
|
#include "config/ConfigManager.hpp"
|
||||||
#include "helpers/MiscFunctions.hpp"
|
#include "helpers/MiscFunctions.hpp"
|
||||||
#include "../desktop/LayerSurface.hpp"
|
#include "../desktop/LayerSurface.hpp"
|
||||||
|
#include "../desktop/rule/Engine.hpp"
|
||||||
#include "../version.h"
|
#include "../version.h"
|
||||||
|
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
|
|
@ -317,7 +318,7 @@ static std::string monitorsRequest(eHyprCtlOutputFormat format, std::string requ
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string getTagsData(PHLWINDOW w, eHyprCtlOutputFormat format) {
|
static std::string getTagsData(PHLWINDOW w, eHyprCtlOutputFormat format) {
|
||||||
const auto tags = w->m_tags.getTags();
|
const auto tags = w->m_ruleApplicator->m_tagKeeper.getTags();
|
||||||
|
|
||||||
if (format == eHyprCtlOutputFormat::FORMAT_JSON)
|
if (format == eHyprCtlOutputFormat::FORMAT_JSON)
|
||||||
return std::ranges::fold_left(tags, std::string(),
|
return std::ranges::fold_left(tags, std::string(),
|
||||||
|
|
@ -1272,8 +1273,12 @@ static std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in)
|
||||||
if (COMMAND.empty())
|
if (COMMAND.empty())
|
||||||
return "Invalid input: command is empty";
|
return "Invalid input: command is empty";
|
||||||
|
|
||||||
|
g_pHyprCtl->m_currentRequestParams.isDynamicKeyword = true;
|
||||||
|
|
||||||
std::string retval = g_pConfigManager->parseKeyword(COMMAND, VALUE);
|
std::string retval = g_pConfigManager->parseKeyword(COMMAND, VALUE);
|
||||||
|
|
||||||
|
g_pHyprCtl->m_currentRequestParams.isDynamicKeyword = false;
|
||||||
|
|
||||||
// if we are executing a dynamic source we have to reload everything, so every if will have a check for source.
|
// if we are executing a dynamic source we have to reload everything, so every if will have a check for source.
|
||||||
if (COMMAND == "monitor" || COMMAND == "source")
|
if (COMMAND == "monitor" || COMMAND == "source")
|
||||||
g_pConfigManager->m_wantsMonitorReload = true; // for monitor keywords
|
g_pConfigManager->m_wantsMonitorReload = true; // for monitor keywords
|
||||||
|
|
@ -1306,8 +1311,7 @@ static std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in)
|
||||||
g_pConfigManager->updateWatcher();
|
g_pConfigManager->updateWatcher();
|
||||||
|
|
||||||
// decorations will probably need a repaint
|
// decorations will probably need a repaint
|
||||||
if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("zoom_factor") || COMMAND == "source" ||
|
if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("zoom_factor") || COMMAND == "source") {
|
||||||
COMMAND.starts_with("windowrule")) {
|
|
||||||
static auto PZOOMFACTOR = CConfigValue<Hyprlang::FLOAT>("cursor:zoom_factor");
|
static auto PZOOMFACTOR = CConfigValue<Hyprlang::FLOAT>("cursor:zoom_factor");
|
||||||
for (auto const& m : g_pCompositor->m_monitors) {
|
for (auto const& m : g_pCompositor->m_monitors) {
|
||||||
*(m->m_cursorZoom) = *PZOOMFACTOR;
|
*(m->m_cursorZoom) = *PZOOMFACTOR;
|
||||||
|
|
@ -1316,6 +1320,9 @@ static std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (COMMAND.contains("windowrule ") || COMMAND.contains("windowrule["))
|
||||||
|
g_pConfigManager->reloadRules();
|
||||||
|
|
||||||
if (COMMAND.contains("workspace"))
|
if (COMMAND.contains("workspace"))
|
||||||
g_pConfigManager->ensurePersistentWorkspacesPresent();
|
g_pConfigManager->ensurePersistentWorkspacesPresent();
|
||||||
|
|
||||||
|
|
@ -1521,11 +1528,6 @@ static std::string dispatchSeterror(eHyprCtlOutputFormat format, std::string req
|
||||||
return "ok";
|
return "ok";
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string dispatchSetProp(eHyprCtlOutputFormat format, std::string request) {
|
|
||||||
auto result = g_pKeybindManager->m_dispatchers["setprop"](request.substr(request.find_first_of(' ') + 1));
|
|
||||||
return "DEPRECATED: use hyprctl dispatch setprop instead" + (result.success ? "" : "\n" + result.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string dispatchGetProp(eHyprCtlOutputFormat format, std::string request) {
|
static std::string dispatchGetProp(eHyprCtlOutputFormat format, std::string request) {
|
||||||
CVarList vars(request, 0, ' ');
|
CVarList vars(request, 0, ' ');
|
||||||
|
|
||||||
|
|
@ -1543,9 +1545,9 @@ static std::string dispatchGetProp(eHyprCtlOutputFormat format, std::string requ
|
||||||
const bool FORMNORM = format == FORMAT_NORMAL;
|
const bool FORMNORM = format == FORMAT_NORMAL;
|
||||||
|
|
||||||
auto sizeToString = [&](bool max) -> std::string {
|
auto sizeToString = [&](bool max) -> std::string {
|
||||||
auto sizeValue = PWINDOW->m_windowData.minSize.valueOr(Vector2D(MIN_WINDOW_SIZE, MIN_WINDOW_SIZE));
|
auto sizeValue = PWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D(MIN_WINDOW_SIZE, MIN_WINDOW_SIZE));
|
||||||
if (max)
|
if (max)
|
||||||
sizeValue = PWINDOW->m_windowData.maxSize.valueOr(Vector2D(INFINITY, INFINITY));
|
sizeValue = PWINDOW->m_ruleApplicator->maxSize().valueOr(Vector2D(INFINITY, INFINITY));
|
||||||
|
|
||||||
if (FORMNORM)
|
if (FORMNORM)
|
||||||
return std::format("{} {}", sizeValue.x, sizeValue.y);
|
return std::format("{} {}", sizeValue.x, sizeValue.y);
|
||||||
|
|
@ -1556,7 +1558,7 @@ static std::string dispatchGetProp(eHyprCtlOutputFormat format, std::string requ
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto alphaToString = [&](CWindowOverridableVar<SAlphaValue>& alpha, bool getAlpha) -> std::string {
|
auto alphaToString = [&](Desktop::Types::COverridableVar<Desktop::Types::SAlphaValue>& alpha, bool getAlpha) -> std::string {
|
||||||
if (FORMNORM) {
|
if (FORMNORM) {
|
||||||
if (getAlpha)
|
if (getAlpha)
|
||||||
return std::format("{}", alpha.valueOrDefault().alpha);
|
return std::format("{}", alpha.valueOrDefault().alpha);
|
||||||
|
|
@ -1590,7 +1592,7 @@ static std::string dispatchGetProp(eHyprCtlOutputFormat format, std::string requ
|
||||||
const auto* const ACTIVECOLOR =
|
const auto* const ACTIVECOLOR =
|
||||||
!PWINDOW->m_groupData.pNextWindow.lock() ? (!PWINDOW->m_groupData.deny ? ACTIVECOL : NOGROUPACTIVECOL) : (GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL);
|
!PWINDOW->m_groupData.pNextWindow.lock() ? (!PWINDOW->m_groupData.deny ? ACTIVECOL : NOGROUPACTIVECOL) : (GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL);
|
||||||
|
|
||||||
std::string borderColorString = PWINDOW->m_windowData.activeBorderColor.valueOr(*ACTIVECOLOR).toString();
|
std::string borderColorString = PWINDOW->m_ruleApplicator->activeBorderColor().valueOr(*ACTIVECOLOR).toString();
|
||||||
if (FORMNORM)
|
if (FORMNORM)
|
||||||
return borderColorString;
|
return borderColorString;
|
||||||
else
|
else
|
||||||
|
|
@ -1603,7 +1605,7 @@ static std::string dispatchGetProp(eHyprCtlOutputFormat format, std::string requ
|
||||||
const auto* const INACTIVECOLOR = !PWINDOW->m_groupData.pNextWindow.lock() ? (!PWINDOW->m_groupData.deny ? INACTIVECOL : NOGROUPINACTIVECOL) :
|
const auto* const INACTIVECOLOR = !PWINDOW->m_groupData.pNextWindow.lock() ? (!PWINDOW->m_groupData.deny ? INACTIVECOL : NOGROUPINACTIVECOL) :
|
||||||
(GROUPLOCKED ? GROUPINACTIVELOCKEDCOL : GROUPINACTIVECOL);
|
(GROUPLOCKED ? GROUPINACTIVELOCKEDCOL : GROUPINACTIVECOL);
|
||||||
|
|
||||||
std::string borderColorString = PWINDOW->m_windowData.inactiveBorderColor.valueOr(*INACTIVECOLOR).toString();
|
std::string borderColorString = PWINDOW->m_ruleApplicator->inactiveBorderColor().valueOr(*INACTIVECOLOR).toString();
|
||||||
if (FORMNORM)
|
if (FORMNORM)
|
||||||
return borderColorString;
|
return borderColorString;
|
||||||
else
|
else
|
||||||
|
|
@ -1618,38 +1620,92 @@ static std::string dispatchGetProp(eHyprCtlOutputFormat format, std::string requ
|
||||||
return std::format(R"({{"{}": {}}})", PROP, prop.valueOrDefault());
|
return std::format(R"({{"{}": {}}})", PROP, prop.valueOrDefault());
|
||||||
};
|
};
|
||||||
|
|
||||||
if (PROP == "animationstyle") {
|
if (PROP == "animation") {
|
||||||
auto& animationStyle = PWINDOW->m_windowData.animationStyle;
|
auto& animationStyle = PWINDOW->m_ruleApplicator->animationStyle();
|
||||||
if (FORMNORM)
|
if (FORMNORM)
|
||||||
return animationStyle.valueOr("(unset)");
|
return animationStyle.valueOr("(unset)");
|
||||||
else
|
else
|
||||||
return std::format(R"({{"{}": "{}"}})", PROP, animationStyle.valueOr(""));
|
return std::format(R"({{"{}": "{}"}})", PROP, animationStyle.valueOr(""));
|
||||||
} else if (PROP == "maxsize")
|
} else if (PROP == "max_size")
|
||||||
return sizeToString(true);
|
return sizeToString(true);
|
||||||
else if (PROP == "minsize")
|
else if (PROP == "min_size")
|
||||||
return sizeToString(false);
|
return sizeToString(false);
|
||||||
else if (PROP == "alpha")
|
else if (PROP == "opacity")
|
||||||
return alphaToString(PWINDOW->m_windowData.alpha, true);
|
return alphaToString(PWINDOW->m_ruleApplicator->alpha(), true);
|
||||||
else if (PROP == "alphainactive")
|
else if (PROP == "opacity_inactive")
|
||||||
return alphaToString(PWINDOW->m_windowData.alphaInactive, true);
|
return alphaToString(PWINDOW->m_ruleApplicator->alphaInactive(), true);
|
||||||
else if (PROP == "alphafullscreen")
|
else if (PROP == "opacity_fullscreen")
|
||||||
return alphaToString(PWINDOW->m_windowData.alphaFullscreen, true);
|
return alphaToString(PWINDOW->m_ruleApplicator->alphaFullscreen(), true);
|
||||||
else if (PROP == "alphaoverride")
|
else if (PROP == "opacity_override")
|
||||||
return alphaToString(PWINDOW->m_windowData.alpha, false);
|
return alphaToString(PWINDOW->m_ruleApplicator->alpha(), false);
|
||||||
else if (PROP == "alphainactiveoverride")
|
else if (PROP == "opacity_inactive_override")
|
||||||
return alphaToString(PWINDOW->m_windowData.alphaInactive, false);
|
return alphaToString(PWINDOW->m_ruleApplicator->alphaInactive(), false);
|
||||||
else if (PROP == "alphafullscreenoverride")
|
else if (PROP == "opacity_fullscreen_override")
|
||||||
return alphaToString(PWINDOW->m_windowData.alphaFullscreen, false);
|
return alphaToString(PWINDOW->m_ruleApplicator->alphaFullscreen(), false);
|
||||||
else if (PROP == "activebordercolor")
|
else if (PROP == "active_border_color")
|
||||||
return borderColorToString(true);
|
return borderColorToString(true);
|
||||||
else if (PROP == "inactivebordercolor")
|
else if (PROP == "inactive_border_color")
|
||||||
return borderColorToString(false);
|
return borderColorToString(false);
|
||||||
else if (auto search = NWindowProperties::boolWindowProperties.find(PROP); search != NWindowProperties::boolWindowProperties.end())
|
else if (PROP == "allows_input")
|
||||||
return windowPropToString(*search->second(PWINDOW));
|
return windowPropToString(PWINDOW->m_ruleApplicator->allowsInput());
|
||||||
else if (auto search = NWindowProperties::intWindowProperties.find(PROP); search != NWindowProperties::intWindowProperties.end())
|
else if (PROP == "decorate")
|
||||||
return windowPropToString(*search->second(PWINDOW));
|
return windowPropToString(PWINDOW->m_ruleApplicator->decorate());
|
||||||
else if (auto search = NWindowProperties::floatWindowProperties.find(PROP); search != NWindowProperties::floatWindowProperties.end())
|
else if (PROP == "focus_on_activate")
|
||||||
return windowPropToString(*search->second(PWINDOW));
|
return windowPropToString(PWINDOW->m_ruleApplicator->focusOnActivate());
|
||||||
|
else if (PROP == "keep_aspect_ratio")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->keepAspectRatio());
|
||||||
|
else if (PROP == "nearest_neighbor")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->nearestNeighbor());
|
||||||
|
else if (PROP == "no_anim")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->noAnim());
|
||||||
|
else if (PROP == "no_blur")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->noBlur());
|
||||||
|
else if (PROP == "no_dim")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->noDim());
|
||||||
|
else if (PROP == "no_focus")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->noFocus());
|
||||||
|
else if (PROP == "no_max_size")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->noMaxSize());
|
||||||
|
else if (PROP == "no_shadow")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->noShadow());
|
||||||
|
else if (PROP == "no_shortcuts_inhibit")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->noShortcutsInhibit());
|
||||||
|
else if (PROP == "opaque")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->opaque());
|
||||||
|
else if (PROP == "dim_around")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->dimAround());
|
||||||
|
else if (PROP == "force_rgbx")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->RGBX());
|
||||||
|
else if (PROP == "sync_fullscreen")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->syncFullscreen());
|
||||||
|
else if (PROP == "immediate")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->tearing());
|
||||||
|
else if (PROP == "xray")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->xray());
|
||||||
|
else if (PROP == "render_unfocused")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->renderUnfocused());
|
||||||
|
else if (PROP == "no_follow_mouse")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->noFollowMouse());
|
||||||
|
else if (PROP == "no_screen_share")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->noScreenShare());
|
||||||
|
else if (PROP == "no_vrr")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->noVRR());
|
||||||
|
else if (PROP == "persistent_size")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->persistentSize());
|
||||||
|
else if (PROP == "stay_focused")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->stayFocused());
|
||||||
|
else if (PROP == "idle_inhibit")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->idleInhibitMode());
|
||||||
|
else if (PROP == "border_size")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->borderSize());
|
||||||
|
else if (PROP == "rounding")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->rounding());
|
||||||
|
else if (PROP == "rounding_power")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->roundingPower());
|
||||||
|
else if (PROP == "scroll_mouse")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->scrollMouse());
|
||||||
|
else if (PROP == "scroll_touchpad")
|
||||||
|
return windowPropToString(PWINDOW->m_ruleApplicator->scrollTouchpad());
|
||||||
|
|
||||||
return "prop not found";
|
return "prop not found";
|
||||||
}
|
}
|
||||||
|
|
@ -2014,7 +2070,6 @@ CHyprCtl::CHyprCtl() {
|
||||||
registerCommand(SHyprCtlCommand{"plugin", false, dispatchPlugin});
|
registerCommand(SHyprCtlCommand{"plugin", false, dispatchPlugin});
|
||||||
registerCommand(SHyprCtlCommand{"notify", false, dispatchNotify});
|
registerCommand(SHyprCtlCommand{"notify", false, dispatchNotify});
|
||||||
registerCommand(SHyprCtlCommand{"dismissnotify", false, dispatchDismissNotify});
|
registerCommand(SHyprCtlCommand{"dismissnotify", false, dispatchDismissNotify});
|
||||||
registerCommand(SHyprCtlCommand{"setprop", false, dispatchSetProp});
|
|
||||||
registerCommand(SHyprCtlCommand{"getprop", false, dispatchGetProp});
|
registerCommand(SHyprCtlCommand{"getprop", false, dispatchGetProp});
|
||||||
registerCommand(SHyprCtlCommand{"seterror", false, dispatchSeterror});
|
registerCommand(SHyprCtlCommand{"seterror", false, dispatchSeterror});
|
||||||
registerCommand(SHyprCtlCommand{"switchxkblayout", false, switchXKBLayoutRequest});
|
registerCommand(SHyprCtlCommand{"switchxkblayout", false, switchXKBLayoutRequest});
|
||||||
|
|
@ -2130,8 +2185,7 @@ std::string CHyprCtl::getReply(std::string request) {
|
||||||
if (!w->m_isMapped || !w->m_workspace || !w->m_workspace->isVisible())
|
if (!w->m_isMapped || !w->m_workspace || !w->m_workspace->isVisible())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
w->updateDynamicRules();
|
Desktop::Rule::ruleEngine()->updateAllRules();
|
||||||
g_pCompositor->updateWindowAnimatedDecorationValues(w);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const& m : g_pCompositor->m_monitors) {
|
for (auto const& m : g_pCompositor->m_monitors) {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ class CHyprCtl {
|
||||||
struct {
|
struct {
|
||||||
bool all = false;
|
bool all = false;
|
||||||
bool sysInfoConfig = false;
|
bool sysInfoConfig = false;
|
||||||
|
bool isDynamicKeyword = false;
|
||||||
pid_t pid = 0;
|
pid_t pid = 0;
|
||||||
SP<CPromise<std::string>> pendingPromise;
|
SP<CPromise<std::string>> pendingPromise;
|
||||||
} m_currentRequestParams;
|
} m_currentRequestParams;
|
||||||
|
|
|
||||||
|
|
@ -1,42 +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", "noscreenshare"};
|
|
||||||
static const auto RULES_PREFIX = std::unordered_set<std::string>{"ignorealpha", "ignorezero", "xray", "animation", "order", "abovelock"};
|
|
||||||
|
|
||||||
CLayerRule::CLayerRule(const std::string& rule_, const std::string& ns_) : m_targetNamespace(ns_), m_rule(rule_) {
|
|
||||||
const bool VALID = RULES.contains(m_rule) || std::ranges::any_of(RULES_PREFIX, [&rule_](const auto& prefix) { return rule_.starts_with(prefix); });
|
|
||||||
|
|
||||||
if (!VALID)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (m_rule == "noanim")
|
|
||||||
m_ruleType = RULE_NOANIM;
|
|
||||||
else if (m_rule == "blur")
|
|
||||||
m_ruleType = RULE_BLUR;
|
|
||||||
else if (m_rule == "blurpopups")
|
|
||||||
m_ruleType = RULE_BLURPOPUPS;
|
|
||||||
else if (m_rule == "dimaround")
|
|
||||||
m_ruleType = RULE_DIMAROUND;
|
|
||||||
else if (m_rule == "noscreenshare")
|
|
||||||
m_ruleType = RULE_NOSCREENSHARE;
|
|
||||||
else if (m_rule.starts_with("ignorealpha"))
|
|
||||||
m_ruleType = RULE_IGNOREALPHA;
|
|
||||||
else if (m_rule.starts_with("ignorezero"))
|
|
||||||
m_ruleType = RULE_IGNOREZERO;
|
|
||||||
else if (m_rule.starts_with("xray"))
|
|
||||||
m_ruleType = RULE_XRAY;
|
|
||||||
else if (m_rule.starts_with("animation"))
|
|
||||||
m_ruleType = RULE_ANIMATION;
|
|
||||||
else if (m_rule.starts_with("order"))
|
|
||||||
m_ruleType = RULE_ORDER;
|
|
||||||
else if (m_rule.starts_with("abovelock"))
|
|
||||||
m_ruleType = RULE_ABOVELOCK;
|
|
||||||
else {
|
|
||||||
Debug::log(ERR, "CLayerRule: didn't match a rule that was found valid?!");
|
|
||||||
m_ruleType = RULE_INVALID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +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_ABOVELOCK,
|
|
||||||
RULE_IGNOREALPHA,
|
|
||||||
RULE_IGNOREZERO,
|
|
||||||
RULE_XRAY,
|
|
||||||
RULE_ANIMATION,
|
|
||||||
RULE_ORDER,
|
|
||||||
RULE_ZUMBA,
|
|
||||||
RULE_NOSCREENSHARE
|
|
||||||
};
|
|
||||||
|
|
||||||
eRuleType m_ruleType = RULE_INVALID;
|
|
||||||
|
|
||||||
const std::string m_targetNamespace;
|
|
||||||
const std::string m_rule;
|
|
||||||
|
|
||||||
CRuleRegexContainer m_targetNamespaceRegex;
|
|
||||||
};
|
|
||||||
|
|
@ -37,7 +37,7 @@ PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) {
|
||||||
pLS->m_monitor = pMonitor;
|
pLS->m_monitor = pMonitor;
|
||||||
pMonitor->m_layerSurfaceLayers[resource->m_current.layer].emplace_back(pLS);
|
pMonitor->m_layerSurfaceLayers[resource->m_current.layer].emplace_back(pLS);
|
||||||
|
|
||||||
pLS->m_forceBlur = g_pConfigManager->shouldBlurLS(pLS->m_namespace);
|
pLS->m_ruleApplicator = makeUnique<Desktop::Rule::CLayerRuleApplicator>(pLS);
|
||||||
|
|
||||||
g_pAnimationManager->createAnimation(0.f, pLS->m_alpha, g_pConfigManager->getAnimationPropertyConfig("fadeLayersIn"), pLS, AVARDAMAGE_ENTIRE);
|
g_pAnimationManager->createAnimation(0.f, pLS->m_alpha, g_pConfigManager->getAnimationPropertyConfig("fadeLayersIn"), pLS, AVARDAMAGE_ENTIRE);
|
||||||
g_pAnimationManager->createAnimation(Vector2D(0, 0), pLS->m_realPosition, g_pConfigManager->getAnimationPropertyConfig("layersIn"), pLS, AVARDAMAGE_ENTIRE);
|
g_pAnimationManager->createAnimation(Vector2D(0, 0), pLS->m_realPosition, g_pConfigManager->getAnimationPropertyConfig("layersIn"), pLS, AVARDAMAGE_ENTIRE);
|
||||||
|
|
@ -55,7 +55,7 @@ PHLLS CLayerSurface::create(SP<CLayerShellResource> resource) {
|
||||||
|
|
||||||
void CLayerSurface::registerCallbacks() {
|
void CLayerSurface::registerCallbacks() {
|
||||||
m_alpha->setUpdateCallback([this](auto) {
|
m_alpha->setUpdateCallback([this](auto) {
|
||||||
if (m_dimAround && m_monitor)
|
if (m_ruleApplicator->dimAround().valueOrDefault() && m_monitor)
|
||||||
g_pHyprRenderer->damageMonitor(m_monitor.lock());
|
g_pHyprRenderer->damageMonitor(m_monitor.lock());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -137,6 +137,8 @@ void CLayerSurface::onMap() {
|
||||||
m_mapped = true;
|
m_mapped = true;
|
||||||
m_interactivity = m_layerSurface->m_current.interactivity;
|
m_interactivity = m_layerSurface->m_current.interactivity;
|
||||||
|
|
||||||
|
m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_ALL);
|
||||||
|
|
||||||
m_layerSurface->m_surface->map();
|
m_layerSurface->m_surface->map();
|
||||||
|
|
||||||
// this layer might be re-mapped.
|
// this layer might be re-mapped.
|
||||||
|
|
@ -149,8 +151,6 @@ void CLayerSurface::onMap() {
|
||||||
if (!PMONITOR)
|
if (!PMONITOR)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
applyRules();
|
|
||||||
|
|
||||||
PMONITOR->m_scheduledRecalc = true;
|
PMONITOR->m_scheduledRecalc = true;
|
||||||
|
|
||||||
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->m_id);
|
g_pHyprRenderer->arrangeLayersForMonitor(PMONITOR->m_id);
|
||||||
|
|
@ -398,83 +398,6 @@ void CLayerSurface::onCommit() {
|
||||||
g_pCompositor->setPreferredTransformForSurface(m_surface->resource(), PMONITOR->m_transform);
|
g_pCompositor->setPreferredTransformForSurface(m_surface->resource(), PMONITOR->m_transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLayerSurface::applyRules() {
|
|
||||||
m_noAnimations = false;
|
|
||||||
m_forceBlur = false;
|
|
||||||
m_ignoreAlpha = false;
|
|
||||||
m_dimAround = false;
|
|
||||||
m_noScreenShare = false;
|
|
||||||
m_ignoreAlphaValue = 0.f;
|
|
||||||
m_xray = -1;
|
|
||||||
m_animationStyle.reset();
|
|
||||||
|
|
||||||
for (auto const& rule : g_pConfigManager->getMatchingRules(m_self.lock())) {
|
|
||||||
switch (rule->m_ruleType) {
|
|
||||||
case CLayerRule::RULE_NOANIM: {
|
|
||||||
m_noAnimations = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CLayerRule::RULE_BLUR: {
|
|
||||||
m_forceBlur = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CLayerRule::RULE_BLURPOPUPS: {
|
|
||||||
m_forceBlurPopups = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CLayerRule::RULE_IGNOREALPHA:
|
|
||||||
case CLayerRule::RULE_IGNOREZERO: {
|
|
||||||
const auto FIRST_SPACE_POS = rule->m_rule.find_first_of(' ');
|
|
||||||
std::string alphaValue = "";
|
|
||||||
if (FIRST_SPACE_POS != std::string::npos)
|
|
||||||
alphaValue = rule->m_rule.substr(FIRST_SPACE_POS + 1);
|
|
||||||
|
|
||||||
try {
|
|
||||||
m_ignoreAlpha = true;
|
|
||||||
if (!alphaValue.empty())
|
|
||||||
m_ignoreAlphaValue = std::stof(alphaValue);
|
|
||||||
} catch (...) { Debug::log(ERR, "Invalid value passed to ignoreAlpha"); }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CLayerRule::RULE_DIMAROUND: {
|
|
||||||
m_dimAround = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CLayerRule::RULE_NOSCREENSHARE: {
|
|
||||||
m_noScreenShare = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CLayerRule::RULE_XRAY: {
|
|
||||||
CVarList vars{rule->m_rule, 0, ' '};
|
|
||||||
m_xray = configStringToInt(vars[1]).value_or(false);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CLayerRule::RULE_ANIMATION: {
|
|
||||||
CVarList vars{rule->m_rule, 2, 's'};
|
|
||||||
m_animationStyle = vars[1];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CLayerRule::RULE_ORDER: {
|
|
||||||
CVarList vars{rule->m_rule, 2, 's'};
|
|
||||||
try {
|
|
||||||
m_order = std::stoi(vars[1]);
|
|
||||||
} catch (...) { Debug::log(ERR, "Invalid value passed to order"); }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CLayerRule::RULE_ABOVELOCK: {
|
|
||||||
m_aboveLockscreen = true;
|
|
||||||
|
|
||||||
CVarList vars{rule->m_rule, 0, ' '};
|
|
||||||
m_aboveLockscreenInteractable = configStringToInt(vars[1]).value_or(false);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CLayerSurface::isFadedOut() {
|
bool CLayerSurface::isFadedOut() {
|
||||||
if (!m_fadingOut)
|
if (!m_fadingOut)
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "WLSurface.hpp"
|
#include "WLSurface.hpp"
|
||||||
|
#include "rule/layerRule/LayerRuleApplicator.hpp"
|
||||||
#include "../helpers/AnimatedVariable.hpp"
|
#include "../helpers/AnimatedVariable.hpp"
|
||||||
|
|
||||||
class CLayerShellResource;
|
class CLayerShellResource;
|
||||||
|
|
@ -17,7 +18,6 @@ class CLayerSurface {
|
||||||
public:
|
public:
|
||||||
~CLayerSurface();
|
~CLayerSurface();
|
||||||
|
|
||||||
void applyRules();
|
|
||||||
bool isFadedOut();
|
bool isFadedOut();
|
||||||
int popupsCount();
|
int popupsCount();
|
||||||
|
|
||||||
|
|
@ -40,20 +40,8 @@ class CLayerSurface {
|
||||||
bool m_fadingOut = false;
|
bool m_fadingOut = false;
|
||||||
bool m_readyToDelete = false;
|
bool m_readyToDelete = false;
|
||||||
bool m_noProcess = false;
|
bool m_noProcess = false;
|
||||||
bool m_noAnimations = false;
|
|
||||||
|
|
||||||
bool m_forceBlur = false;
|
UP<Desktop::Rule::CLayerRuleApplicator> m_ruleApplicator;
|
||||||
bool m_forceBlurPopups = false;
|
|
||||||
int64_t m_xray = -1;
|
|
||||||
bool m_ignoreAlpha = false;
|
|
||||||
float m_ignoreAlphaValue = 0.f;
|
|
||||||
bool m_dimAround = false;
|
|
||||||
bool m_noScreenShare = false;
|
|
||||||
int64_t m_order = 0;
|
|
||||||
bool m_aboveLockscreen = false;
|
|
||||||
bool m_aboveLockscreenInteractable = false;
|
|
||||||
|
|
||||||
std::optional<std::string> m_animationStyle;
|
|
||||||
|
|
||||||
PHLLSREF m_self;
|
PHLLSREF m_self;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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:");
|
|
||||||
|
|
||||||
m_negative = NEGATIVE;
|
|
||||||
m_regex = makeUnique<RE2>(NEGATIVE ? regex_.substr(9) : regex_);
|
|
||||||
|
|
||||||
// TODO: maybe pop an error?
|
|
||||||
if (!m_regex->ok())
|
|
||||||
Debug::log(ERR, "RuleRegexContainer: regex {} failed to parse!", regex_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CRuleRegexContainer::passes(const std::string& str) const {
|
|
||||||
if (!m_regex)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return RE2::FullMatch(str, *m_regex) != m_negative;
|
|
||||||
}
|
|
||||||
|
|
@ -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> m_regex;
|
|
||||||
bool m_negative = false;
|
|
||||||
};
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "../protocols/FractionalScale.hpp"
|
#include "../protocols/FractionalScale.hpp"
|
||||||
#include "../xwayland/XWayland.hpp"
|
#include "../xwayland/XWayland.hpp"
|
||||||
#include "../helpers/Color.hpp"
|
#include "../helpers/Color.hpp"
|
||||||
|
#include "../helpers/math/Expression.hpp"
|
||||||
#include "../events/Events.hpp"
|
#include "../events/Events.hpp"
|
||||||
#include "../managers/XWaylandManager.hpp"
|
#include "../managers/XWaylandManager.hpp"
|
||||||
#include "../render/Renderer.hpp"
|
#include "../render/Renderer.hpp"
|
||||||
|
|
@ -43,6 +44,7 @@ PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
|
||||||
|
|
||||||
pWindow->m_self = pWindow;
|
pWindow->m_self = pWindow;
|
||||||
pWindow->m_isX11 = true;
|
pWindow->m_isX11 = true;
|
||||||
|
pWindow->m_ruleApplicator = makeUnique<Desktop::Rule::CWindowRuleApplicator>(pWindow);
|
||||||
|
|
||||||
g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_realPosition, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_realPosition, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
||||||
g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_realSize, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_realSize, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
||||||
|
|
@ -67,6 +69,7 @@ PHLWINDOW CWindow::create(SP<CXDGSurfaceResource> resource) {
|
||||||
|
|
||||||
pWindow->m_self = pWindow;
|
pWindow->m_self = pWindow;
|
||||||
resource->m_toplevel->m_window = pWindow;
|
resource->m_toplevel->m_window = pWindow;
|
||||||
|
pWindow->m_ruleApplicator = makeUnique<Desktop::Rule::CWindowRuleApplicator>(pWindow);
|
||||||
|
|
||||||
g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_realPosition, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_realPosition, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
||||||
g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_realSize, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_realSize, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
||||||
|
|
@ -138,7 +141,7 @@ SBoxExtents CWindow::getFullWindowExtents() {
|
||||||
|
|
||||||
const int BORDERSIZE = getRealBorderSize();
|
const int BORDERSIZE = getRealBorderSize();
|
||||||
|
|
||||||
if (m_windowData.dimAround.valueOrDefault()) {
|
if (m_ruleApplicator->dimAround().valueOrDefault()) {
|
||||||
if (const auto PMONITOR = m_monitor.lock(); PMONITOR)
|
if (const auto PMONITOR = m_monitor.lock(); PMONITOR)
|
||||||
return {.topLeft = {m_realPosition->value().x - PMONITOR->m_position.x, m_realPosition->value().y - PMONITOR->m_position.y},
|
return {.topLeft = {m_realPosition->value().x - PMONITOR->m_position.x, m_realPosition->value().y - PMONITOR->m_position.y},
|
||||||
.bottomRight = {PMONITOR->m_size.x - (m_realPosition->value().x - PMONITOR->m_position.x),
|
.bottomRight = {PMONITOR->m_size.x - (m_realPosition->value().x - PMONITOR->m_position.x),
|
||||||
|
|
@ -191,7 +194,7 @@ SBoxExtents CWindow::getFullWindowExtents() {
|
||||||
}
|
}
|
||||||
|
|
||||||
CBox CWindow::getFullWindowBoundingBox() {
|
CBox CWindow::getFullWindowBoundingBox() {
|
||||||
if (m_windowData.dimAround.valueOrDefault()) {
|
if (m_ruleApplicator->dimAround().valueOrDefault()) {
|
||||||
if (const auto PMONITOR = m_monitor.lock(); PMONITOR)
|
if (const auto PMONITOR = m_monitor.lock(); PMONITOR)
|
||||||
return {PMONITOR->m_position.x, PMONITOR->m_position.y, PMONITOR->m_size.x, PMONITOR->m_size.y};
|
return {PMONITOR->m_position.x, PMONITOR->m_position.y, PMONITOR->m_size.x, PMONITOR->m_size.y};
|
||||||
}
|
}
|
||||||
|
|
@ -251,7 +254,7 @@ SBoxExtents CWindow::getWindowExtentsUnified(uint64_t properties) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CBox CWindow::getWindowBoxUnified(uint64_t properties) {
|
CBox CWindow::getWindowBoxUnified(uint64_t properties) {
|
||||||
if (m_windowData.dimAround.valueOrDefault()) {
|
if (m_ruleApplicator->dimAround().valueOrDefault()) {
|
||||||
const auto PMONITOR = m_monitor.lock();
|
const auto PMONITOR = m_monitor.lock();
|
||||||
if (PMONITOR)
|
if (PMONITOR)
|
||||||
return {PMONITOR->m_position.x, PMONITOR->m_position.y, PMONITOR->m_size.x, PMONITOR->m_size.y};
|
return {PMONITOR->m_position.x, PMONITOR->m_position.y, PMONITOR->m_size.x, PMONITOR->m_size.y};
|
||||||
|
|
@ -636,222 +639,6 @@ bool CWindow::isHidden() {
|
||||||
return m_hidden;
|
return m_hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::applyDynamicRule(const SP<CWindowRule>& r) {
|
|
||||||
const eOverridePriority priority = r->m_execRule ? PRIORITY_SET_PROP : PRIORITY_WINDOW_RULE;
|
|
||||||
static auto PCLAMP_TILED = CConfigValue<Hyprlang::INT>("misc:size_limits_tiled");
|
|
||||||
|
|
||||||
switch (r->m_ruleType) {
|
|
||||||
case CWindowRule::RULE_TAG: {
|
|
||||||
CVarList vars{r->m_rule, 0, 's', true};
|
|
||||||
|
|
||||||
if (vars.size() == 2 && vars[0] == "tag")
|
|
||||||
m_tags.applyTag(vars[1], true);
|
|
||||||
else
|
|
||||||
Debug::log(ERR, "Tag rule invalid: {}", r->m_rule);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWindowRule::RULE_OPACITY: {
|
|
||||||
try {
|
|
||||||
CVarList vars(r->m_rule, 0, ' ');
|
|
||||||
|
|
||||||
int opacityIDX = 0;
|
|
||||||
|
|
||||||
for (auto const& r : vars) {
|
|
||||||
if (r == "opacity")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (r == "override") {
|
|
||||||
if (opacityIDX == 1)
|
|
||||||
m_windowData.alpha = CWindowOverridableVar(SAlphaValue{.alpha = m_windowData.alpha.value().alpha, .overridden = true}, priority);
|
|
||||||
else if (opacityIDX == 2)
|
|
||||||
m_windowData.alphaInactive = CWindowOverridableVar(SAlphaValue{.alpha = m_windowData.alphaInactive.value().alpha, .overridden = true}, priority);
|
|
||||||
else if (opacityIDX == 3)
|
|
||||||
m_windowData.alphaFullscreen = CWindowOverridableVar(SAlphaValue{.alpha = m_windowData.alphaFullscreen.value().alpha, .overridden = true}, priority);
|
|
||||||
} else {
|
|
||||||
if (opacityIDX == 0) {
|
|
||||||
m_windowData.alpha = CWindowOverridableVar(SAlphaValue{.alpha = std::stof(r), .overridden = false}, priority);
|
|
||||||
} else if (opacityIDX == 1) {
|
|
||||||
m_windowData.alphaInactive = CWindowOverridableVar(SAlphaValue{.alpha = std::stof(r), .overridden = false}, priority);
|
|
||||||
} else if (opacityIDX == 2) {
|
|
||||||
m_windowData.alphaFullscreen = CWindowOverridableVar(SAlphaValue{.alpha = std::stof(r), .overridden = false}, priority);
|
|
||||||
} else {
|
|
||||||
throw std::runtime_error("more than 3 alpha values");
|
|
||||||
}
|
|
||||||
|
|
||||||
opacityIDX++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opacityIDX == 1) {
|
|
||||||
m_windowData.alphaInactive = m_windowData.alpha;
|
|
||||||
m_windowData.alphaFullscreen = m_windowData.alpha;
|
|
||||||
}
|
|
||||||
} catch (std::exception& e) { Debug::log(ERR, "Opacity rule \"{}\" failed with: {}", r->m_rule, e.what()); }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWindowRule::RULE_ANIMATION: {
|
|
||||||
auto STYLE = r->m_rule.substr(r->m_rule.find_first_of(' ') + 1);
|
|
||||||
m_windowData.animationStyle = CWindowOverridableVar(STYLE, priority);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWindowRule::RULE_BORDERCOLOR: {
|
|
||||||
try {
|
|
||||||
// Each vector will only get used if it has at least one color
|
|
||||||
CGradientValueData activeBorderGradient = {};
|
|
||||||
CGradientValueData inactiveBorderGradient = {};
|
|
||||||
bool active = true;
|
|
||||||
CVarList colorsAndAngles = CVarList(trim(r->m_rule.substr(r->m_rule.find_first_of(' ') + 1)), 0, 's', true);
|
|
||||||
|
|
||||||
// Basic form has only two colors, everything else can be parsed as a gradient
|
|
||||||
if (colorsAndAngles.size() == 2 && !colorsAndAngles[1].contains("deg")) {
|
|
||||||
m_windowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CHyprColor(configStringToInt(colorsAndAngles[0]).value_or(0))), priority);
|
|
||||||
m_windowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CHyprColor(configStringToInt(colorsAndAngles[1]).value_or(0))), priority);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto const& token : colorsAndAngles) {
|
|
||||||
// The first angle, or an explicit "0deg", splits the two gradients
|
|
||||||
if (active && token.contains("deg")) {
|
|
||||||
activeBorderGradient.m_angle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
|
||||||
active = false;
|
|
||||||
} else if (token.contains("deg"))
|
|
||||||
inactiveBorderGradient.m_angle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
|
||||||
else if (active)
|
|
||||||
activeBorderGradient.m_colors.emplace_back(configStringToInt(token).value_or(0));
|
|
||||||
else
|
|
||||||
inactiveBorderGradient.m_colors.emplace_back(configStringToInt(token).value_or(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
activeBorderGradient.updateColorsOk();
|
|
||||||
|
|
||||||
// Includes sanity checks for the number of colors in each gradient
|
|
||||||
if (activeBorderGradient.m_colors.size() > 10 || inactiveBorderGradient.m_colors.size() > 10)
|
|
||||||
Debug::log(WARN, "Bordercolor rule \"{}\" has more than 10 colors in one gradient, ignoring", r->m_rule);
|
|
||||||
else if (activeBorderGradient.m_colors.empty())
|
|
||||||
Debug::log(WARN, "Bordercolor rule \"{}\" has no colors, ignoring", r->m_rule);
|
|
||||||
else if (inactiveBorderGradient.m_colors.empty())
|
|
||||||
m_windowData.activeBorderColor = CWindowOverridableVar(activeBorderGradient, priority);
|
|
||||||
else {
|
|
||||||
m_windowData.activeBorderColor = CWindowOverridableVar(activeBorderGradient, priority);
|
|
||||||
m_windowData.inactiveBorderColor = CWindowOverridableVar(inactiveBorderGradient, priority);
|
|
||||||
}
|
|
||||||
} catch (std::exception& e) { Debug::log(ERR, "BorderColor rule \"{}\" failed with: {}", r->m_rule, e.what()); }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWindowRule::RULE_IDLEINHIBIT: {
|
|
||||||
auto IDLERULE = r->m_rule.substr(r->m_rule.find_first_of(' ') + 1);
|
|
||||||
|
|
||||||
if (IDLERULE == "none")
|
|
||||||
m_idleInhibitMode = IDLEINHIBIT_NONE;
|
|
||||||
else if (IDLERULE == "always")
|
|
||||||
m_idleInhibitMode = IDLEINHIBIT_ALWAYS;
|
|
||||||
else if (IDLERULE == "focus")
|
|
||||||
m_idleInhibitMode = IDLEINHIBIT_FOCUS;
|
|
||||||
else if (IDLERULE == "fullscreen")
|
|
||||||
m_idleInhibitMode = IDLEINHIBIT_FULLSCREEN;
|
|
||||||
else
|
|
||||||
Debug::log(ERR, "Rule idleinhibit: unknown mode {}", IDLERULE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWindowRule::RULE_MAXSIZE: {
|
|
||||||
try {
|
|
||||||
if (!m_isFloating && !sc<bool>(*PCLAMP_TILED))
|
|
||||||
return;
|
|
||||||
const auto VEC = configStringToVector2D(r->m_rule.substr(8));
|
|
||||||
if (VEC.x < 1 || VEC.y < 1) {
|
|
||||||
Debug::log(ERR, "Invalid size for maxsize");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_windowData.maxSize = CWindowOverridableVar(VEC, priority);
|
|
||||||
clampWindowSize(std::nullopt, m_windowData.maxSize.value());
|
|
||||||
|
|
||||||
} catch (std::exception& e) { Debug::log(ERR, "maxsize rule \"{}\" failed with: {}", r->m_rule, e.what()); }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWindowRule::RULE_MINSIZE: {
|
|
||||||
try {
|
|
||||||
if (!m_isFloating && !sc<bool>(*PCLAMP_TILED))
|
|
||||||
return;
|
|
||||||
const auto VEC = configStringToVector2D(r->m_rule.substr(8));
|
|
||||||
if (VEC.x < 1 || VEC.y < 1) {
|
|
||||||
Debug::log(ERR, "Invalid size for minsize");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_windowData.minSize = CWindowOverridableVar(VEC, priority);
|
|
||||||
clampWindowSize(m_windowData.minSize.value(), std::nullopt);
|
|
||||||
|
|
||||||
if (m_groupData.pNextWindow.expired())
|
|
||||||
setHidden(false);
|
|
||||||
} catch (std::exception& e) { Debug::log(ERR, "minsize rule \"{}\" failed with: {}", r->m_rule, e.what()); }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWindowRule::RULE_RENDERUNFOCUSED: {
|
|
||||||
m_windowData.renderUnfocused = CWindowOverridableVar(true, priority);
|
|
||||||
g_pHyprRenderer->addWindowToRenderUnfocused(m_self.lock());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWindowRule::RULE_PROP: {
|
|
||||||
const CVarList VARS(r->m_rule, 0, ' ');
|
|
||||||
if (auto search = NWindowProperties::intWindowProperties.find(VARS[1]); search != NWindowProperties::intWindowProperties.end()) {
|
|
||||||
try {
|
|
||||||
*(search->second(m_self.lock())) = CWindowOverridableVar(sc<Hyprlang::INT>(std::stoi(VARS[2])), priority);
|
|
||||||
} catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->m_rule, e.what()); }
|
|
||||||
} else if (auto search = NWindowProperties::floatWindowProperties.find(VARS[1]); search != NWindowProperties::floatWindowProperties.end()) {
|
|
||||||
try {
|
|
||||||
*(search->second(m_self.lock())) = CWindowOverridableVar(std::stof(VARS[2]), priority);
|
|
||||||
} catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->m_rule, e.what()); }
|
|
||||||
} else if (auto search = NWindowProperties::boolWindowProperties.find(VARS[1]); search != NWindowProperties::boolWindowProperties.end()) {
|
|
||||||
try {
|
|
||||||
*(search->second(m_self.lock())) = CWindowOverridableVar(VARS[2].empty() ? true : sc<bool>(std::stoi(VARS[2])), priority);
|
|
||||||
} catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->m_rule, e.what()); }
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWindowRule::RULE_PERSISTENTSIZE: {
|
|
||||||
m_windowData.persistentSize = CWindowOverridableVar(true, PRIORITY_WINDOW_RULE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWindowRule::RULE_NOVRR: {
|
|
||||||
m_windowData.noVRR = CWindowOverridableVar(true, priority);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWindow::updateDynamicRules() {
|
|
||||||
m_windowData.alpha.unset(PRIORITY_WINDOW_RULE);
|
|
||||||
m_windowData.alphaInactive.unset(PRIORITY_WINDOW_RULE);
|
|
||||||
m_windowData.alphaFullscreen.unset(PRIORITY_WINDOW_RULE);
|
|
||||||
|
|
||||||
unsetWindowData(PRIORITY_WINDOW_RULE);
|
|
||||||
|
|
||||||
m_windowData.animationStyle.unset(PRIORITY_WINDOW_RULE);
|
|
||||||
m_windowData.maxSize.unset(PRIORITY_WINDOW_RULE);
|
|
||||||
m_windowData.minSize.unset(PRIORITY_WINDOW_RULE);
|
|
||||||
|
|
||||||
m_windowData.activeBorderColor.unset(PRIORITY_WINDOW_RULE);
|
|
||||||
m_windowData.inactiveBorderColor.unset(PRIORITY_WINDOW_RULE);
|
|
||||||
|
|
||||||
m_windowData.renderUnfocused.unset(PRIORITY_WINDOW_RULE);
|
|
||||||
m_windowData.noVRR.unset(PRIORITY_WINDOW_RULE);
|
|
||||||
|
|
||||||
m_idleInhibitMode = IDLEINHIBIT_NONE;
|
|
||||||
|
|
||||||
m_tags.removeDynamicTags();
|
|
||||||
|
|
||||||
m_matchedRules = g_pConfigManager->getMatchingRules(m_self.lock());
|
|
||||||
for (const auto& r : m_matchedRules) {
|
|
||||||
applyDynamicRule(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
EMIT_HOOK_EVENT("windowUpdateRules", m_self.lock());
|
|
||||||
|
|
||||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the point is "hidden" under a rounded corner of the window
|
// check if the point is "hidden" under a rounded corner of the window
|
||||||
// it is assumed that the point is within the real window box (m_vRealPosition, m_vRealSize)
|
// it is assumed that the point is within the real window box (m_vRealPosition, m_vRealSize)
|
||||||
// otherwise behaviour is undefined
|
// otherwise behaviour is undefined
|
||||||
|
|
@ -924,6 +711,8 @@ void CWindow::createGroup() {
|
||||||
|
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "togglegroup", .data = std::format("1,{:x}", rc<uintptr_t>(this))});
|
g_pEventManager->postEvent(SHyprIPCEvent{.event = "togglegroup", .data = std::format("1,{:x}", rc<uintptr_t>(this))});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::destroyGroup() {
|
void CWindow::destroyGroup() {
|
||||||
|
|
@ -943,6 +732,7 @@ void CWindow::destroyGroup() {
|
||||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||||
|
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "togglegroup", .data = std::format("0,{:x}", rc<uintptr_t>(this))});
|
g_pEventManager->postEvent(SHyprIPCEvent{.event = "togglegroup", .data = std::format("0,{:x}", rc<uintptr_t>(this))});
|
||||||
|
m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -969,6 +759,7 @@ void CWindow::destroyGroup() {
|
||||||
g_pKeybindManager->m_groupsLocked = true;
|
g_pKeybindManager->m_groupsLocked = true;
|
||||||
for (auto const& w : members) {
|
for (auto const& w : members) {
|
||||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(w);
|
g_pLayoutManager->getCurrentLayout()->onWindowCreated(w);
|
||||||
|
w->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||||
w->updateWindowDecos();
|
w->updateWindowDecos();
|
||||||
}
|
}
|
||||||
g_pKeybindManager->m_groupsLocked = GROUPSLOCKEDPREV;
|
g_pKeybindManager->m_groupsLocked = GROUPSLOCKEDPREV;
|
||||||
|
|
@ -982,6 +773,8 @@ void CWindow::destroyGroup() {
|
||||||
|
|
||||||
if (!addresses.empty())
|
if (!addresses.empty())
|
||||||
addresses.pop_back();
|
addresses.pop_back();
|
||||||
|
|
||||||
|
m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "togglegroup", .data = std::format("0,{}", addresses)});
|
g_pEventManager->postEvent(SHyprIPCEvent{.event = "togglegroup", .data = std::format("0,{}", addresses)});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1217,16 +1010,16 @@ float CWindow::rounding() {
|
||||||
static auto PROUNDING = CConfigValue<Hyprlang::INT>("decoration:rounding");
|
static auto PROUNDING = CConfigValue<Hyprlang::INT>("decoration:rounding");
|
||||||
static auto PROUNDINGPOWER = CConfigValue<Hyprlang::FLOAT>("decoration:rounding_power");
|
static auto PROUNDINGPOWER = CConfigValue<Hyprlang::FLOAT>("decoration:rounding_power");
|
||||||
|
|
||||||
float roundingPower = m_windowData.roundingPower.valueOr(*PROUNDINGPOWER);
|
float roundingPower = m_ruleApplicator->roundingPower().valueOr(*PROUNDINGPOWER);
|
||||||
float rounding = m_windowData.rounding.valueOr(*PROUNDING) * (roundingPower / 2.0); /* Make perceived roundness consistent. */
|
float rounding = m_ruleApplicator->rounding().valueOr(*PROUNDING) * (roundingPower / 2.0); /* Make perceived roundness consistent. */
|
||||||
|
|
||||||
return m_windowData.noRounding.valueOrDefault() ? 0 : rounding;
|
return rounding;
|
||||||
}
|
}
|
||||||
|
|
||||||
float CWindow::roundingPower() {
|
float CWindow::roundingPower() {
|
||||||
static auto PROUNDINGPOWER = CConfigValue<Hyprlang::FLOAT>("decoration:rounding_power");
|
static auto PROUNDINGPOWER = CConfigValue<Hyprlang::FLOAT>("decoration:rounding_power");
|
||||||
|
|
||||||
return m_windowData.roundingPower.valueOr(std::clamp(*PROUNDINGPOWER, 1.F, 10.F));
|
return m_ruleApplicator->roundingPower().valueOr(std::clamp(*PROUNDINGPOWER, 1.F, 10.F));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::updateWindowData() {
|
void CWindow::updateWindowData() {
|
||||||
|
|
@ -1236,50 +1029,43 @@ void CWindow::updateWindowData() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::updateWindowData(const SWorkspaceRule& workspaceRule) {
|
void CWindow::updateWindowData(const SWorkspaceRule& workspaceRule) {
|
||||||
static auto PNOBORDERONFLOATING = CConfigValue<Hyprlang::INT>("general:no_border_on_floating");
|
m_ruleApplicator->borderSize().matchOptional(workspaceRule.borderSize, Desktop::Types::PRIORITY_WORKSPACE_RULE);
|
||||||
|
m_ruleApplicator->decorate().matchOptional(workspaceRule.decorate, Desktop::Types::PRIORITY_WORKSPACE_RULE);
|
||||||
if (*PNOBORDERONFLOATING)
|
m_ruleApplicator->borderSize().matchOptional(workspaceRule.noBorder ? std::optional<Hyprlang::INT>(0) : std::nullopt, Desktop::Types::PRIORITY_WORKSPACE_RULE);
|
||||||
m_windowData.noBorder = CWindowOverridableVar(m_isFloating, PRIORITY_LAYOUT);
|
m_ruleApplicator->rounding().matchOptional(workspaceRule.noRounding.value_or(false) ? std::optional<Hyprlang::INT>(0) : std::nullopt, Desktop::Types::PRIORITY_WORKSPACE_RULE);
|
||||||
else
|
m_ruleApplicator->noShadow().matchOptional(workspaceRule.noShadow, Desktop::Types::PRIORITY_WORKSPACE_RULE);
|
||||||
m_windowData.noBorder.unset(PRIORITY_LAYOUT);
|
|
||||||
|
|
||||||
m_windowData.borderSize.matchOptional(workspaceRule.borderSize, PRIORITY_WORKSPACE_RULE);
|
|
||||||
m_windowData.decorate.matchOptional(workspaceRule.decorate, PRIORITY_WORKSPACE_RULE);
|
|
||||||
m_windowData.noBorder.matchOptional(workspaceRule.noBorder, PRIORITY_WORKSPACE_RULE);
|
|
||||||
m_windowData.noRounding.matchOptional(workspaceRule.noRounding, PRIORITY_WORKSPACE_RULE);
|
|
||||||
m_windowData.noShadow.matchOptional(workspaceRule.noShadow, PRIORITY_WORKSPACE_RULE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CWindow::getRealBorderSize() {
|
int CWindow::getRealBorderSize() {
|
||||||
if (m_windowData.noBorder.valueOrDefault() || (m_workspace && isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) || !m_windowData.decorate.valueOrDefault())
|
if ((m_workspace && isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) || !m_ruleApplicator->decorate().valueOrDefault())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
static auto PBORDERSIZE = CConfigValue<Hyprlang::INT>("general:border_size");
|
static auto PBORDERSIZE = CConfigValue<Hyprlang::INT>("general:border_size");
|
||||||
|
|
||||||
return m_windowData.borderSize.valueOr(*PBORDERSIZE);
|
return m_ruleApplicator->borderSize().valueOr(*PBORDERSIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
float CWindow::getScrollMouse() {
|
float CWindow::getScrollMouse() {
|
||||||
static auto PINPUTSCROLLFACTOR = CConfigValue<Hyprlang::FLOAT>("input:scroll_factor");
|
static auto PINPUTSCROLLFACTOR = CConfigValue<Hyprlang::FLOAT>("input:scroll_factor");
|
||||||
return m_windowData.scrollMouse.valueOr(*PINPUTSCROLLFACTOR);
|
return m_ruleApplicator->scrollMouse().valueOr(*PINPUTSCROLLFACTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
float CWindow::getScrollTouchpad() {
|
float CWindow::getScrollTouchpad() {
|
||||||
static auto PTOUCHPADSCROLLFACTOR = CConfigValue<Hyprlang::FLOAT>("input:touchpad:scroll_factor");
|
static auto PTOUCHPADSCROLLFACTOR = CConfigValue<Hyprlang::FLOAT>("input:touchpad:scroll_factor");
|
||||||
return m_windowData.scrollTouchpad.valueOr(*PTOUCHPADSCROLLFACTOR);
|
return m_ruleApplicator->scrollTouchpad().valueOr(*PTOUCHPADSCROLLFACTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWindow::isScrollMouseOverridden() {
|
bool CWindow::isScrollMouseOverridden() {
|
||||||
return m_windowData.scrollMouse.hasValue();
|
return m_ruleApplicator->scrollMouse().hasValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWindow::isScrollTouchpadOverridden() {
|
bool CWindow::isScrollTouchpadOverridden() {
|
||||||
return m_windowData.scrollTouchpad.hasValue();
|
return m_ruleApplicator->scrollTouchpad().hasValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CWindow::canBeTorn() {
|
bool CWindow::canBeTorn() {
|
||||||
static auto PTEARING = CConfigValue<Hyprlang::INT>("general:allow_tearing");
|
static auto PTEARING = CConfigValue<Hyprlang::INT>("general:allow_tearing");
|
||||||
return m_windowData.tearing.valueOr(m_tearingHint) && *PTEARING;
|
return m_ruleApplicator->tearing().valueOr(m_tearingHint) && *PTEARING;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::setSuspended(bool suspend) {
|
void CWindow::setSuspended(bool suspend) {
|
||||||
|
|
@ -1454,7 +1240,8 @@ void CWindow::activate(bool force) {
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "urgent", .data = std::format("{:x}", rc<uintptr_t>(this))});
|
g_pEventManager->postEvent(SHyprIPCEvent{.event = "urgent", .data = std::format("{:x}", rc<uintptr_t>(this))});
|
||||||
EMIT_HOOK_EVENT("urgent", m_self.lock());
|
EMIT_HOOK_EVENT("urgent", m_self.lock());
|
||||||
|
|
||||||
if (!force && (!m_windowData.focusOnActivate.valueOr(*PFOCUSONACTIVATE) || (m_suppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY) || (m_suppressedEvents & SUPPRESS_ACTIVATE)))
|
if (!force &&
|
||||||
|
(!m_ruleApplicator->focusOnActivate().valueOr(*PFOCUSONACTIVATE) || (m_suppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY) || (m_suppressedEvents & SUPPRESS_ACTIVATE)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!m_isMapped) {
|
if (!m_isMapped) {
|
||||||
|
|
@ -1539,8 +1326,7 @@ void CWindow::onUpdateMeta() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doUpdate) {
|
if (doUpdate) {
|
||||||
updateDynamicRules();
|
m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_TITLE | Desktop::Rule::RULE_PROP_CLASS);
|
||||||
g_pCompositor->updateWindowAnimatedDecorationValues(m_self.lock());
|
|
||||||
updateToplevel();
|
updateToplevel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1718,18 +1504,6 @@ PHLWINDOW CWindow::getSwallower() {
|
||||||
return candidates[0];
|
return candidates[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindow::unsetWindowData(eOverridePriority priority) {
|
|
||||||
for (auto const& element : NWindowProperties::boolWindowProperties) {
|
|
||||||
element.second(m_self.lock())->unset(priority);
|
|
||||||
}
|
|
||||||
for (auto const& element : NWindowProperties::intWindowProperties) {
|
|
||||||
element.second(m_self.lock())->unset(priority);
|
|
||||||
}
|
|
||||||
for (auto const& element : NWindowProperties::floatWindowProperties) {
|
|
||||||
element.second(m_self.lock())->unset(priority);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CWindow::isX11OverrideRedirect() {
|
bool CWindow::isX11OverrideRedirect() {
|
||||||
return m_xwaylandSurface && m_xwaylandSurface->m_overrideRedirect;
|
return m_xwaylandSurface && m_xwaylandSurface->m_overrideRedirect;
|
||||||
}
|
}
|
||||||
|
|
@ -1753,7 +1527,7 @@ Vector2D CWindow::requestedMinSize() {
|
||||||
|
|
||||||
Vector2D CWindow::requestedMaxSize() {
|
Vector2D CWindow::requestedMaxSize() {
|
||||||
constexpr int NO_MAX_SIZE_LIMIT = 99999;
|
constexpr int NO_MAX_SIZE_LIMIT = 99999;
|
||||||
if (((m_isX11 && !m_xwaylandSurface->m_sizeHints) || (!m_isX11 && (!m_xdgSurface || !m_xdgSurface->m_toplevel)) || m_windowData.noMaxSize.valueOrDefault()))
|
if (((m_isX11 && !m_xwaylandSurface->m_sizeHints) || (!m_isX11 && (!m_xdgSurface || !m_xdgSurface->m_toplevel)) || m_ruleApplicator->noMaxSize().valueOrDefault()))
|
||||||
return Vector2D(NO_MAX_SIZE_LIMIT, NO_MAX_SIZE_LIMIT);
|
return Vector2D(NO_MAX_SIZE_LIMIT, NO_MAX_SIZE_LIMIT);
|
||||||
|
|
||||||
Vector2D maxSize = m_isX11 ? Vector2D(m_xwaylandSurface->m_sizeHints->max_width, m_xwaylandSurface->m_sizeHints->max_height) : m_xdgSurface->m_toplevel->layoutMaxSize();
|
Vector2D maxSize = m_isX11 ? Vector2D(m_xwaylandSurface->m_sizeHints->max_width, m_xwaylandSurface->m_sizeHints->max_height) : m_xdgSurface->m_toplevel->layoutMaxSize();
|
||||||
|
|
@ -1951,3 +1725,127 @@ Vector2D CWindow::getReportedSize() {
|
||||||
return m_wlSurface->resource()->m_current.ackedSize;
|
return m_wlSurface->resource()->m_current.ackedSize;
|
||||||
return m_reportedSize;
|
return m_reportedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWindow::updateDecorationValues() {
|
||||||
|
static auto PACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.active_border");
|
||||||
|
static auto PINACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.inactive_border");
|
||||||
|
static auto PNOGROUPACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.nogroup_border_active");
|
||||||
|
static auto PNOGROUPINACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.nogroup_border");
|
||||||
|
static auto PGROUPACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_active");
|
||||||
|
static auto PGROUPINACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_inactive");
|
||||||
|
static auto PGROUPACTIVELOCKEDCOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_locked_active");
|
||||||
|
static auto PGROUPINACTIVELOCKEDCOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_locked_inactive");
|
||||||
|
static auto PINACTIVEALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:inactive_opacity");
|
||||||
|
static auto PACTIVEALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:active_opacity");
|
||||||
|
static auto PFULLSCREENALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:fullscreen_opacity");
|
||||||
|
static auto PSHADOWCOL = CConfigValue<Hyprlang::INT>("decoration:shadow:color");
|
||||||
|
static auto PSHADOWCOLINACTIVE = CConfigValue<Hyprlang::INT>("decoration:shadow:color_inactive");
|
||||||
|
static auto PDIMSTRENGTH = CConfigValue<Hyprlang::FLOAT>("decoration:dim_strength");
|
||||||
|
static auto PDIMENABLED = CConfigValue<Hyprlang::INT>("decoration:dim_inactive");
|
||||||
|
static auto PDIMMODAL = CConfigValue<Hyprlang::INT>("decoration:dim_modal");
|
||||||
|
|
||||||
|
auto* const ACTIVECOL = sc<CGradientValueData*>((PACTIVECOL.ptr())->getData());
|
||||||
|
auto* const INACTIVECOL = sc<CGradientValueData*>((PINACTIVECOL.ptr())->getData());
|
||||||
|
auto* const NOGROUPACTIVECOL = sc<CGradientValueData*>((PNOGROUPACTIVECOL.ptr())->getData());
|
||||||
|
auto* const NOGROUPINACTIVECOL = sc<CGradientValueData*>((PNOGROUPINACTIVECOL.ptr())->getData());
|
||||||
|
auto* const GROUPACTIVECOL = sc<CGradientValueData*>((PGROUPACTIVECOL.ptr())->getData());
|
||||||
|
auto* const GROUPINACTIVECOL = sc<CGradientValueData*>((PGROUPINACTIVECOL.ptr())->getData());
|
||||||
|
auto* const GROUPACTIVELOCKEDCOL = sc<CGradientValueData*>((PGROUPACTIVELOCKEDCOL.ptr())->getData());
|
||||||
|
auto* const GROUPINACTIVELOCKEDCOL = sc<CGradientValueData*>((PGROUPINACTIVELOCKEDCOL.ptr())->getData());
|
||||||
|
|
||||||
|
auto setBorderColor = [&](CGradientValueData grad) -> void {
|
||||||
|
if (grad == m_realBorderColor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_realBorderColorPrevious = m_realBorderColor;
|
||||||
|
m_realBorderColor = grad;
|
||||||
|
m_borderFadeAnimationProgress->setValueAndWarp(0.f);
|
||||||
|
*m_borderFadeAnimationProgress = 1.f;
|
||||||
|
};
|
||||||
|
|
||||||
|
const bool IS_SHADOWED_BY_MODAL = m_xdgSurface && m_xdgSurface->m_toplevel && m_xdgSurface->m_toplevel->anyChildModal();
|
||||||
|
|
||||||
|
// border
|
||||||
|
const auto RENDERDATA = g_pLayoutManager->getCurrentLayout()->requestRenderHints(m_self.lock());
|
||||||
|
if (RENDERDATA.isBorderGradient)
|
||||||
|
setBorderColor(*RENDERDATA.borderGradient);
|
||||||
|
else {
|
||||||
|
const bool GROUPLOCKED = m_groupData.pNextWindow.lock() ? getGroupHead()->m_groupData.locked : false;
|
||||||
|
if (m_self == g_pCompositor->m_lastWindow) {
|
||||||
|
const auto* const ACTIVECOLOR =
|
||||||
|
!m_groupData.pNextWindow.lock() ? (!m_groupData.deny ? ACTIVECOL : NOGROUPACTIVECOL) : (GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL);
|
||||||
|
setBorderColor(m_ruleApplicator->activeBorderColor().valueOr(*ACTIVECOLOR));
|
||||||
|
} else {
|
||||||
|
const auto* const INACTIVECOLOR =
|
||||||
|
!m_groupData.pNextWindow.lock() ? (!m_groupData.deny ? INACTIVECOL : NOGROUPINACTIVECOL) : (GROUPLOCKED ? GROUPINACTIVELOCKEDCOL : GROUPINACTIVECOL);
|
||||||
|
setBorderColor(m_ruleApplicator->inactiveBorderColor().valueOr(*INACTIVECOLOR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// opacity
|
||||||
|
const auto PWORKSPACE = m_workspace;
|
||||||
|
if (isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) {
|
||||||
|
*m_activeInactiveAlpha = m_ruleApplicator->alphaFullscreen().valueOrDefault().applyAlpha(*PFULLSCREENALPHA);
|
||||||
|
} else {
|
||||||
|
if (m_self == g_pCompositor->m_lastWindow)
|
||||||
|
*m_activeInactiveAlpha = m_ruleApplicator->alpha().valueOrDefault().applyAlpha(*PACTIVEALPHA);
|
||||||
|
else
|
||||||
|
*m_activeInactiveAlpha = m_ruleApplicator->alphaInactive().valueOrDefault().applyAlpha(*PINACTIVEALPHA);
|
||||||
|
}
|
||||||
|
|
||||||
|
// dim
|
||||||
|
float goalDim = 1.F;
|
||||||
|
if (m_self == g_pCompositor->m_lastWindow.lock() || m_ruleApplicator->noDim().valueOrDefault() || !*PDIMENABLED)
|
||||||
|
goalDim = 0;
|
||||||
|
else
|
||||||
|
goalDim = *PDIMSTRENGTH;
|
||||||
|
|
||||||
|
if (IS_SHADOWED_BY_MODAL && *PDIMMODAL)
|
||||||
|
goalDim += (1.F - goalDim) / 2.F;
|
||||||
|
|
||||||
|
*m_dimPercent = goalDim;
|
||||||
|
|
||||||
|
// shadow
|
||||||
|
if (!isX11OverrideRedirect() && !m_X11DoesntWantBorders) {
|
||||||
|
if (m_self == g_pCompositor->m_lastWindow)
|
||||||
|
*m_realShadowColor = CHyprColor(*PSHADOWCOL);
|
||||||
|
else
|
||||||
|
*m_realShadowColor = CHyprColor(*PSHADOWCOLINACTIVE != -1 ? *PSHADOWCOLINACTIVE : *PSHADOWCOL);
|
||||||
|
} else
|
||||||
|
m_realShadowColor->setValueAndWarp(CHyprColor(0, 0, 0, 0)); // no shadow
|
||||||
|
|
||||||
|
updateWindowDecos();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<double> CWindow::calculateSingleExpr(const std::string& s) {
|
||||||
|
const auto PMONITOR = m_monitor ? m_monitor : g_pCompositor->m_lastMonitor;
|
||||||
|
const auto CURSOR_LOCAL = g_pInputManager->getMouseCoordsInternal() - (PMONITOR ? PMONITOR->m_position : Vector2D{});
|
||||||
|
|
||||||
|
Math::CExpression expr;
|
||||||
|
expr.addVariable("window_w", m_realSize->goal().x);
|
||||||
|
expr.addVariable("window_h", m_realSize->goal().y);
|
||||||
|
expr.addVariable("window_x", m_realPosition->goal().x - (PMONITOR ? PMONITOR->m_position.x : 0));
|
||||||
|
expr.addVariable("window_y", m_realPosition->goal().y - (PMONITOR ? PMONITOR->m_position.y : 0));
|
||||||
|
|
||||||
|
expr.addVariable("monitor_w", PMONITOR ? PMONITOR->m_size.x : 1920);
|
||||||
|
expr.addVariable("monitor_h", PMONITOR ? PMONITOR->m_size.y : 1080);
|
||||||
|
|
||||||
|
expr.addVariable("cursor_x", CURSOR_LOCAL.x);
|
||||||
|
expr.addVariable("cursor_y", CURSOR_LOCAL.y);
|
||||||
|
|
||||||
|
return expr.compute(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<Vector2D> CWindow::calculateExpression(const std::string& s) {
|
||||||
|
auto spacePos = s.find(' ');
|
||||||
|
if (spacePos == std::string::npos)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
const auto LHS = calculateSingleExpr(s.substr(0, spacePos));
|
||||||
|
const auto RHS = calculateSingleExpr(s.substr(spacePos + 1));
|
||||||
|
|
||||||
|
if (!LHS || !RHS)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
return Vector2D{*LHS, *RHS};
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,20 +16,12 @@
|
||||||
#include "Subsurface.hpp"
|
#include "Subsurface.hpp"
|
||||||
#include "WLSurface.hpp"
|
#include "WLSurface.hpp"
|
||||||
#include "Workspace.hpp"
|
#include "Workspace.hpp"
|
||||||
#include "WindowRule.hpp"
|
#include "rule/windowRule/WindowRuleApplicator.hpp"
|
||||||
#include "WindowOverridableVar.hpp"
|
|
||||||
#include "../protocols/types/ContentType.hpp"
|
#include "../protocols/types/ContentType.hpp"
|
||||||
|
|
||||||
class CXDGSurfaceResource;
|
class CXDGSurfaceResource;
|
||||||
class CXWaylandSurface;
|
class CXWaylandSurface;
|
||||||
|
|
||||||
enum eIdleInhibitMode : uint8_t {
|
|
||||||
IDLEINHIBIT_NONE = 0,
|
|
||||||
IDLEINHIBIT_ALWAYS,
|
|
||||||
IDLEINHIBIT_FULLSCREEN,
|
|
||||||
IDLEINHIBIT_FOCUS
|
|
||||||
};
|
|
||||||
|
|
||||||
enum eGroupRules : uint8_t {
|
enum eGroupRules : uint8_t {
|
||||||
// effective only during first map, except for _ALWAYS variant
|
// effective only during first map, except for _ALWAYS variant
|
||||||
GROUP_NONE = 0,
|
GROUP_NONE = 0,
|
||||||
|
|
@ -65,65 +57,6 @@ enum eSuppressEvents : uint8_t {
|
||||||
|
|
||||||
class IWindowTransformer;
|
class IWindowTransformer;
|
||||||
|
|
||||||
struct SAlphaValue {
|
|
||||||
float alpha;
|
|
||||||
bool overridden;
|
|
||||||
|
|
||||||
float applyAlpha(float a) const {
|
|
||||||
if (overridden)
|
|
||||||
return alpha;
|
|
||||||
else
|
|
||||||
return alpha * a;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SWindowData {
|
|
||||||
CWindowOverridableVar<SAlphaValue> alpha = SAlphaValue{.alpha = 1.f, .overridden = false};
|
|
||||||
CWindowOverridableVar<SAlphaValue> alphaInactive = SAlphaValue{.alpha = 1.f, .overridden = false};
|
|
||||||
CWindowOverridableVar<SAlphaValue> alphaFullscreen = SAlphaValue{.alpha = 1.f, .overridden = false};
|
|
||||||
|
|
||||||
CWindowOverridableVar<bool> allowsInput = false;
|
|
||||||
CWindowOverridableVar<bool> dimAround = false;
|
|
||||||
CWindowOverridableVar<bool> decorate = true;
|
|
||||||
CWindowOverridableVar<bool> focusOnActivate = false;
|
|
||||||
CWindowOverridableVar<bool> keepAspectRatio = false;
|
|
||||||
CWindowOverridableVar<bool> nearestNeighbor = false;
|
|
||||||
CWindowOverridableVar<bool> noAnim = false;
|
|
||||||
CWindowOverridableVar<bool> noBorder = false;
|
|
||||||
CWindowOverridableVar<bool> noBlur = false;
|
|
||||||
CWindowOverridableVar<bool> noDim = false;
|
|
||||||
CWindowOverridableVar<bool> noFocus = false;
|
|
||||||
CWindowOverridableVar<bool> noMaxSize = false;
|
|
||||||
CWindowOverridableVar<bool> noRounding = false;
|
|
||||||
CWindowOverridableVar<bool> noShadow = false;
|
|
||||||
CWindowOverridableVar<bool> noShortcutsInhibit = false;
|
|
||||||
CWindowOverridableVar<bool> opaque = false;
|
|
||||||
CWindowOverridableVar<bool> RGBX = false;
|
|
||||||
CWindowOverridableVar<bool> syncFullscreen = true;
|
|
||||||
CWindowOverridableVar<bool> tearing = false;
|
|
||||||
CWindowOverridableVar<bool> xray = false;
|
|
||||||
CWindowOverridableVar<bool> renderUnfocused = false;
|
|
||||||
CWindowOverridableVar<bool> noFollowMouse = false;
|
|
||||||
CWindowOverridableVar<bool> noScreenShare = false;
|
|
||||||
CWindowOverridableVar<bool> noVRR = false;
|
|
||||||
|
|
||||||
CWindowOverridableVar<Hyprlang::INT> borderSize = {std::string("general:border_size"), sc<Hyprlang::INT>(0), std::nullopt};
|
|
||||||
CWindowOverridableVar<Hyprlang::INT> rounding = {std::string("decoration:rounding"), sc<Hyprlang::INT>(0), std::nullopt};
|
|
||||||
|
|
||||||
CWindowOverridableVar<Hyprlang::FLOAT> roundingPower = {std::string("decoration:rounding_power")};
|
|
||||||
CWindowOverridableVar<Hyprlang::FLOAT> scrollMouse = {std::string("input:scroll_factor")};
|
|
||||||
CWindowOverridableVar<Hyprlang::FLOAT> scrollTouchpad = {std::string("input:touchpad:scroll_factor")};
|
|
||||||
|
|
||||||
CWindowOverridableVar<std::string> animationStyle;
|
|
||||||
CWindowOverridableVar<Vector2D> maxSize;
|
|
||||||
CWindowOverridableVar<Vector2D> minSize;
|
|
||||||
|
|
||||||
CWindowOverridableVar<CGradientValueData> activeBorderColor;
|
|
||||||
CWindowOverridableVar<CGradientValueData> inactiveBorderColor;
|
|
||||||
|
|
||||||
CWindowOverridableVar<bool> persistentSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SInitialWorkspaceToken {
|
struct SInitialWorkspaceToken {
|
||||||
PHLWINDOWREF primaryOwner;
|
PHLWINDOWREF primaryOwner;
|
||||||
std::string workspace;
|
std::string workspace;
|
||||||
|
|
@ -256,7 +189,7 @@ class CWindow {
|
||||||
std::vector<IHyprWindowDecoration*> m_decosToRemove;
|
std::vector<IHyprWindowDecoration*> m_decosToRemove;
|
||||||
|
|
||||||
// Special render data, rules, etc
|
// Special render data, rules, etc
|
||||||
SWindowData m_windowData;
|
UP<Desktop::Rule::CWindowRuleApplicator> m_ruleApplicator;
|
||||||
|
|
||||||
// Transformers
|
// Transformers
|
||||||
std::vector<UP<IWindowTransformer>> m_transformers;
|
std::vector<UP<IWindowTransformer>> m_transformers;
|
||||||
|
|
@ -280,15 +213,9 @@ class CWindow {
|
||||||
bool m_currentlySwallowed = false;
|
bool m_currentlySwallowed = false;
|
||||||
bool m_groupSwallowed = false;
|
bool m_groupSwallowed = false;
|
||||||
|
|
||||||
// focus stuff
|
|
||||||
bool m_stayFocused = false;
|
|
||||||
|
|
||||||
// for toplevel monitor events
|
// for toplevel monitor events
|
||||||
MONITORID m_lastSurfaceMonitorID = -1;
|
MONITORID m_lastSurfaceMonitorID = -1;
|
||||||
|
|
||||||
// for idle inhibiting windows
|
|
||||||
eIdleInhibitMode m_idleInhibitMode = IDLEINHIBIT_NONE;
|
|
||||||
|
|
||||||
// initial token. Will be unregistered on workspace change or timeout of 2 minutes
|
// initial token. Will be unregistered on workspace change or timeout of 2 minutes
|
||||||
std::string m_initialWorkspaceToken = "";
|
std::string m_initialWorkspaceToken = "";
|
||||||
|
|
||||||
|
|
@ -303,12 +230,6 @@ class CWindow {
|
||||||
|
|
||||||
bool m_tearingHint = false;
|
bool m_tearingHint = false;
|
||||||
|
|
||||||
// stores the currently matched window rules
|
|
||||||
std::vector<SP<CWindowRule>> m_matchedRules;
|
|
||||||
|
|
||||||
// window tags
|
|
||||||
CTagKeeper m_tags;
|
|
||||||
|
|
||||||
// ANR
|
// ANR
|
||||||
PHLANIMVAR<float> m_notRespondingTint;
|
PHLANIMVAR<float> m_notRespondingTint;
|
||||||
|
|
||||||
|
|
@ -342,8 +263,7 @@ class CWindow {
|
||||||
void onMap();
|
void onMap();
|
||||||
void setHidden(bool hidden);
|
void setHidden(bool hidden);
|
||||||
bool isHidden();
|
bool isHidden();
|
||||||
void applyDynamicRule(const SP<CWindowRule>& r);
|
void updateDecorationValues();
|
||||||
void updateDynamicRules();
|
|
||||||
SBoxExtents getFullWindowReservedArea();
|
SBoxExtents getFullWindowReservedArea();
|
||||||
Vector2D middle();
|
Vector2D middle();
|
||||||
bool opaque();
|
bool opaque();
|
||||||
|
|
@ -397,7 +317,6 @@ class CWindow {
|
||||||
std::string fetchClass();
|
std::string fetchClass();
|
||||||
void warpCursor(bool force = false);
|
void warpCursor(bool force = false);
|
||||||
PHLWINDOW getSwallower();
|
PHLWINDOW getSwallower();
|
||||||
void unsetWindowData(eOverridePriority priority);
|
|
||||||
bool isX11OverrideRedirect();
|
bool isX11OverrideRedirect();
|
||||||
bool isModal();
|
bool isModal();
|
||||||
Vector2D requestedMinSize();
|
Vector2D requestedMinSize();
|
||||||
|
|
@ -418,6 +337,7 @@ class CWindow {
|
||||||
bool priorityFocus();
|
bool priorityFocus();
|
||||||
SP<CWLSurfaceResource> getSolitaryResource();
|
SP<CWLSurfaceResource> getSolitaryResource();
|
||||||
Vector2D getReportedSize();
|
Vector2D getReportedSize();
|
||||||
|
std::optional<Vector2D> calculateExpression(const std::string& s);
|
||||||
|
|
||||||
CBox getWindowMainSurfaceBox() const {
|
CBox getWindowMainSurfaceBox() const {
|
||||||
return {m_realPosition->value().x, m_realPosition->value().y, m_realSize->value().x, m_realSize->value().y};
|
return {m_realPosition->value().x, m_realPosition->value().y, m_realSize->value().x, m_realSize->value().y};
|
||||||
|
|
@ -448,6 +368,8 @@ class CWindow {
|
||||||
} m_listeners;
|
} m_listeners;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::optional<double> calculateSingleExpr(const std::string& s);
|
||||||
|
|
||||||
// For hidden windows and stuff
|
// For hidden windows and stuff
|
||||||
bool m_hidden = false;
|
bool m_hidden = false;
|
||||||
bool m_suspended = false;
|
bool m_suspended = false;
|
||||||
|
|
@ -474,45 +396,6 @@ inline bool validMapped(PHLWINDOWREF w) {
|
||||||
return w->m_isMapped;
|
return w->m_isMapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace NWindowProperties {
|
|
||||||
static const std::unordered_map<std::string, std::function<CWindowOverridableVar<bool>*(const PHLWINDOW&)>> boolWindowProperties = {
|
|
||||||
{"allowsinput", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.allowsInput; }},
|
|
||||||
{"dimaround", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.dimAround; }},
|
|
||||||
{"decorate", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.decorate; }},
|
|
||||||
{"focusonactivate", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.focusOnActivate; }},
|
|
||||||
{"keepaspectratio", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.keepAspectRatio; }},
|
|
||||||
{"nearestneighbor", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.nearestNeighbor; }},
|
|
||||||
{"noanim", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.noAnim; }},
|
|
||||||
{"noblur", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.noBlur; }},
|
|
||||||
{"noborder", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.noBorder; }},
|
|
||||||
{"nodim", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.noDim; }},
|
|
||||||
{"nofocus", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.noFocus; }},
|
|
||||||
{"nomaxsize", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.noMaxSize; }},
|
|
||||||
{"norounding", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.noRounding; }},
|
|
||||||
{"noshadow", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.noShadow; }},
|
|
||||||
{"noshortcutsinhibit", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.noShortcutsInhibit; }},
|
|
||||||
{"opaque", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.opaque; }},
|
|
||||||
{"forcergbx", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.RGBX; }},
|
|
||||||
{"syncfullscreen", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.syncFullscreen; }},
|
|
||||||
{"novrr", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.noVRR; }},
|
|
||||||
{"immediate", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.tearing; }},
|
|
||||||
{"xray", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.xray; }},
|
|
||||||
{"nofollowmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.noFollowMouse; }},
|
|
||||||
{"noscreenshare", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.noScreenShare; }},
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::unordered_map<std::string, std::function<CWindowOverridableVar<Hyprlang::INT>*(const PHLWINDOW&)>> intWindowProperties = {
|
|
||||||
{"rounding", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.rounding; }},
|
|
||||||
{"bordersize", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.borderSize; }},
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::unordered_map<std::string, std::function<CWindowOverridableVar<Hyprlang::FLOAT>*(PHLWINDOW)>> floatWindowProperties = {
|
|
||||||
{"roundingpower", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.roundingPower; }},
|
|
||||||
{"scrollmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.scrollMouse; }},
|
|
||||||
{"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_windowData.scrollTouchpad; }},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
format specification
|
format specification
|
||||||
- 'x', only address, equivalent of (uintpr_t)CWindow*
|
- 'x', only address, equivalent of (uintpr_t)CWindow*
|
||||||
|
|
|
||||||
|
|
@ -1,132 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <any>
|
|
||||||
#include "../config/ConfigValue.hpp"
|
|
||||||
|
|
||||||
enum eOverridePriority : uint8_t {
|
|
||||||
PRIORITY_LAYOUT = 0,
|
|
||||||
PRIORITY_WORKSPACE_RULE,
|
|
||||||
PRIORITY_WINDOW_RULE,
|
|
||||||
PRIORITY_SET_PROP,
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T clampOptional(T const& value, std::optional<T> const& min, std::optional<T> const& max) {
|
|
||||||
return std::clamp(value, min.value_or(std::numeric_limits<T>::min()), max.value_or(std::numeric_limits<T>::max()));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, bool Extended = std::is_same_v<T, bool> || std::is_same_v<T, Hyprlang::INT> || std::is_same_v<T, Hyprlang::FLOAT>>
|
|
||||||
class CWindowOverridableVar {
|
|
||||||
public:
|
|
||||||
CWindowOverridableVar(T const& value, eOverridePriority priority) {
|
|
||||||
m_values[priority] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
CWindowOverridableVar(T const& value) : m_defaultValue{value} {}
|
|
||||||
CWindowOverridableVar(T const& value, std::optional<T> const& min, std::optional<T> const& max = std::nullopt) : m_defaultValue{value}, m_minValue{min}, m_maxValue{max} {}
|
|
||||||
CWindowOverridableVar(std::string const& value)
|
|
||||||
requires(Extended && !std::is_same_v<T, bool>)
|
|
||||||
: m_configValue(SP<CConfigValue<T>>(new CConfigValue<T>(value))) {}
|
|
||||||
CWindowOverridableVar(std::string const& value, std::optional<T> const& min, std::optional<T> const& max = std::nullopt)
|
|
||||||
requires(Extended && !std::is_same_v<T, bool>)
|
|
||||||
: m_minValue(min), m_maxValue(max), m_configValue(SP<CConfigValue<T>>(new CConfigValue<T>(value))) {}
|
|
||||||
|
|
||||||
CWindowOverridableVar() = default;
|
|
||||||
~CWindowOverridableVar() = default;
|
|
||||||
|
|
||||||
CWindowOverridableVar& operator=(CWindowOverridableVar<T> const& other) {
|
|
||||||
// Self-assignment check
|
|
||||||
if (this == &other)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
for (auto const& value : other.m_values) {
|
|
||||||
if constexpr (Extended && !std::is_same_v<T, bool>)
|
|
||||||
m_values[value.first] = clampOptional(value.second, m_minValue, m_maxValue);
|
|
||||||
else
|
|
||||||
m_values[value.first] = value.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unset(eOverridePriority priority) {
|
|
||||||
m_values.erase(priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasValue() {
|
|
||||||
return !m_values.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
T value() {
|
|
||||||
if (!m_values.empty())
|
|
||||||
return std::prev(m_values.end())->second;
|
|
||||||
else
|
|
||||||
throw std::bad_optional_access();
|
|
||||||
}
|
|
||||||
|
|
||||||
T valueOr(T const& other) {
|
|
||||||
if (hasValue())
|
|
||||||
return value();
|
|
||||||
else
|
|
||||||
return other;
|
|
||||||
}
|
|
||||||
|
|
||||||
T valueOrDefault()
|
|
||||||
requires(Extended && !std::is_same_v<T, bool>)
|
|
||||||
{
|
|
||||||
if (hasValue())
|
|
||||||
return value();
|
|
||||||
else if (m_defaultValue.has_value())
|
|
||||||
return m_defaultValue.value();
|
|
||||||
else
|
|
||||||
return **std::any_cast<SP<CConfigValue<T>>>(m_configValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
T valueOrDefault()
|
|
||||||
requires(!Extended || std::is_same_v<T, bool>)
|
|
||||||
{
|
|
||||||
if (hasValue())
|
|
||||||
return value();
|
|
||||||
else if (!m_defaultValue.has_value())
|
|
||||||
throw std::bad_optional_access();
|
|
||||||
else
|
|
||||||
return m_defaultValue.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
eOverridePriority getPriority() {
|
|
||||||
if (!m_values.empty())
|
|
||||||
return std::prev(m_values.end())->first;
|
|
||||||
else
|
|
||||||
throw std::bad_optional_access();
|
|
||||||
}
|
|
||||||
|
|
||||||
void increment(T const& other, eOverridePriority priority) {
|
|
||||||
if constexpr (std::is_same_v<T, bool>)
|
|
||||||
m_values[priority] = valueOr(false) ^ other;
|
|
||||||
else
|
|
||||||
m_values[priority] = clampOptional(valueOrDefault() + other, m_minValue, m_maxValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void matchOptional(std::optional<T> const& optValue, eOverridePriority priority) {
|
|
||||||
if (optValue.has_value())
|
|
||||||
m_values[priority] = optValue.value();
|
|
||||||
else
|
|
||||||
unset(priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator std::optional<T>() {
|
|
||||||
if (hasValue())
|
|
||||||
return value();
|
|
||||||
else
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::map<eOverridePriority, T> m_values;
|
|
||||||
std::optional<T> m_defaultValue; // used for toggling, so required for bool
|
|
||||||
std::optional<T> m_minValue;
|
|
||||||
std::optional<T> m_maxValue;
|
|
||||||
std::any m_configValue; // only there for select variables
|
|
||||||
};
|
|
||||||
|
|
@ -1,99 +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", "persistentsize",
|
|
||||||
};
|
|
||||||
static const auto RULES_PREFIX = std::unordered_set<std::string>{
|
|
||||||
"animation", "bordercolor", "bordersize", "center", "content", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor",
|
|
||||||
"move", "noclosefor", "opacity", "plugin:", "prop", "pseudo", "rounding", "roundingpower", "scrollmouse", "scrolltouchpad", "size",
|
|
||||||
"suppressevent", "tag", "workspace", "xray", "novrr",
|
|
||||||
};
|
|
||||||
|
|
||||||
CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool isV2, bool isExecRule) : m_value(value), m_rule(rule), m_v2(isV2), m_execRule(isExecRule) {
|
|
||||||
const auto VALS = CVarList(rule, 2, ' ');
|
|
||||||
const bool VALID = RULES.contains(rule) || std::ranges::any_of(RULES_PREFIX, [&rule](auto prefix) { return rule.starts_with(prefix); }) ||
|
|
||||||
(NWindowProperties::boolWindowProperties.contains(VALS[0])) || (NWindowProperties::intWindowProperties.contains(VALS[0])) ||
|
|
||||||
(NWindowProperties::floatWindowProperties.contains(VALS[0]));
|
|
||||||
|
|
||||||
if (!VALID)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (rule == "float")
|
|
||||||
m_ruleType = RULE_FLOAT;
|
|
||||||
else if (rule == "fullscreen")
|
|
||||||
m_ruleType = RULE_FULLSCREEN;
|
|
||||||
else if (rule == "maximize")
|
|
||||||
m_ruleType = RULE_MAXIMIZE;
|
|
||||||
else if (rule == "noinitialfocus")
|
|
||||||
m_ruleType = RULE_NOINITIALFOCUS;
|
|
||||||
else if (rule == "pin")
|
|
||||||
m_ruleType = RULE_PIN;
|
|
||||||
else if (rule == "stayfocused")
|
|
||||||
m_ruleType = RULE_STAYFOCUSED;
|
|
||||||
else if (rule == "tile")
|
|
||||||
m_ruleType = RULE_TILE;
|
|
||||||
else if (rule == "renderunfocused")
|
|
||||||
m_ruleType = RULE_RENDERUNFOCUSED;
|
|
||||||
else if (rule == "persistentsize")
|
|
||||||
m_ruleType = RULE_PERSISTENTSIZE;
|
|
||||||
else if (rule.starts_with("animation"))
|
|
||||||
m_ruleType = RULE_ANIMATION;
|
|
||||||
else if (rule.starts_with("bordercolor"))
|
|
||||||
m_ruleType = RULE_BORDERCOLOR;
|
|
||||||
else if (rule.starts_with("center"))
|
|
||||||
m_ruleType = RULE_CENTER;
|
|
||||||
else if (rule.starts_with("fullscreenstate"))
|
|
||||||
m_ruleType = RULE_FULLSCREENSTATE;
|
|
||||||
else if (rule.starts_with("group"))
|
|
||||||
m_ruleType = RULE_GROUP;
|
|
||||||
else if (rule.starts_with("idleinhibit"))
|
|
||||||
m_ruleType = RULE_IDLEINHIBIT;
|
|
||||||
else if (rule.starts_with("maxsize"))
|
|
||||||
m_ruleType = RULE_MAXSIZE;
|
|
||||||
else if (rule.starts_with("minsize"))
|
|
||||||
m_ruleType = RULE_MINSIZE;
|
|
||||||
else if (rule.starts_with("monitor"))
|
|
||||||
m_ruleType = RULE_MONITOR;
|
|
||||||
else if (rule.starts_with("move"))
|
|
||||||
m_ruleType = RULE_MOVE;
|
|
||||||
else if (rule.starts_with("opacity"))
|
|
||||||
m_ruleType = RULE_OPACITY;
|
|
||||||
else if (rule.starts_with("plugin:"))
|
|
||||||
m_ruleType = RULE_PLUGIN;
|
|
||||||
else if (rule.starts_with("pseudo"))
|
|
||||||
m_ruleType = RULE_PSEUDO;
|
|
||||||
else if (rule.starts_with("size"))
|
|
||||||
m_ruleType = RULE_SIZE;
|
|
||||||
else if (rule.starts_with("suppressevent"))
|
|
||||||
m_ruleType = RULE_SUPPRESSEVENT;
|
|
||||||
else if (rule.starts_with("novrr"))
|
|
||||||
m_ruleType = RULE_NOVRR;
|
|
||||||
else if (rule.starts_with("tag"))
|
|
||||||
m_ruleType = RULE_TAG;
|
|
||||||
else if (rule.starts_with("workspace"))
|
|
||||||
m_ruleType = RULE_WORKSPACE;
|
|
||||||
else if (rule.starts_with("prop"))
|
|
||||||
m_ruleType = RULE_PROP;
|
|
||||||
else if (rule.starts_with("content"))
|
|
||||||
m_ruleType = RULE_CONTENT;
|
|
||||||
else if (rule.starts_with("noclosefor"))
|
|
||||||
m_ruleType = RULE_NOCLOSEFOR;
|
|
||||||
else {
|
|
||||||
// check if this is a prop.
|
|
||||||
const CVarList VARS(rule, 0, 's', true);
|
|
||||||
const bool ISPROP = NWindowProperties::intWindowProperties.contains(VARS[0]) || NWindowProperties::boolWindowProperties.contains(VARS[0]) ||
|
|
||||||
NWindowProperties::floatWindowProperties.contains(VARS[0]);
|
|
||||||
if (ISPROP) {
|
|
||||||
*const_cast<std::string*>(&m_rule) = "prop " + rule;
|
|
||||||
m_ruleType = RULE_PROP;
|
|
||||||
Debug::log(LOG, "CWindowRule: direct prop rule found, rewritten {} -> {}", rule, m_rule);
|
|
||||||
} else {
|
|
||||||
Debug::log(ERR, "CWindowRule: didn't match a rule that was found valid?!");
|
|
||||||
m_ruleType = RULE_INVALID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,76 +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,
|
|
||||||
RULE_CONTENT,
|
|
||||||
RULE_PERSISTENTSIZE,
|
|
||||||
RULE_NOCLOSEFOR,
|
|
||||||
RULE_NOVRR,
|
|
||||||
};
|
|
||||||
|
|
||||||
eRuleType m_ruleType = RULE_INVALID;
|
|
||||||
|
|
||||||
const std::string m_value;
|
|
||||||
const std::string m_rule;
|
|
||||||
const bool m_v2 = false;
|
|
||||||
const bool m_execRule = false;
|
|
||||||
|
|
||||||
std::string m_title;
|
|
||||||
std::string m_class;
|
|
||||||
std::string m_initialTitle;
|
|
||||||
std::string m_initialClass;
|
|
||||||
std::string m_tag;
|
|
||||||
int m_X11 = -1; // -1 means "ANY"
|
|
||||||
int m_floating = -1;
|
|
||||||
int m_fullscreen = -1;
|
|
||||||
int m_pinned = -1;
|
|
||||||
int m_focus = -1;
|
|
||||||
int m_group = -1;
|
|
||||||
int m_modal = -1;
|
|
||||||
std::string m_fullscreenState = ""; // empty means any
|
|
||||||
std::string m_onWorkspace = ""; // empty means any
|
|
||||||
std::string m_workspace = ""; // empty means any
|
|
||||||
std::string m_contentType = ""; // empty means any
|
|
||||||
std::string m_xdgTag = ""; // empty means any
|
|
||||||
|
|
||||||
// precompiled regexes
|
|
||||||
CRuleRegexContainer m_titleRegex;
|
|
||||||
CRuleRegexContainer m_classRegex;
|
|
||||||
CRuleRegexContainer m_initialTitleRegex;
|
|
||||||
CRuleRegexContainer m_initialClassRegex;
|
|
||||||
CRuleRegexContainer m_v1Regex;
|
|
||||||
};
|
|
||||||
|
|
@ -542,7 +542,7 @@ void CWorkspace::updateWindows() {
|
||||||
if (!w->m_isMapped || w->m_workspace != m_self)
|
if (!w->m_isMapped || w->m_workspace != m_self)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
w->updateDynamicRules();
|
w->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
56
src/desktop/rule/Engine.cpp
Normal file
56
src/desktop/rule/Engine.cpp
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
#include "Engine.hpp"
|
||||||
|
#include "Rule.hpp"
|
||||||
|
#include "../LayerSurface.hpp"
|
||||||
|
#include "../../Compositor.hpp"
|
||||||
|
|
||||||
|
using namespace Desktop;
|
||||||
|
using namespace Desktop::Rule;
|
||||||
|
|
||||||
|
SP<CRuleEngine> Rule::ruleEngine() {
|
||||||
|
static SP<CRuleEngine> engine = makeShared<CRuleEngine>();
|
||||||
|
return engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRuleEngine::registerRule(SP<IRule>&& rule) {
|
||||||
|
m_rules.emplace_back(std::move(rule));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRuleEngine::unregisterRule(const std::string& name) {
|
||||||
|
if (name.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::erase_if(m_rules, [&name](const auto& el) { return el->name() == name; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRuleEngine::unregisterRule(const SP<IRule>& rule) {
|
||||||
|
std::erase(m_rules, rule);
|
||||||
|
cleanExecRules();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRuleEngine::cleanExecRules() {
|
||||||
|
std::erase_if(m_rules, [](const auto& e) { return e->isExecRule() && e->execExpired(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRuleEngine::updateAllRules() {
|
||||||
|
cleanExecRules();
|
||||||
|
for (const auto& w : g_pCompositor->m_windows) {
|
||||||
|
if (!validMapped(w) || w->isHidden())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
w->m_ruleApplicator->propertiesChanged(RULE_PROP_ALL);
|
||||||
|
}
|
||||||
|
for (const auto& ls : g_pCompositor->m_layers) {
|
||||||
|
if (!validMapped(ls))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ls->m_ruleApplicator->propertiesChanged(RULE_PROP_ALL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRuleEngine::clearAllRules() {
|
||||||
|
std::erase_if(m_rules, [](const auto& e) { return !e->isExecRule() || e->execExpired(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<SP<IRule>>& CRuleEngine::rules() {
|
||||||
|
return m_rules;
|
||||||
|
}
|
||||||
24
src/desktop/rule/Engine.hpp
Normal file
24
src/desktop/rule/Engine.hpp
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Rule.hpp"
|
||||||
|
|
||||||
|
namespace Desktop::Rule {
|
||||||
|
class CRuleEngine {
|
||||||
|
public:
|
||||||
|
CRuleEngine() = default;
|
||||||
|
~CRuleEngine() = default;
|
||||||
|
|
||||||
|
void registerRule(SP<IRule>&& rule);
|
||||||
|
void unregisterRule(const std::string& name);
|
||||||
|
void unregisterRule(const SP<IRule>& rule);
|
||||||
|
void updateAllRules();
|
||||||
|
void cleanExecRules();
|
||||||
|
void clearAllRules();
|
||||||
|
const std::vector<SP<IRule>>& rules();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<SP<IRule>> m_rules;
|
||||||
|
};
|
||||||
|
|
||||||
|
SP<CRuleEngine> ruleEngine();
|
||||||
|
}
|
||||||
149
src/desktop/rule/Rule.cpp
Normal file
149
src/desktop/rule/Rule.cpp
Normal file
|
|
@ -0,0 +1,149 @@
|
||||||
|
#include "Rule.hpp"
|
||||||
|
#include "../../debug/Log.hpp"
|
||||||
|
#include <re2/re2.h>
|
||||||
|
|
||||||
|
#include "matchEngine/RegexMatchEngine.hpp"
|
||||||
|
#include "matchEngine/BoolMatchEngine.hpp"
|
||||||
|
#include "matchEngine/IntMatchEngine.hpp"
|
||||||
|
#include "matchEngine/WorkspaceMatchEngine.hpp"
|
||||||
|
#include "matchEngine/TagMatchEngine.hpp"
|
||||||
|
|
||||||
|
using namespace Desktop;
|
||||||
|
using namespace Desktop::Rule;
|
||||||
|
|
||||||
|
static const std::unordered_map<eRuleProperty, std::string> MATCH_PROP_STRINGS = {
|
||||||
|
{RULE_PROP_CLASS, "class"}, //
|
||||||
|
{RULE_PROP_TITLE, "title"}, //
|
||||||
|
{RULE_PROP_INITIAL_CLASS, "initial_class"}, //
|
||||||
|
{RULE_PROP_INITIAL_TITLE, "initial_title"}, //
|
||||||
|
{RULE_PROP_FLOATING, "float"}, //
|
||||||
|
{RULE_PROP_TAG, "tag"}, //
|
||||||
|
{RULE_PROP_XWAYLAND, "xwayland"}, //
|
||||||
|
{RULE_PROP_FULLSCREEN, "fullscreen"}, //
|
||||||
|
{RULE_PROP_PINNED, "pin"}, //
|
||||||
|
{RULE_PROP_FOCUS, "focus"}, //
|
||||||
|
{RULE_PROP_GROUP, "group"}, //
|
||||||
|
{RULE_PROP_MODAL, "modal"}, //
|
||||||
|
{RULE_PROP_FULLSCREENSTATE_INTERNAL, "fullscreen_state_internal"}, //
|
||||||
|
{RULE_PROP_FULLSCREENSTATE_CLIENT, "fullscreen_state_client"}, //
|
||||||
|
{RULE_PROP_ON_WORKSPACE, "workspace"}, //
|
||||||
|
{RULE_PROP_CONTENT, "content"}, //
|
||||||
|
{RULE_PROP_XDG_TAG, "xdg_tag"}, //
|
||||||
|
{RULE_PROP_NAMESPACE, "namespace"}, //
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::unordered_map<eRuleProperty, eRuleMatchEngine> RULE_ENGINES = {
|
||||||
|
{RULE_PROP_CLASS, RULE_MATCH_ENGINE_REGEX}, //
|
||||||
|
{RULE_PROP_TITLE, RULE_MATCH_ENGINE_REGEX}, //
|
||||||
|
{RULE_PROP_INITIAL_CLASS, RULE_MATCH_ENGINE_REGEX}, //
|
||||||
|
{RULE_PROP_INITIAL_TITLE, RULE_MATCH_ENGINE_REGEX}, //
|
||||||
|
{RULE_PROP_FLOATING, RULE_MATCH_ENGINE_BOOL}, //
|
||||||
|
{RULE_PROP_TAG, RULE_MATCH_ENGINE_TAG}, //
|
||||||
|
{RULE_PROP_XWAYLAND, RULE_MATCH_ENGINE_BOOL}, //
|
||||||
|
{RULE_PROP_FULLSCREEN, RULE_MATCH_ENGINE_BOOL}, //
|
||||||
|
{RULE_PROP_PINNED, RULE_MATCH_ENGINE_BOOL}, //
|
||||||
|
{RULE_PROP_FOCUS, RULE_MATCH_ENGINE_BOOL}, //
|
||||||
|
{RULE_PROP_GROUP, RULE_MATCH_ENGINE_BOOL}, //
|
||||||
|
{RULE_PROP_MODAL, RULE_MATCH_ENGINE_BOOL}, //
|
||||||
|
{RULE_PROP_FULLSCREENSTATE_INTERNAL, RULE_MATCH_ENGINE_INT}, //
|
||||||
|
{RULE_PROP_FULLSCREENSTATE_CLIENT, RULE_MATCH_ENGINE_INT}, //
|
||||||
|
{RULE_PROP_ON_WORKSPACE, RULE_MATCH_ENGINE_WORKSPACE}, //
|
||||||
|
{RULE_PROP_CONTENT, RULE_MATCH_ENGINE_INT}, //
|
||||||
|
{RULE_PROP_XDG_TAG, RULE_MATCH_ENGINE_REGEX}, //
|
||||||
|
{RULE_PROP_NAMESPACE, RULE_MATCH_ENGINE_REGEX}, //
|
||||||
|
{RULE_PROP_EXEC_TOKEN, RULE_MATCH_ENGINE_REGEX}, //
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::vector<std::string>& Rule::allMatchPropStrings() {
|
||||||
|
static std::vector<std::string> strings;
|
||||||
|
static bool once = true;
|
||||||
|
if (once) {
|
||||||
|
for (const auto& [k, v] : MATCH_PROP_STRINGS) {
|
||||||
|
strings.emplace_back(v);
|
||||||
|
}
|
||||||
|
once = false;
|
||||||
|
}
|
||||||
|
return strings;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<eRuleProperty> Rule::matchPropFromString(const std::string_view& s) {
|
||||||
|
const auto IT = std::ranges::find_if(MATCH_PROP_STRINGS, [&s](const auto& el) { return el.second == s; });
|
||||||
|
if (IT == MATCH_PROP_STRINGS.end())
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
return IT->first;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<eRuleProperty> Rule::matchPropFromString(const std::string& s) {
|
||||||
|
return matchPropFromString(std::string_view{s});
|
||||||
|
}
|
||||||
|
|
||||||
|
IRule::IRule(const std::string& name) : m_name(name) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRule::registerMatch(eRuleProperty p, const std::string& s) {
|
||||||
|
if (!RULE_ENGINES.contains(p)) {
|
||||||
|
Debug::log(ERR, "BUG THIS: IRule: RULE_ENGINES does not contain rule idx {}", sc<std::underlying_type_t<eRuleProperty>>(p));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (RULE_ENGINES.at(p)) {
|
||||||
|
case RULE_MATCH_ENGINE_REGEX: m_matchEngines[p] = makeUnique<CRegexMatchEngine>(s); break;
|
||||||
|
case RULE_MATCH_ENGINE_BOOL: m_matchEngines[p] = makeUnique<CBoolMatchEngine>(s); break;
|
||||||
|
case RULE_MATCH_ENGINE_INT: m_matchEngines[p] = makeUnique<CIntMatchEngine>(s); break;
|
||||||
|
case RULE_MATCH_ENGINE_WORKSPACE: m_matchEngines[p] = makeUnique<CWorkspaceMatchEngine>(s); break;
|
||||||
|
case RULE_MATCH_ENGINE_TAG: m_matchEngines[p] = makeUnique<CTagMatchEngine>(s); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_mask |= p;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::underlying_type_t<eRuleProperty> IRule::getPropertiesMask() {
|
||||||
|
return m_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRule::has(eRuleProperty p) {
|
||||||
|
return m_matchEngines.contains(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRule::matches(eRuleProperty p, const std::string& s) {
|
||||||
|
if (!has(p))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return m_matchEngines[p]->match(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRule::matches(eRuleProperty p, bool b) {
|
||||||
|
if (!has(p))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return m_matchEngines[p]->match(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& IRule::name() {
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRule::markAsExecRule(const std::string& token, bool persistent) {
|
||||||
|
m_execData.isExecRule = true;
|
||||||
|
m_execData.isExecPersistent = persistent;
|
||||||
|
m_execData.token = token;
|
||||||
|
m_execData.expiresAt = Time::steadyNow() + std::chrono::minutes(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRule::isExecRule() {
|
||||||
|
return m_execData.isExecRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRule::isExecPersistent() {
|
||||||
|
return m_execData.isExecPersistent;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRule::execExpired() {
|
||||||
|
return Time::steadyNow() > m_execData.expiresAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& IRule::execToken() {
|
||||||
|
return m_execData.token;
|
||||||
|
}
|
||||||
84
src/desktop/rule/Rule.hpp
Normal file
84
src/desktop/rule/Rule.hpp
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "matchEngine/MatchEngine.hpp"
|
||||||
|
|
||||||
|
#include "../../helpers/memory/Memory.hpp"
|
||||||
|
#include "../../helpers/time/Time.hpp"
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace Desktop::Rule {
|
||||||
|
enum eRuleProperty : uint32_t {
|
||||||
|
RULE_PROP_NONE = 0,
|
||||||
|
RULE_PROP_CLASS = (1 << 0),
|
||||||
|
RULE_PROP_TITLE = (1 << 1),
|
||||||
|
RULE_PROP_INITIAL_CLASS = (1 << 2),
|
||||||
|
RULE_PROP_INITIAL_TITLE = (1 << 3),
|
||||||
|
RULE_PROP_FLOATING = (1 << 4),
|
||||||
|
RULE_PROP_TAG = (1 << 5),
|
||||||
|
RULE_PROP_XWAYLAND = (1 << 6),
|
||||||
|
RULE_PROP_FULLSCREEN = (1 << 7),
|
||||||
|
RULE_PROP_PINNED = (1 << 8),
|
||||||
|
RULE_PROP_FOCUS = (1 << 9),
|
||||||
|
RULE_PROP_GROUP = (1 << 10),
|
||||||
|
RULE_PROP_MODAL = (1 << 11),
|
||||||
|
RULE_PROP_FULLSCREENSTATE_INTERNAL = (1 << 12),
|
||||||
|
RULE_PROP_FULLSCREENSTATE_CLIENT = (1 << 13),
|
||||||
|
RULE_PROP_ON_WORKSPACE = (1 << 14),
|
||||||
|
RULE_PROP_CONTENT = (1 << 15),
|
||||||
|
RULE_PROP_XDG_TAG = (1 << 16),
|
||||||
|
RULE_PROP_NAMESPACE = (1 << 17),
|
||||||
|
RULE_PROP_EXEC_TOKEN = (1 << 18),
|
||||||
|
|
||||||
|
RULE_PROP_ALL = std::numeric_limits<std::underlying_type_t<eRuleProperty>>::max(),
|
||||||
|
};
|
||||||
|
|
||||||
|
enum eRuleType : uint8_t {
|
||||||
|
RULE_TYPE_WINDOW = 0,
|
||||||
|
RULE_TYPE_LAYER,
|
||||||
|
};
|
||||||
|
|
||||||
|
std::optional<eRuleProperty> matchPropFromString(const std::string& s);
|
||||||
|
std::optional<eRuleProperty> matchPropFromString(const std::string_view& s);
|
||||||
|
const std::vector<std::string>& allMatchPropStrings();
|
||||||
|
|
||||||
|
class IRule {
|
||||||
|
public:
|
||||||
|
virtual ~IRule() = default;
|
||||||
|
|
||||||
|
virtual eRuleType type() = 0;
|
||||||
|
virtual std::underlying_type_t<eRuleProperty> getPropertiesMask();
|
||||||
|
|
||||||
|
void registerMatch(eRuleProperty, const std::string&);
|
||||||
|
void markAsExecRule(const std::string& token, bool persistent = false);
|
||||||
|
bool isExecRule();
|
||||||
|
bool isExecPersistent();
|
||||||
|
bool execExpired();
|
||||||
|
const std::string& execToken();
|
||||||
|
|
||||||
|
const std::string& name();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
IRule(const std::string& name = "");
|
||||||
|
|
||||||
|
bool matches(eRuleProperty, const std::string& s);
|
||||||
|
bool matches(eRuleProperty, bool b);
|
||||||
|
bool has(eRuleProperty);
|
||||||
|
|
||||||
|
//
|
||||||
|
std::unordered_map<eRuleProperty, UP<IMatchEngine>> m_matchEngines;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::underlying_type_t<eRuleProperty> m_mask = 0;
|
||||||
|
std::string m_name = "";
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool isExecRule = false;
|
||||||
|
bool isExecPersistent = false;
|
||||||
|
std::string token;
|
||||||
|
Time::steady_tp expiresAt;
|
||||||
|
} m_execData;
|
||||||
|
};
|
||||||
|
}
|
||||||
81
src/desktop/rule/effect/EffectContainer.hpp
Normal file
81
src/desktop/rule/effect/EffectContainer.hpp
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace Desktop::Rule {
|
||||||
|
template <typename T>
|
||||||
|
class IEffectContainer {
|
||||||
|
static_assert(std::is_enum_v<T>);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const std::string DEFAULT_MISSING_KEY = "";
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Make sure we're using at least a uint16_t for dynamic registrations to not overflow.
|
||||||
|
// 32k should be enough
|
||||||
|
using storageType = std::conditional_t<(sizeof(std::underlying_type_t<T>) >= 2), std::underlying_type_t<T>, uint16_t>;
|
||||||
|
|
||||||
|
IEffectContainer(std::vector<std::string>&& defaultKeys) : m_keys(std::move(defaultKeys)), m_originalSize(m_keys.size()) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
virtual ~IEffectContainer() = default;
|
||||||
|
|
||||||
|
virtual storageType registerEffect(std::string&& name) {
|
||||||
|
if (m_keys.size() >= std::numeric_limits<storageType>::max())
|
||||||
|
return 0;
|
||||||
|
if (auto it = std::ranges::find(m_keys, name); it != m_keys.end())
|
||||||
|
return it - m_keys.begin();
|
||||||
|
m_keys.emplace_back(std::move(name));
|
||||||
|
return m_keys.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void unregisterEffect(storageType id) {
|
||||||
|
if (id >= m_keys.size())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_keys[id] = DEFAULT_MISSING_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void unregisterEffect(const std::string& name) {
|
||||||
|
for (auto& key : m_keys) {
|
||||||
|
if (key == name) {
|
||||||
|
key = DEFAULT_MISSING_KEY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const std::string& get(storageType idx) {
|
||||||
|
if (idx >= m_keys.size())
|
||||||
|
return DEFAULT_MISSING_KEY;
|
||||||
|
|
||||||
|
return m_keys[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::optional<storageType> get(const std::string_view& s) {
|
||||||
|
for (storageType i = 0; i < m_keys.size(); ++i) {
|
||||||
|
if (m_keys[i] == s)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const std::vector<std::string>& allEffectStrings() {
|
||||||
|
return m_keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
// whether the effect has been added dynamically as opposed to in the ctor.
|
||||||
|
virtual bool isEffectDynamic(storageType i) {
|
||||||
|
return i >= m_originalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::vector<std::string> m_keys;
|
||||||
|
size_t m_originalSize = 0;
|
||||||
|
};
|
||||||
|
};
|
||||||
43
src/desktop/rule/layerRule/LayerRule.cpp
Normal file
43
src/desktop/rule/layerRule/LayerRule.cpp
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
#include "LayerRule.hpp"
|
||||||
|
#include "../../../debug/Log.hpp"
|
||||||
|
#include "../../LayerSurface.hpp"
|
||||||
|
|
||||||
|
using namespace Desktop;
|
||||||
|
using namespace Desktop::Rule;
|
||||||
|
|
||||||
|
CLayerRule::CLayerRule(const std::string& name) : IRule(name) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
eRuleType CLayerRule::type() {
|
||||||
|
return RULE_TYPE_LAYER;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLayerRule::addEffect(CLayerRule::storageType e, const std::string& result) {
|
||||||
|
m_effects.emplace_back(std::make_pair<>(e, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::pair<CLayerRule::storageType, std::string>>& CLayerRule::effects() {
|
||||||
|
return m_effects;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CLayerRule::matches(PHLLS ls) {
|
||||||
|
if (m_matchEngines.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (const auto& [prop, engine] : m_matchEngines) {
|
||||||
|
switch (prop) {
|
||||||
|
default: {
|
||||||
|
Debug::log(TRACE, "CLayerRule::matches: skipping prop entry {}", sc<std::underlying_type_t<eRuleProperty>>(prop));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case RULE_PROP_NAMESPACE:
|
||||||
|
if (!engine->match(ls->m_namespace))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
25
src/desktop/rule/layerRule/LayerRule.hpp
Normal file
25
src/desktop/rule/layerRule/LayerRule.hpp
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Rule.hpp"
|
||||||
|
#include "../../DesktopTypes.hpp"
|
||||||
|
#include "LayerRuleEffectContainer.hpp"
|
||||||
|
|
||||||
|
namespace Desktop::Rule {
|
||||||
|
class CLayerRule : public IRule {
|
||||||
|
public:
|
||||||
|
using storageType = CLayerRuleEffectContainer::storageType;
|
||||||
|
|
||||||
|
CLayerRule(const std::string& name = "");
|
||||||
|
virtual ~CLayerRule() = default;
|
||||||
|
|
||||||
|
virtual eRuleType type();
|
||||||
|
|
||||||
|
void addEffect(storageType e, const std::string& result);
|
||||||
|
const std::vector<std::pair<storageType, std::string>>& effects();
|
||||||
|
|
||||||
|
bool matches(PHLLS w);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::pair<storageType, std::string>> m_effects;
|
||||||
|
};
|
||||||
|
};
|
||||||
128
src/desktop/rule/layerRule/LayerRuleApplicator.cpp
Normal file
128
src/desktop/rule/layerRule/LayerRuleApplicator.cpp
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
#include "LayerRuleApplicator.hpp"
|
||||||
|
#include "LayerRule.hpp"
|
||||||
|
#include "../Engine.hpp"
|
||||||
|
#include "../../LayerSurface.hpp"
|
||||||
|
#include "../../types/OverridableVar.hpp"
|
||||||
|
#include "../../../helpers/MiscFunctions.hpp"
|
||||||
|
|
||||||
|
using namespace Desktop;
|
||||||
|
using namespace Desktop::Rule;
|
||||||
|
|
||||||
|
CLayerRuleApplicator::CLayerRuleApplicator(PHLLS ls) : m_ls(ls) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLayerRuleApplicator::resetProps(std::underlying_type_t<eRuleProperty> props, Types::eOverridePriority prio) {
|
||||||
|
// TODO: fucking kill me, is there a better way to do this?
|
||||||
|
|
||||||
|
#define UNSET(x) \
|
||||||
|
if (m_##x.second & props) { \
|
||||||
|
if (prio == Types::PRIORITY_WINDOW_RULE) \
|
||||||
|
m_##x.second &= ~props; \
|
||||||
|
m_##x.first.unset(prio); \
|
||||||
|
}
|
||||||
|
|
||||||
|
UNSET(noanim)
|
||||||
|
UNSET(blur)
|
||||||
|
UNSET(blurPopups)
|
||||||
|
UNSET(dimAround)
|
||||||
|
UNSET(xray)
|
||||||
|
UNSET(noScreenShare)
|
||||||
|
UNSET(order)
|
||||||
|
UNSET(aboveLock)
|
||||||
|
UNSET(ignoreAlpha)
|
||||||
|
UNSET(animationStyle)
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLayerRuleApplicator::applyDynamicRule(const SP<CLayerRule>& rule) {
|
||||||
|
for (const auto& [key, effect] : rule->effects()) {
|
||||||
|
switch (key) {
|
||||||
|
case LAYER_RULE_EFFECT_NONE: {
|
||||||
|
Debug::log(ERR, "CLayerRuleApplicator::applyDynamicRule: BUG THIS: LAYER_RULE_EFFECT_NONE??");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LAYER_RULE_EFFECT_NO_ANIM: {
|
||||||
|
m_noanim.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_noanim.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LAYER_RULE_EFFECT_BLUR: {
|
||||||
|
m_blur.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_blur.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LAYER_RULE_EFFECT_BLUR_POPUPS: {
|
||||||
|
m_blurPopups.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_blurPopups.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LAYER_RULE_EFFECT_DIM_AROUND: {
|
||||||
|
m_dimAround.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_dimAround.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LAYER_RULE_EFFECT_XRAY: {
|
||||||
|
m_xray.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_xray.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LAYER_RULE_EFFECT_NO_SCREEN_SHARE: {
|
||||||
|
m_noScreenShare.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_noScreenShare.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LAYER_RULE_EFFECT_ORDER: {
|
||||||
|
try {
|
||||||
|
m_noScreenShare.first.set(std::stoi(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_noScreenShare.second |= rule->getPropertiesMask();
|
||||||
|
} catch (...) { Debug::log(ERR, "CLayerRuleApplicator::applyDynamicRule: invalid order {}", effect); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LAYER_RULE_EFFECT_ABOVE_LOCK: {
|
||||||
|
try {
|
||||||
|
m_aboveLock.first.set(std::clamp(std::stoull(effect), 0ULL, 2ULL), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_aboveLock.second |= rule->getPropertiesMask();
|
||||||
|
} catch (...) { Debug::log(ERR, "CLayerRuleApplicator::applyDynamicRule: invalid order {}", effect); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LAYER_RULE_EFFECT_IGNORE_ALPHA: {
|
||||||
|
try {
|
||||||
|
m_ignoreAlpha.first.set(std::clamp(std::stof(effect), 0.F, 1.F), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_ignoreAlpha.second |= rule->getPropertiesMask();
|
||||||
|
} catch (...) { Debug::log(ERR, "CLayerRuleApplicator::applyDynamicRule: invalid order {}", effect); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LAYER_RULE_EFFECT_ANIMATION: {
|
||||||
|
m_animationStyle.first.set(effect, Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_animationStyle.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLayerRuleApplicator::propertiesChanged(std::underlying_type_t<eRuleProperty> props) {
|
||||||
|
if (!m_ls)
|
||||||
|
return;
|
||||||
|
|
||||||
|
resetProps(props);
|
||||||
|
|
||||||
|
// FIXME: this will not update properties correctly if we implement dynamic rules for
|
||||||
|
// layers, due to effects overlapping on 0 prop intersection.
|
||||||
|
// See WindowRule.cpp, and ::propertiesChanged there.
|
||||||
|
|
||||||
|
for (const auto& r : ruleEngine()->rules()) {
|
||||||
|
if (r->type() != RULE_TYPE_LAYER)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(r->getPropertiesMask() & props))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto wr = reinterpretPointerCast<CLayerRule>(r);
|
||||||
|
|
||||||
|
if (!wr->matches(m_ls.lock()))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
applyDynamicRule(wr);
|
||||||
|
}
|
||||||
|
}
|
||||||
60
src/desktop/rule/layerRule/LayerRuleApplicator.hpp
Normal file
60
src/desktop/rule/layerRule/LayerRuleApplicator.hpp
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../DesktopTypes.hpp"
|
||||||
|
#include "../Rule.hpp"
|
||||||
|
#include "../../types/OverridableVar.hpp"
|
||||||
|
#include "../../../helpers/math/Math.hpp"
|
||||||
|
#include "../../../config/ConfigDataValues.hpp"
|
||||||
|
|
||||||
|
namespace Desktop::Rule {
|
||||||
|
class CLayerRule;
|
||||||
|
|
||||||
|
class CLayerRuleApplicator {
|
||||||
|
public:
|
||||||
|
CLayerRuleApplicator(PHLLS ls);
|
||||||
|
~CLayerRuleApplicator() = default;
|
||||||
|
|
||||||
|
CLayerRuleApplicator(const CLayerRuleApplicator&) = delete;
|
||||||
|
CLayerRuleApplicator(CLayerRuleApplicator&) = delete;
|
||||||
|
CLayerRuleApplicator(CLayerRuleApplicator&&) = delete;
|
||||||
|
|
||||||
|
void propertiesChanged(std::underlying_type_t<eRuleProperty> props);
|
||||||
|
void resetProps(std::underlying_type_t<eRuleProperty> props, Types::eOverridePriority prio = Types::PRIORITY_WINDOW_RULE);
|
||||||
|
|
||||||
|
#define COMMA ,
|
||||||
|
#define DEFINE_PROP(type, name, def) \
|
||||||
|
private: \
|
||||||
|
std::pair<Types::COverridableVar<type>, std::underlying_type_t<eRuleProperty>> m_##name = {def, RULE_PROP_NONE}; \
|
||||||
|
\
|
||||||
|
public: \
|
||||||
|
Types::COverridableVar<type>& name() { \
|
||||||
|
return m_##name.first; \
|
||||||
|
} \
|
||||||
|
void name##Override(const Types::COverridableVar<type>& other) { \
|
||||||
|
m_##name.first = other; \
|
||||||
|
}
|
||||||
|
|
||||||
|
// dynamic props
|
||||||
|
DEFINE_PROP(bool, noanim, false)
|
||||||
|
DEFINE_PROP(bool, blur, false)
|
||||||
|
DEFINE_PROP(bool, blurPopups, false)
|
||||||
|
DEFINE_PROP(bool, dimAround, false)
|
||||||
|
DEFINE_PROP(bool, xray, false)
|
||||||
|
DEFINE_PROP(bool, noScreenShare, false)
|
||||||
|
|
||||||
|
DEFINE_PROP(Hyprlang::INT, order, 0)
|
||||||
|
DEFINE_PROP(Hyprlang::INT, aboveLock, 0)
|
||||||
|
|
||||||
|
DEFINE_PROP(Hyprlang::FLOAT, ignoreAlpha, 0.F)
|
||||||
|
|
||||||
|
DEFINE_PROP(std::string, animationStyle, std::string(""))
|
||||||
|
|
||||||
|
#undef COMMA
|
||||||
|
#undef DEFINE_PROP
|
||||||
|
|
||||||
|
private:
|
||||||
|
PHLLSREF m_ls;
|
||||||
|
|
||||||
|
void applyDynamicRule(const SP<CLayerRule>& rule);
|
||||||
|
};
|
||||||
|
};
|
||||||
33
src/desktop/rule/layerRule/LayerRuleEffectContainer.cpp
Normal file
33
src/desktop/rule/layerRule/LayerRuleEffectContainer.cpp
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#include "LayerRuleEffectContainer.hpp"
|
||||||
|
|
||||||
|
using namespace Desktop;
|
||||||
|
using namespace Desktop::Rule;
|
||||||
|
|
||||||
|
//
|
||||||
|
SP<CLayerRuleEffectContainer> Rule::layerEffects() {
|
||||||
|
static SP<CLayerRuleEffectContainer> container = makeShared<CLayerRuleEffectContainer>();
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const std::vector<std::string> EFFECT_STRINGS = {
|
||||||
|
"__internal_none", //
|
||||||
|
"no_anim", //
|
||||||
|
"blur", //
|
||||||
|
"blur_popups", //
|
||||||
|
"ignore_alpha", //
|
||||||
|
"dim_around", //
|
||||||
|
"xray", //
|
||||||
|
"animation", //
|
||||||
|
"order", //
|
||||||
|
"above_lock", //
|
||||||
|
"no_screen_share", //
|
||||||
|
"__internal_last_static", //
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is here so that if we change the rules, we get reminded to update
|
||||||
|
// the strings.
|
||||||
|
static_assert(LAYER_RULE_EFFECT_LAST_STATIC == 11);
|
||||||
|
|
||||||
|
CLayerRuleEffectContainer::CLayerRuleEffectContainer() : IEffectContainer<eLayerRuleEffect>(std::vector<std::string>{EFFECT_STRINGS}) {
|
||||||
|
;
|
||||||
|
}
|
||||||
33
src/desktop/rule/layerRule/LayerRuleEffectContainer.hpp
Normal file
33
src/desktop/rule/layerRule/LayerRuleEffectContainer.hpp
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../effect/EffectContainer.hpp"
|
||||||
|
#include "../../../helpers/memory/Memory.hpp"
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Desktop::Rule {
|
||||||
|
enum eLayerRuleEffect : uint8_t {
|
||||||
|
LAYER_RULE_EFFECT_NONE = 0,
|
||||||
|
|
||||||
|
LAYER_RULE_EFFECT_NO_ANIM,
|
||||||
|
LAYER_RULE_EFFECT_BLUR,
|
||||||
|
LAYER_RULE_EFFECT_BLUR_POPUPS,
|
||||||
|
LAYER_RULE_EFFECT_IGNORE_ALPHA,
|
||||||
|
LAYER_RULE_EFFECT_DIM_AROUND,
|
||||||
|
LAYER_RULE_EFFECT_XRAY,
|
||||||
|
LAYER_RULE_EFFECT_ANIMATION,
|
||||||
|
LAYER_RULE_EFFECT_ORDER,
|
||||||
|
LAYER_RULE_EFFECT_ABOVE_LOCK,
|
||||||
|
LAYER_RULE_EFFECT_NO_SCREEN_SHARE,
|
||||||
|
|
||||||
|
LAYER_RULE_EFFECT_LAST_STATIC,
|
||||||
|
};
|
||||||
|
|
||||||
|
class CLayerRuleEffectContainer : public IEffectContainer<eLayerRuleEffect> {
|
||||||
|
public:
|
||||||
|
CLayerRuleEffectContainer();
|
||||||
|
virtual ~CLayerRuleEffectContainer() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
SP<CLayerRuleEffectContainer> layerEffects();
|
||||||
|
};
|
||||||
12
src/desktop/rule/matchEngine/BoolMatchEngine.cpp
Normal file
12
src/desktop/rule/matchEngine/BoolMatchEngine.cpp
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "BoolMatchEngine.hpp"
|
||||||
|
#include "../../../helpers/MiscFunctions.hpp"
|
||||||
|
|
||||||
|
using namespace Desktop::Rule;
|
||||||
|
|
||||||
|
CBoolMatchEngine::CBoolMatchEngine(const std::string& s) : m_value(truthy(s)) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBoolMatchEngine::match(bool other) {
|
||||||
|
return other == m_value;
|
||||||
|
}
|
||||||
16
src/desktop/rule/matchEngine/BoolMatchEngine.hpp
Normal file
16
src/desktop/rule/matchEngine/BoolMatchEngine.hpp
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "MatchEngine.hpp"
|
||||||
|
|
||||||
|
namespace Desktop::Rule {
|
||||||
|
class CBoolMatchEngine : public IMatchEngine {
|
||||||
|
public:
|
||||||
|
CBoolMatchEngine(const std::string&);
|
||||||
|
virtual ~CBoolMatchEngine() = default;
|
||||||
|
|
||||||
|
virtual bool match(bool other);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_value = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
14
src/desktop/rule/matchEngine/IntMatchEngine.cpp
Normal file
14
src/desktop/rule/matchEngine/IntMatchEngine.cpp
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#include "IntMatchEngine.hpp"
|
||||||
|
#include "../../../debug/Log.hpp"
|
||||||
|
|
||||||
|
using namespace Desktop::Rule;
|
||||||
|
|
||||||
|
CIntMatchEngine::CIntMatchEngine(const std::string& s) {
|
||||||
|
try {
|
||||||
|
m_value = std::stoi(s);
|
||||||
|
} catch (...) { Debug::log(ERR, "CIntMatchEngine: invalid input {}", s); }
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIntMatchEngine::match(int other) {
|
||||||
|
return m_value == other;
|
||||||
|
}
|
||||||
16
src/desktop/rule/matchEngine/IntMatchEngine.hpp
Normal file
16
src/desktop/rule/matchEngine/IntMatchEngine.hpp
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "MatchEngine.hpp"
|
||||||
|
|
||||||
|
namespace Desktop::Rule {
|
||||||
|
class CIntMatchEngine : public IMatchEngine {
|
||||||
|
public:
|
||||||
|
CIntMatchEngine(const std::string&);
|
||||||
|
virtual ~CIntMatchEngine() = default;
|
||||||
|
|
||||||
|
virtual bool match(int other);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_value = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
23
src/desktop/rule/matchEngine/MatchEngine.cpp
Normal file
23
src/desktop/rule/matchEngine/MatchEngine.cpp
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include "MatchEngine.hpp"
|
||||||
|
|
||||||
|
using namespace Desktop::Rule;
|
||||||
|
|
||||||
|
bool IMatchEngine::match(const std::string&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IMatchEngine::match(bool) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IMatchEngine::match(int) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IMatchEngine::match(PHLWORKSPACE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IMatchEngine::match(const CTagKeeper& keeper) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
28
src/desktop/rule/matchEngine/MatchEngine.hpp
Normal file
28
src/desktop/rule/matchEngine/MatchEngine.hpp
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../../DesktopTypes.hpp"
|
||||||
|
|
||||||
|
class CTagKeeper;
|
||||||
|
|
||||||
|
namespace Desktop::Rule {
|
||||||
|
enum eRuleMatchEngine : uint8_t {
|
||||||
|
RULE_MATCH_ENGINE_REGEX = 0,
|
||||||
|
RULE_MATCH_ENGINE_BOOL,
|
||||||
|
RULE_MATCH_ENGINE_INT,
|
||||||
|
RULE_MATCH_ENGINE_WORKSPACE,
|
||||||
|
RULE_MATCH_ENGINE_TAG,
|
||||||
|
};
|
||||||
|
|
||||||
|
class IMatchEngine {
|
||||||
|
public:
|
||||||
|
virtual ~IMatchEngine() = default;
|
||||||
|
virtual bool match(const std::string&);
|
||||||
|
virtual bool match(bool);
|
||||||
|
virtual bool match(int);
|
||||||
|
virtual bool match(PHLWORKSPACE);
|
||||||
|
virtual bool match(const CTagKeeper& keeper);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
IMatchEngine() = default;
|
||||||
|
};
|
||||||
|
};
|
||||||
17
src/desktop/rule/matchEngine/RegexMatchEngine.cpp
Normal file
17
src/desktop/rule/matchEngine/RegexMatchEngine.cpp
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#include "RegexMatchEngine.hpp"
|
||||||
|
#include <re2/re2.h>
|
||||||
|
|
||||||
|
using namespace Desktop::Rule;
|
||||||
|
|
||||||
|
CRegexMatchEngine::CRegexMatchEngine(const std::string& regex) {
|
||||||
|
if (regex.starts_with("negative:")) {
|
||||||
|
m_negative = true;
|
||||||
|
m_regex = makeUnique<re2::RE2>(regex.substr(9));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_regex = makeUnique<re2::RE2>(regex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRegexMatchEngine::match(const std::string& other) {
|
||||||
|
return re2::RE2::FullMatch(other, *m_regex) != m_negative;
|
||||||
|
}
|
||||||
23
src/desktop/rule/matchEngine/RegexMatchEngine.hpp
Normal file
23
src/desktop/rule/matchEngine/RegexMatchEngine.hpp
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "MatchEngine.hpp"
|
||||||
|
#include "../../../helpers/memory/Memory.hpp"
|
||||||
|
|
||||||
|
//NOLINTNEXTLINE
|
||||||
|
namespace re2 {
|
||||||
|
class RE2;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Desktop::Rule {
|
||||||
|
class CRegexMatchEngine : public IMatchEngine {
|
||||||
|
public:
|
||||||
|
CRegexMatchEngine(const std::string& regex);
|
||||||
|
virtual ~CRegexMatchEngine() = default;
|
||||||
|
|
||||||
|
virtual bool match(const std::string& other);
|
||||||
|
|
||||||
|
private:
|
||||||
|
UP<re2::RE2> m_regex;
|
||||||
|
bool m_negative = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
12
src/desktop/rule/matchEngine/TagMatchEngine.cpp
Normal file
12
src/desktop/rule/matchEngine/TagMatchEngine.cpp
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "TagMatchEngine.hpp"
|
||||||
|
#include "../../../helpers/TagKeeper.hpp"
|
||||||
|
|
||||||
|
using namespace Desktop::Rule;
|
||||||
|
|
||||||
|
CTagMatchEngine::CTagMatchEngine(const std::string& tag) : m_tag(tag) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CTagMatchEngine::match(const CTagKeeper& keeper) {
|
||||||
|
return keeper.isTagged(m_tag);
|
||||||
|
}
|
||||||
16
src/desktop/rule/matchEngine/TagMatchEngine.hpp
Normal file
16
src/desktop/rule/matchEngine/TagMatchEngine.hpp
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "MatchEngine.hpp"
|
||||||
|
|
||||||
|
namespace Desktop::Rule {
|
||||||
|
class CTagMatchEngine : public IMatchEngine {
|
||||||
|
public:
|
||||||
|
CTagMatchEngine(const std::string& tag);
|
||||||
|
virtual ~CTagMatchEngine() = default;
|
||||||
|
|
||||||
|
virtual bool match(const CTagKeeper& keeper);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_tag;
|
||||||
|
};
|
||||||
|
}
|
||||||
12
src/desktop/rule/matchEngine/WorkspaceMatchEngine.cpp
Normal file
12
src/desktop/rule/matchEngine/WorkspaceMatchEngine.cpp
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "WorkspaceMatchEngine.hpp"
|
||||||
|
#include "../../Workspace.hpp"
|
||||||
|
|
||||||
|
using namespace Desktop::Rule;
|
||||||
|
|
||||||
|
CWorkspaceMatchEngine::CWorkspaceMatchEngine(const std::string& s) : m_value(s) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWorkspaceMatchEngine::match(PHLWORKSPACE ws) {
|
||||||
|
return ws->matchesStaticSelector(m_value);
|
||||||
|
}
|
||||||
16
src/desktop/rule/matchEngine/WorkspaceMatchEngine.hpp
Normal file
16
src/desktop/rule/matchEngine/WorkspaceMatchEngine.hpp
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "MatchEngine.hpp"
|
||||||
|
|
||||||
|
namespace Desktop::Rule {
|
||||||
|
class CWorkspaceMatchEngine : public IMatchEngine {
|
||||||
|
public:
|
||||||
|
CWorkspaceMatchEngine(const std::string&);
|
||||||
|
virtual ~CWorkspaceMatchEngine() = default;
|
||||||
|
|
||||||
|
virtual bool match(PHLWORKSPACE ws);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_value = "";
|
||||||
|
};
|
||||||
|
}
|
||||||
17
src/desktop/rule/utils/SetUtils.hpp
Normal file
17
src/desktop/rule/utils/SetUtils.hpp
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
namespace Desktop::Rule {
|
||||||
|
template <class T>
|
||||||
|
bool setsIntersect(const std::unordered_set<T>& A, const std::unordered_set<T>& B) {
|
||||||
|
if (A.size() > B.size())
|
||||||
|
return setsIntersect(B, A);
|
||||||
|
|
||||||
|
for (const auto& e : A) {
|
||||||
|
if (B.contains(e))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
186
src/desktop/rule/windowRule/WindowRule.cpp
Normal file
186
src/desktop/rule/windowRule/WindowRule.cpp
Normal file
|
|
@ -0,0 +1,186 @@
|
||||||
|
#include "WindowRule.hpp"
|
||||||
|
#include "../../Window.hpp"
|
||||||
|
#include "../../../helpers/Monitor.hpp"
|
||||||
|
#include "../../../Compositor.hpp"
|
||||||
|
#include "../../../managers/TokenManager.hpp"
|
||||||
|
|
||||||
|
using namespace Desktop;
|
||||||
|
using namespace Desktop::Rule;
|
||||||
|
|
||||||
|
std::optional<Vector2D> Rule::parseRelativeVector(PHLWINDOW w, const std::string& s) {
|
||||||
|
try {
|
||||||
|
const auto VALUE = s.substr(s.find(' ') + 1);
|
||||||
|
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
|
||||||
|
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
|
||||||
|
|
||||||
|
const auto MAXSIZE = w->requestedMaxSize();
|
||||||
|
|
||||||
|
const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, g_pCompositor->m_lastMonitor->m_size.x) :
|
||||||
|
stringToPercentage(SIZEXSTR, g_pCompositor->m_lastMonitor->m_size.x);
|
||||||
|
|
||||||
|
const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, g_pCompositor->m_lastMonitor->m_size.y) :
|
||||||
|
stringToPercentage(SIZEYSTR, g_pCompositor->m_lastMonitor->m_size.y);
|
||||||
|
|
||||||
|
return Vector2D{SIZEX, SIZEY};
|
||||||
|
|
||||||
|
} catch (...) { Debug::log(LOG, "Rule size failed, rule: {}", s); }
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
CWindowRule::CWindowRule(const std::string& name) : IRule(name) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
eRuleType CWindowRule::type() {
|
||||||
|
return RULE_TYPE_WINDOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindowRule::addEffect(CWindowRule::storageType e, const std::string& result) {
|
||||||
|
m_effects.emplace_back(std::make_pair<>(e, result));
|
||||||
|
m_effectSet.emplace(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::pair<CWindowRule::storageType, std::string>>& CWindowRule::effects() {
|
||||||
|
return m_effects;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CWindowRule::matches(PHLWINDOW w, bool allowEnvLookup) {
|
||||||
|
if (m_matchEngines.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (const auto& [prop, engine] : m_matchEngines) {
|
||||||
|
switch (prop) {
|
||||||
|
default: {
|
||||||
|
Debug::log(TRACE, "CWindowRule::matches: skipping prop entry {}", sc<std::underlying_type_t<eRuleProperty>>(prop));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case RULE_PROP_TITLE:
|
||||||
|
if (!engine->match(w->m_title))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case RULE_PROP_INITIAL_TITLE:
|
||||||
|
if (!engine->match(w->m_initialTitle))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case RULE_PROP_CLASS:
|
||||||
|
if (!engine->match(w->m_class))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case RULE_PROP_INITIAL_CLASS:
|
||||||
|
if (!engine->match(w->m_initialClass))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case RULE_PROP_FLOATING:
|
||||||
|
if (!engine->match(w->m_isFloating))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case RULE_PROP_TAG:
|
||||||
|
if (!engine->match(w->m_ruleApplicator->m_tagKeeper))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case RULE_PROP_XWAYLAND:
|
||||||
|
if (!engine->match(w->m_isX11))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case RULE_PROP_FULLSCREEN:
|
||||||
|
if (!engine->match(w->m_fullscreenState.internal != 0))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case RULE_PROP_PINNED:
|
||||||
|
if (!engine->match(w->m_pinned))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case RULE_PROP_FOCUS:
|
||||||
|
if (!engine->match(g_pCompositor->m_lastWindow == w))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case RULE_PROP_GROUP:
|
||||||
|
if (!engine->match(w->m_groupData.pNextWindow))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case RULE_PROP_MODAL:
|
||||||
|
if (!engine->match(w->isModal()))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case RULE_PROP_FULLSCREENSTATE_INTERNAL:
|
||||||
|
if (!engine->match(w->m_fullscreenState.internal))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case RULE_PROP_FULLSCREENSTATE_CLIENT:
|
||||||
|
if (!engine->match(w->m_fullscreenState.client))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case RULE_PROP_ON_WORKSPACE:
|
||||||
|
if (!engine->match(w->m_workspace))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case RULE_PROP_CONTENT:
|
||||||
|
if (!engine->match(NContentType::toString(w->getContentType())))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case RULE_PROP_XDG_TAG:
|
||||||
|
if (!w->xdgTag().has_value() || !engine->match(*w->xdgTag()))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case RULE_PROP_EXEC_TOKEN:
|
||||||
|
// this is only allowed on static rules, we don't need it on dynamic plus it's expensive
|
||||||
|
if (!allowEnvLookup)
|
||||||
|
break;
|
||||||
|
|
||||||
|
const auto ENV = w->getEnv();
|
||||||
|
if (ENV.contains(EXEC_RULE_ENV_NAME)) {
|
||||||
|
const auto TKN = ENV.at(EXEC_RULE_ENV_NAME);
|
||||||
|
if (!engine->match(TKN))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SP<CWindowRule> CWindowRule::buildFromExecString(std::string&& s) {
|
||||||
|
CVarList2 varlist(std::move(s), 0, ';');
|
||||||
|
SP<CWindowRule> wr = makeShared<CWindowRule>("__exec_rule");
|
||||||
|
|
||||||
|
for (const auto& el : varlist) {
|
||||||
|
// split element by space, can't do better
|
||||||
|
size_t spacePos = el.find(' ');
|
||||||
|
if (spacePos != std::string::npos) {
|
||||||
|
// great, split and try to parse
|
||||||
|
auto LHS = el.substr(0, spacePos);
|
||||||
|
const auto EFFECT = windowEffects()->get(LHS);
|
||||||
|
|
||||||
|
if (!EFFECT.has_value() || *EFFECT == WINDOW_RULE_EFFECT_NONE)
|
||||||
|
continue; // invalid...
|
||||||
|
|
||||||
|
wr->addEffect(*EFFECT, std::string{el.substr(spacePos + 1)});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// assume 1 maybe...
|
||||||
|
|
||||||
|
const auto EFFECT = windowEffects()->get(el);
|
||||||
|
|
||||||
|
if (!EFFECT.has_value() || *EFFECT == WINDOW_RULE_EFFECT_NONE)
|
||||||
|
continue; // invalid...
|
||||||
|
|
||||||
|
wr->addEffect(*EFFECT, std::string{"1"});
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto TOKEN = g_pTokenManager->registerNewToken(nullptr, std::chrono::seconds(1));
|
||||||
|
|
||||||
|
wr->markAsExecRule(TOKEN, false /* TODO: could be nice. */);
|
||||||
|
wr->registerMatch(RULE_PROP_EXEC_TOKEN, TOKEN);
|
||||||
|
|
||||||
|
return wr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::unordered_set<CWindowRule::storageType>& CWindowRule::effectsSet() {
|
||||||
|
return m_effectSet;
|
||||||
|
}
|
||||||
37
src/desktop/rule/windowRule/WindowRule.hpp
Normal file
37
src/desktop/rule/windowRule/WindowRule.hpp
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Rule.hpp"
|
||||||
|
#include "../../DesktopTypes.hpp"
|
||||||
|
#include "WindowRuleEffectContainer.hpp"
|
||||||
|
#include "../../../helpers/math/Math.hpp"
|
||||||
|
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
namespace Desktop::Rule {
|
||||||
|
constexpr const char* EXEC_RULE_ENV_NAME = "HL_EXEC_RULE_TOKEN";
|
||||||
|
|
||||||
|
std::optional<Vector2D> parseRelativeVector(PHLWINDOW w, const std::string& s);
|
||||||
|
|
||||||
|
class CWindowRule : public IRule {
|
||||||
|
private:
|
||||||
|
using storageType = CWindowRuleEffectContainer::storageType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CWindowRule(const std::string& name = "");
|
||||||
|
virtual ~CWindowRule() = default;
|
||||||
|
|
||||||
|
static SP<CWindowRule> buildFromExecString(std::string&&);
|
||||||
|
|
||||||
|
virtual eRuleType type();
|
||||||
|
|
||||||
|
void addEffect(storageType e, const std::string& result);
|
||||||
|
const std::vector<std::pair<storageType, std::string>>& effects();
|
||||||
|
const std::unordered_set<storageType>& effectsSet();
|
||||||
|
|
||||||
|
bool matches(PHLWINDOW w, bool allowEnvLookup = false);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::pair<storageType, std::string>> m_effects;
|
||||||
|
std::unordered_set<storageType> m_effectSet;
|
||||||
|
};
|
||||||
|
};
|
||||||
646
src/desktop/rule/windowRule/WindowRuleApplicator.cpp
Normal file
646
src/desktop/rule/windowRule/WindowRuleApplicator.cpp
Normal file
|
|
@ -0,0 +1,646 @@
|
||||||
|
#include "WindowRuleApplicator.hpp"
|
||||||
|
#include "WindowRule.hpp"
|
||||||
|
#include "../Engine.hpp"
|
||||||
|
#include "../utils/SetUtils.hpp"
|
||||||
|
#include "../../Window.hpp"
|
||||||
|
#include "../../types/OverridableVar.hpp"
|
||||||
|
#include "../../../managers/LayoutManager.hpp"
|
||||||
|
#include "../../../managers/HookSystemManager.hpp"
|
||||||
|
|
||||||
|
#include <hyprutils/string/String.hpp>
|
||||||
|
|
||||||
|
using namespace Hyprutils::String;
|
||||||
|
|
||||||
|
using namespace Desktop;
|
||||||
|
using namespace Desktop::Rule;
|
||||||
|
|
||||||
|
CWindowRuleApplicator::CWindowRuleApplicator(PHLWINDOW w) : m_window(w) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindowRuleApplicator::resetProps(std::underlying_type_t<eRuleProperty> props, Types::eOverridePriority prio) {
|
||||||
|
// TODO: fucking kill me, is there a better way to do this?
|
||||||
|
|
||||||
|
#define UNSET(x) \
|
||||||
|
if (m_##x.second & props) { \
|
||||||
|
if (prio == Types::PRIORITY_WINDOW_RULE) \
|
||||||
|
m_##x.second &= ~props; \
|
||||||
|
m_##x.first.unset(prio); \
|
||||||
|
}
|
||||||
|
|
||||||
|
UNSET(alpha)
|
||||||
|
UNSET(alphaInactive)
|
||||||
|
UNSET(alphaFullscreen)
|
||||||
|
UNSET(allowsInput)
|
||||||
|
UNSET(decorate)
|
||||||
|
UNSET(focusOnActivate)
|
||||||
|
UNSET(keepAspectRatio)
|
||||||
|
UNSET(nearestNeighbor)
|
||||||
|
UNSET(noAnim)
|
||||||
|
UNSET(noBlur)
|
||||||
|
UNSET(noDim)
|
||||||
|
UNSET(noFocus)
|
||||||
|
UNSET(noMaxSize)
|
||||||
|
UNSET(noShadow)
|
||||||
|
UNSET(noShortcutsInhibit)
|
||||||
|
UNSET(opaque)
|
||||||
|
UNSET(dimAround)
|
||||||
|
UNSET(RGBX)
|
||||||
|
UNSET(syncFullscreen)
|
||||||
|
UNSET(tearing)
|
||||||
|
UNSET(xray)
|
||||||
|
UNSET(renderUnfocused)
|
||||||
|
UNSET(noFollowMouse)
|
||||||
|
UNSET(noScreenShare)
|
||||||
|
UNSET(noVRR)
|
||||||
|
UNSET(persistentSize)
|
||||||
|
UNSET(stayFocused)
|
||||||
|
UNSET(idleInhibitMode)
|
||||||
|
UNSET(borderSize)
|
||||||
|
UNSET(rounding)
|
||||||
|
UNSET(roundingPower)
|
||||||
|
UNSET(scrollMouse)
|
||||||
|
UNSET(scrollTouchpad)
|
||||||
|
UNSET(animationStyle)
|
||||||
|
UNSET(maxSize)
|
||||||
|
UNSET(minSize)
|
||||||
|
UNSET(activeBorderColor)
|
||||||
|
UNSET(inactiveBorderColor)
|
||||||
|
|
||||||
|
#undef UNSET
|
||||||
|
|
||||||
|
if (prio == Types::PRIORITY_WINDOW_RULE) {
|
||||||
|
std::erase_if(m_dynamicTags, [props, this](const auto& el) {
|
||||||
|
const bool REMOVE = el.second & props;
|
||||||
|
|
||||||
|
if (REMOVE)
|
||||||
|
m_tagKeeper.removeDynamicTag(el.first);
|
||||||
|
|
||||||
|
return REMOVE;
|
||||||
|
});
|
||||||
|
|
||||||
|
std::erase_if(m_otherProps.props, [props](const auto& el) { return !el.second || el.second->propMask & props; });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CWindowRuleApplicator::SRuleResult CWindowRuleApplicator::applyDynamicRule(const SP<CWindowRule>& rule) {
|
||||||
|
SRuleResult result;
|
||||||
|
|
||||||
|
for (const auto& [key, effect] : rule->effects()) {
|
||||||
|
switch (key) {
|
||||||
|
default: {
|
||||||
|
if (key <= WINDOW_RULE_EFFECT_LAST_STATIC) {
|
||||||
|
Debug::log(TRACE, "CWindowRuleApplicator::applyDynamicRule: Skipping effect {}, not dynamic", sc<std::underlying_type_t<eWindowRuleEffect>>(key));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// custom type, add to our vec
|
||||||
|
if (!m_otherProps.props.contains(key)) {
|
||||||
|
m_otherProps.props.emplace(key,
|
||||||
|
makeUnique<SCustomPropContainer>(SCustomPropContainer{
|
||||||
|
.idx = key,
|
||||||
|
.propMask = rule->getPropertiesMask(),
|
||||||
|
.effect = effect,
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
auto& e = m_otherProps.props[key];
|
||||||
|
e->propMask |= rule->getPropertiesMask();
|
||||||
|
e->effect = effect;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WINDOW_RULE_EFFECT_NONE: {
|
||||||
|
Debug::log(ERR, "CWindowRuleApplicator::applyDynamicRule: BUG THIS: WINDOW_RULE_EFFECT_NONE??");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_ROUNDING: {
|
||||||
|
try {
|
||||||
|
m_rounding.first.set(std::stoull(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_rounding.second |= rule->getPropertiesMask();
|
||||||
|
} catch (...) { Debug::log(ERR, "CWindowRuleApplicator::applyDynamicRule: invalid rounding {}", effect); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_ROUNDING_POWER: {
|
||||||
|
try {
|
||||||
|
m_roundingPower.first.set(std::clamp(std::stof(effect), 1.F, 10.F), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_roundingPower.second |= rule->getPropertiesMask();
|
||||||
|
} catch (...) { Debug::log(ERR, "CWindowRuleApplicator::applyDynamicRule: invalid rounding_power {}", effect); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_PERSISTENT_SIZE: {
|
||||||
|
try {
|
||||||
|
m_persistentSize.first.set(std::stoi(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_persistentSize.second |= rule->getPropertiesMask();
|
||||||
|
} catch (...) { Debug::log(ERR, "CWindowRuleApplicator::applyDynamicRule: invalid rounding_power {}", effect); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_ANIMATION: {
|
||||||
|
m_animationStyle.first.set(effect, Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_animationStyle.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_BORDER_COLOR: {
|
||||||
|
try {
|
||||||
|
// Each vector will only get used if it has at least one color
|
||||||
|
CGradientValueData activeBorderGradient = {};
|
||||||
|
CGradientValueData inactiveBorderGradient = {};
|
||||||
|
bool active = true;
|
||||||
|
CVarList colorsAndAngles = CVarList(trim(effect.substr(effect.find_first_of(' ') + 1)), 0, 's', true);
|
||||||
|
|
||||||
|
// Basic form has only two colors, everything else can be parsed as a gradient
|
||||||
|
if (colorsAndAngles.size() == 2 && !colorsAndAngles[1].contains("deg")) {
|
||||||
|
m_activeBorderColor.first =
|
||||||
|
Types::COverridableVar(CGradientValueData(CHyprColor(configStringToInt(colorsAndAngles[0]).value_or(0))), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_inactiveBorderColor.first =
|
||||||
|
Types::COverridableVar(CGradientValueData(CHyprColor(configStringToInt(colorsAndAngles[1]).value_or(0))), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto const& token : colorsAndAngles) {
|
||||||
|
// The first angle, or an explicit "0deg", splits the two gradients
|
||||||
|
if (active && token.contains("deg")) {
|
||||||
|
activeBorderGradient.m_angle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
||||||
|
active = false;
|
||||||
|
} else if (token.contains("deg"))
|
||||||
|
inactiveBorderGradient.m_angle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
||||||
|
else if (active)
|
||||||
|
activeBorderGradient.m_colors.emplace_back(configStringToInt(token).value_or(0));
|
||||||
|
else
|
||||||
|
inactiveBorderGradient.m_colors.emplace_back(configStringToInt(token).value_or(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
activeBorderGradient.updateColorsOk();
|
||||||
|
|
||||||
|
// Includes sanity checks for the number of colors in each gradient
|
||||||
|
if (activeBorderGradient.m_colors.size() > 10 || inactiveBorderGradient.m_colors.size() > 10)
|
||||||
|
Debug::log(WARN, "Bordercolor rule \"{}\" has more than 10 colors in one gradient, ignoring", effect);
|
||||||
|
else if (activeBorderGradient.m_colors.empty())
|
||||||
|
Debug::log(WARN, "Bordercolor rule \"{}\" has no colors, ignoring", effect);
|
||||||
|
else if (inactiveBorderGradient.m_colors.empty())
|
||||||
|
m_activeBorderColor.first = Types::COverridableVar(activeBorderGradient, Types::PRIORITY_WINDOW_RULE);
|
||||||
|
else {
|
||||||
|
m_activeBorderColor.first = Types::COverridableVar(activeBorderGradient, Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_inactiveBorderColor.first = Types::COverridableVar(inactiveBorderGradient, Types::PRIORITY_WINDOW_RULE);
|
||||||
|
}
|
||||||
|
} catch (std::exception& e) { Debug::log(ERR, "BorderColor rule \"{}\" failed with: {}", effect, e.what()); }
|
||||||
|
m_activeBorderColor.second = rule->getPropertiesMask();
|
||||||
|
m_inactiveBorderColor.second = rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_IDLE_INHIBIT: {
|
||||||
|
if (effect == "none")
|
||||||
|
m_idleInhibitMode.first.set(IDLEINHIBIT_NONE, Types::PRIORITY_WINDOW_RULE);
|
||||||
|
else if (effect == "always")
|
||||||
|
m_idleInhibitMode.first.set(IDLEINHIBIT_ALWAYS, Types::PRIORITY_WINDOW_RULE);
|
||||||
|
else if (effect == "focus")
|
||||||
|
m_idleInhibitMode.first.set(IDLEINHIBIT_FOCUS, Types::PRIORITY_WINDOW_RULE);
|
||||||
|
else if (effect == "fullscreen")
|
||||||
|
m_idleInhibitMode.first.set(IDLEINHIBIT_FULLSCREEN, Types::PRIORITY_WINDOW_RULE);
|
||||||
|
else
|
||||||
|
Debug::log(ERR, "Rule idleinhibit: unknown mode {}", effect);
|
||||||
|
m_idleInhibitMode.second = rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_OPACITY: {
|
||||||
|
try {
|
||||||
|
CVarList2 vars(std::string{effect}, 0, ' ');
|
||||||
|
|
||||||
|
int opacityIDX = 0;
|
||||||
|
|
||||||
|
for (const auto& r : vars) {
|
||||||
|
if (r == "opacity")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (r == "override") {
|
||||||
|
if (opacityIDX == 1)
|
||||||
|
m_alpha.first = Types::COverridableVar(Types::SAlphaValue{.alpha = m_alpha.first.value().alpha, .overridden = true}, Types::PRIORITY_WINDOW_RULE);
|
||||||
|
else if (opacityIDX == 2)
|
||||||
|
m_alphaInactive.first =
|
||||||
|
Types::COverridableVar(Types::SAlphaValue{.alpha = m_alphaInactive.first.value().alpha, .overridden = true}, Types::PRIORITY_WINDOW_RULE);
|
||||||
|
else if (opacityIDX == 3)
|
||||||
|
m_alphaFullscreen.first =
|
||||||
|
Types::COverridableVar(Types::SAlphaValue{.alpha = m_alphaFullscreen.first.value().alpha, .overridden = true}, Types::PRIORITY_WINDOW_RULE);
|
||||||
|
} else {
|
||||||
|
if (opacityIDX == 0)
|
||||||
|
m_alpha.first = Types::COverridableVar(Types::SAlphaValue{.alpha = std::stof(std::string{r}), .overridden = false}, Types::PRIORITY_WINDOW_RULE);
|
||||||
|
else if (opacityIDX == 1)
|
||||||
|
m_alphaInactive.first =
|
||||||
|
Types::COverridableVar(Types::SAlphaValue{.alpha = std::stof(std::string{r}), .overridden = false}, Types::PRIORITY_WINDOW_RULE);
|
||||||
|
else if (opacityIDX == 2)
|
||||||
|
m_alphaFullscreen.first =
|
||||||
|
Types::COverridableVar(Types::SAlphaValue{.alpha = std::stof(std::string{r}), .overridden = false}, Types::PRIORITY_WINDOW_RULE);
|
||||||
|
else
|
||||||
|
throw std::runtime_error("more than 3 alpha values");
|
||||||
|
|
||||||
|
opacityIDX++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opacityIDX == 1) {
|
||||||
|
m_alphaInactive.first = m_alpha.first;
|
||||||
|
m_alphaFullscreen.first = m_alpha.first;
|
||||||
|
}
|
||||||
|
} catch (std::exception& e) { Debug::log(ERR, "Opacity rule \"{}\" failed with: {}", effect, e.what()); }
|
||||||
|
m_alpha.second = rule->getPropertiesMask();
|
||||||
|
m_alphaInactive.second = rule->getPropertiesMask();
|
||||||
|
m_alphaFullscreen.second = rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_TAG: {
|
||||||
|
m_dynamicTags.emplace_back(std::make_pair<>(effect, rule->getPropertiesMask()));
|
||||||
|
m_tagKeeper.applyTag(effect, true);
|
||||||
|
result.tagsChanged = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_MAX_SIZE: {
|
||||||
|
try {
|
||||||
|
static auto PCLAMP_TILED = CConfigValue<Hyprlang::INT>("misc:size_limits_tiled");
|
||||||
|
|
||||||
|
if (!m_window)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!m_window->m_isFloating && !sc<bool>(*PCLAMP_TILED))
|
||||||
|
break;
|
||||||
|
|
||||||
|
const auto VEC = configStringToVector2D(effect);
|
||||||
|
if (VEC.x < 1 || VEC.y < 1) {
|
||||||
|
Debug::log(ERR, "Invalid size for maxsize");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_maxSize.first = Types::COverridableVar(VEC, Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_window->clampWindowSize(std::nullopt, m_maxSize.first.value());
|
||||||
|
|
||||||
|
} catch (std::exception& e) { Debug::log(ERR, "maxsize rule \"{}\" failed with: {}", effect, e.what()); }
|
||||||
|
m_maxSize.second = rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_MIN_SIZE: {
|
||||||
|
try {
|
||||||
|
static auto PCLAMP_TILED = CConfigValue<Hyprlang::INT>("misc:size_limits_tiled");
|
||||||
|
|
||||||
|
if (!m_window)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!m_window->m_isFloating && !sc<bool>(*PCLAMP_TILED))
|
||||||
|
break;
|
||||||
|
|
||||||
|
const auto VEC = configStringToVector2D(effect);
|
||||||
|
if (VEC.x < 1 || VEC.y < 1) {
|
||||||
|
Debug::log(ERR, "Invalid size for maxsize");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_minSize.first = Types::COverridableVar(VEC, Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_window->clampWindowSize(std::nullopt, m_minSize.first.value());
|
||||||
|
} catch (std::exception& e) { Debug::log(ERR, "minsize rule \"{}\" failed with: {}", effect, e.what()); }
|
||||||
|
m_minSize.second = rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_BORDER_SIZE: {
|
||||||
|
try {
|
||||||
|
auto oldBorderSize = m_borderSize.first.valueOrDefault();
|
||||||
|
m_borderSize.first.set(std::stoi(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_borderSize.second |= rule->getPropertiesMask();
|
||||||
|
if (oldBorderSize != m_borderSize.first.valueOrDefault())
|
||||||
|
result.needsRelayout = true;
|
||||||
|
} catch (...) { Debug::log(ERR, "CWindowRuleApplicator::applyDynamicRule: invalid border_size {}", effect); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_ALLOWS_INPUT: {
|
||||||
|
m_allowsInput.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_allowsInput.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_DIM_AROUND: {
|
||||||
|
m_dimAround.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_dimAround.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_DECORATE: {
|
||||||
|
m_decorate.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_decorate.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_FOCUS_ON_ACTIVATE: {
|
||||||
|
m_focusOnActivate.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_focusOnActivate.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_KEEP_ASPECT_RATIO: {
|
||||||
|
m_keepAspectRatio.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_keepAspectRatio.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_NEAREST_NEIGHBOR: {
|
||||||
|
m_nearestNeighbor.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_nearestNeighbor.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_NO_ANIM: {
|
||||||
|
m_noAnim.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_noAnim.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_NO_BLUR: {
|
||||||
|
m_noBlur.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_noBlur.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_NO_DIM: {
|
||||||
|
m_noDim.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_noDim.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_NO_FOCUS: {
|
||||||
|
m_noFocus.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_noFocus.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_NO_FOLLOW_MOUSE: {
|
||||||
|
m_noFollowMouse.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_noFollowMouse.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_NO_MAX_SIZE: {
|
||||||
|
m_noMaxSize.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_noMaxSize.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_NO_SHADOW: {
|
||||||
|
m_noShadow.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_noShadow.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_NO_SHORTCUTS_INHIBIT: {
|
||||||
|
m_noShortcutsInhibit.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_noShortcutsInhibit.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_OPAQUE: {
|
||||||
|
m_opaque.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_opaque.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_FORCE_RGBX: {
|
||||||
|
m_RGBX.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_RGBX.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_SYNC_FULLSCREEN: {
|
||||||
|
m_syncFullscreen.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_syncFullscreen.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_IMMEDIATE: {
|
||||||
|
m_tearing.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_tearing.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_XRAY: {
|
||||||
|
m_xray.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_xray.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_RENDER_UNFOCUSED: {
|
||||||
|
m_renderUnfocused.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_renderUnfocused.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_NO_SCREEN_SHARE: {
|
||||||
|
m_noScreenShare.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_noScreenShare.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_NO_VRR: {
|
||||||
|
m_noVRR.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_noVRR.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_STAY_FOCUSED: {
|
||||||
|
m_stayFocused.first.set(truthy(effect), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_stayFocused.second |= rule->getPropertiesMask();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_SCROLL_MOUSE: {
|
||||||
|
try {
|
||||||
|
m_scrollMouse.first.set(std::clamp(std::stof(effect), 0.01F, 10.F), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_scrollMouse.second |= rule->getPropertiesMask();
|
||||||
|
} catch (...) { Debug::log(ERR, "CWindowRuleApplicator::applyDynamicRule: invalid scroll_mouse {}", effect); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_SCROLL_TOUCHPAD: {
|
||||||
|
try {
|
||||||
|
m_scrollTouchpad.first.set(std::clamp(std::stof(effect), 0.01F, 10.F), Types::PRIORITY_WINDOW_RULE);
|
||||||
|
m_scrollTouchpad.second |= rule->getPropertiesMask();
|
||||||
|
} catch (...) { Debug::log(ERR, "CWindowRuleApplicator::applyDynamicRule: invalid scroll_touchpad {}", effect); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
CWindowRuleApplicator::SRuleResult CWindowRuleApplicator::applyStaticRule(const SP<CWindowRule>& rule) {
|
||||||
|
for (const auto& [key, effect] : rule->effects()) {
|
||||||
|
switch (key) {
|
||||||
|
default: {
|
||||||
|
Debug::log(TRACE, "CWindowRuleApplicator::applyStaticRule: Skipping effect {}, not static", sc<std::underlying_type_t<eWindowRuleEffect>>(key));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WINDOW_RULE_EFFECT_FLOAT: {
|
||||||
|
static_.floating = truthy(effect);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_TILE: {
|
||||||
|
static_.floating = !truthy(effect);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_FULLSCREEN: {
|
||||||
|
static_.fullscreen = truthy(effect);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_MAXIMIZE: {
|
||||||
|
static_.maximize = truthy(effect);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_FULLSCREENSTATE: {
|
||||||
|
CVarList2 vars(std::string{effect}, 0, 's');
|
||||||
|
try {
|
||||||
|
static_.fullscreenStateInternal = std::stoi(std::string{vars[0]});
|
||||||
|
if (!vars[1].empty())
|
||||||
|
static_.fullscreenStateClient = std::stoi(std::string{vars[1]});
|
||||||
|
} catch (...) { Debug::log(ERR, "CWindowRuleApplicator::applyStaticRule: invalid fullscreen state {}", effect); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_MOVE: {
|
||||||
|
static_.position = effect;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_SIZE: {
|
||||||
|
static_.size = effect;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_CENTER: {
|
||||||
|
static_.center = truthy(effect);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_PSEUDO: {
|
||||||
|
static_.pseudo = truthy(effect);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_MONITOR: {
|
||||||
|
static_.monitor = effect;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_WORKSPACE: {
|
||||||
|
static_.workspace = effect;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_NOINITIALFOCUS: {
|
||||||
|
static_.noInitialFocus = truthy(effect);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_PIN: {
|
||||||
|
static_.pin = truthy(effect);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_GROUP: {
|
||||||
|
static_.group = effect;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_SUPPRESSEVENT: {
|
||||||
|
CVarList2 varlist(std::string{effect}, 0, 's');
|
||||||
|
for (const auto& e : varlist) {
|
||||||
|
static_.suppressEvent.emplace_back(e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_CONTENT: {
|
||||||
|
static_.content = NContentType::fromString(effect);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WINDOW_RULE_EFFECT_NOCLOSEFOR: {
|
||||||
|
try {
|
||||||
|
static_.noCloseFor = std::stoi(effect);
|
||||||
|
} catch (...) { Debug::log(ERR, "CWindowRuleApplicator::applyStaticRule: invalid no close for {}", effect); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SRuleResult{};
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindowRuleApplicator::readStaticRules() {
|
||||||
|
if (!m_window)
|
||||||
|
return;
|
||||||
|
|
||||||
|
static_ = {};
|
||||||
|
|
||||||
|
std::vector<SP<IRule>> toRemove;
|
||||||
|
bool tagsWereChanged = false;
|
||||||
|
|
||||||
|
for (const auto& r : ruleEngine()->rules()) {
|
||||||
|
if (r->type() != RULE_TYPE_WINDOW)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto wr = reinterpretPointerCast<CWindowRule>(r);
|
||||||
|
|
||||||
|
if (!wr->matches(m_window.lock(), true))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
applyStaticRule(wr);
|
||||||
|
const auto RES = applyDynamicRule(wr); // also apply dynamic, because we won't recheck it before layout gets data
|
||||||
|
tagsWereChanged = tagsWereChanged || RES.tagsChanged;
|
||||||
|
|
||||||
|
if (wr->isExecRule())
|
||||||
|
toRemove.emplace_back(wr);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& wr : toRemove) {
|
||||||
|
ruleEngine()->unregisterRule(wr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// recheck some props people might wanna use for static rules.
|
||||||
|
std::underlying_type_t<eRuleProperty> propsToRecheck = RULE_PROP_NONE;
|
||||||
|
if (tagsWereChanged)
|
||||||
|
propsToRecheck |= RULE_PROP_TAG;
|
||||||
|
if (static_.content != NContentType::CONTENT_TYPE_NONE)
|
||||||
|
propsToRecheck |= RULE_PROP_CONTENT;
|
||||||
|
|
||||||
|
if (propsToRecheck != RULE_PROP_NONE) {
|
||||||
|
for (const auto& r : ruleEngine()->rules()) {
|
||||||
|
if (r->type() != RULE_TYPE_WINDOW)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(r->getPropertiesMask() & propsToRecheck))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto wr = reinterpretPointerCast<CWindowRule>(r);
|
||||||
|
|
||||||
|
if (!wr->matches(m_window.lock(), true))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
applyStaticRule(wr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindowRuleApplicator::propertiesChanged(std::underlying_type_t<eRuleProperty> props) {
|
||||||
|
if (!m_window || !m_window->m_isMapped || m_window->isHidden())
|
||||||
|
return;
|
||||||
|
|
||||||
|
resetProps(props);
|
||||||
|
|
||||||
|
bool needsRelayout = false;
|
||||||
|
|
||||||
|
std::unordered_set<CWindowRuleEffectContainer::storageType> effectsNeedingRecheck;
|
||||||
|
std::unordered_set<SP<CWindowRule>> passedWrs;
|
||||||
|
|
||||||
|
for (const auto& r : ruleEngine()->rules()) {
|
||||||
|
if (r->type() != RULE_TYPE_WINDOW)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!(r->getPropertiesMask() & props))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto wr = reinterpretPointerCast<CWindowRule>(r);
|
||||||
|
|
||||||
|
if (!wr->matches(m_window.lock()))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (const auto& [type, eff] : wr->effects()) {
|
||||||
|
effectsNeedingRecheck.emplace(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
passedWrs.emplace(std::move(wr));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& r : ruleEngine()->rules()) {
|
||||||
|
if (r->type() != RULE_TYPE_WINDOW)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const auto WR = reinterpretPointerCast<CWindowRule>(r);
|
||||||
|
|
||||||
|
if (!(WR->getPropertiesMask() & props) && !setsIntersect(WR->effectsSet(), effectsNeedingRecheck))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!std::ranges::contains(passedWrs, WR) && !WR->matches(m_window.lock()))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const auto RES = applyDynamicRule(WR);
|
||||||
|
needsRelayout = needsRelayout || RES.needsRelayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_window->updateDecorationValues();
|
||||||
|
|
||||||
|
if (needsRelayout)
|
||||||
|
g_pDecorationPositioner->forceRecalcFor(m_window.lock());
|
||||||
|
|
||||||
|
// for plugins
|
||||||
|
EMIT_HOOK_EVENT("windowUpdateRules", m_window.lock());
|
||||||
|
}
|
||||||
148
src/desktop/rule/windowRule/WindowRuleApplicator.hpp
Normal file
148
src/desktop/rule/windowRule/WindowRuleApplicator.hpp
Normal file
|
|
@ -0,0 +1,148 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "WindowRuleEffectContainer.hpp"
|
||||||
|
#include "../../DesktopTypes.hpp"
|
||||||
|
#include "../Rule.hpp"
|
||||||
|
#include "../../types/OverridableVar.hpp"
|
||||||
|
#include "../../../helpers/math/Math.hpp"
|
||||||
|
#include "../../../helpers/TagKeeper.hpp"
|
||||||
|
#include "../../../config/ConfigDataValues.hpp"
|
||||||
|
|
||||||
|
namespace Desktop::Rule {
|
||||||
|
class CWindowRule;
|
||||||
|
|
||||||
|
enum eIdleInhibitMode : uint8_t {
|
||||||
|
IDLEINHIBIT_NONE = 0,
|
||||||
|
IDLEINHIBIT_ALWAYS,
|
||||||
|
IDLEINHIBIT_FULLSCREEN,
|
||||||
|
IDLEINHIBIT_FOCUS
|
||||||
|
};
|
||||||
|
|
||||||
|
class CWindowRuleApplicator {
|
||||||
|
public:
|
||||||
|
CWindowRuleApplicator(PHLWINDOW w);
|
||||||
|
~CWindowRuleApplicator() = default;
|
||||||
|
|
||||||
|
CWindowRuleApplicator(const CWindowRuleApplicator&) = delete;
|
||||||
|
CWindowRuleApplicator(CWindowRuleApplicator&) = delete;
|
||||||
|
CWindowRuleApplicator(CWindowRuleApplicator&&) = delete;
|
||||||
|
|
||||||
|
void propertiesChanged(std::underlying_type_t<eRuleProperty> props);
|
||||||
|
void resetProps(std::underlying_type_t<eRuleProperty> props, Types::eOverridePriority prio = Types::PRIORITY_WINDOW_RULE);
|
||||||
|
void readStaticRules();
|
||||||
|
void applyStaticRules();
|
||||||
|
|
||||||
|
// static props
|
||||||
|
struct {
|
||||||
|
std::string monitor, workspace, group;
|
||||||
|
|
||||||
|
std::optional<bool> floating;
|
||||||
|
|
||||||
|
bool fullscreen = false;
|
||||||
|
bool maximize = false;
|
||||||
|
bool pseudo = false;
|
||||||
|
bool pin = false;
|
||||||
|
bool noInitialFocus = false;
|
||||||
|
|
||||||
|
std::optional<int> fullscreenStateClient;
|
||||||
|
std::optional<int> fullscreenStateInternal;
|
||||||
|
std::optional<int> center;
|
||||||
|
std::optional<int> content;
|
||||||
|
std::optional<int> noCloseFor;
|
||||||
|
|
||||||
|
std::string size, position;
|
||||||
|
|
||||||
|
std::vector<std::string> suppressEvent;
|
||||||
|
} static_;
|
||||||
|
|
||||||
|
struct SCustomPropContainer {
|
||||||
|
CWindowRuleEffectContainer::storageType idx = WINDOW_RULE_EFFECT_NONE;
|
||||||
|
std::underlying_type_t<eRuleProperty> propMask = RULE_PROP_NONE;
|
||||||
|
std::string effect;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This struct holds props that were dynamically registered. Plugins may read this.
|
||||||
|
struct {
|
||||||
|
std::unordered_map<CWindowRuleEffectContainer::storageType, UP<SCustomPropContainer>> props;
|
||||||
|
} m_otherProps;
|
||||||
|
|
||||||
|
#define COMMA ,
|
||||||
|
#define DEFINE_PROP(type, name, def) \
|
||||||
|
private: \
|
||||||
|
std::pair<Types::COverridableVar<type>, std::underlying_type_t<eRuleProperty>> m_##name = {def, RULE_PROP_NONE}; \
|
||||||
|
\
|
||||||
|
public: \
|
||||||
|
Types::COverridableVar<type>& name() { \
|
||||||
|
return m_##name.first; \
|
||||||
|
} \
|
||||||
|
void name##Override(const Types::COverridableVar<type>& other) { \
|
||||||
|
m_##name.first = other; \
|
||||||
|
}
|
||||||
|
|
||||||
|
// dynamic props
|
||||||
|
DEFINE_PROP(Types::SAlphaValue, alpha, Types::SAlphaValue{})
|
||||||
|
DEFINE_PROP(Types::SAlphaValue, alphaInactive, Types::SAlphaValue{})
|
||||||
|
DEFINE_PROP(Types::SAlphaValue, alphaFullscreen, Types::SAlphaValue{})
|
||||||
|
|
||||||
|
DEFINE_PROP(bool, allowsInput, false)
|
||||||
|
DEFINE_PROP(bool, decorate, true)
|
||||||
|
DEFINE_PROP(bool, focusOnActivate, false)
|
||||||
|
DEFINE_PROP(bool, keepAspectRatio, false)
|
||||||
|
DEFINE_PROP(bool, nearestNeighbor, false)
|
||||||
|
DEFINE_PROP(bool, noAnim, false)
|
||||||
|
DEFINE_PROP(bool, noBlur, false)
|
||||||
|
DEFINE_PROP(bool, noDim, false)
|
||||||
|
DEFINE_PROP(bool, noFocus, false)
|
||||||
|
DEFINE_PROP(bool, noMaxSize, false)
|
||||||
|
DEFINE_PROP(bool, noShadow, false)
|
||||||
|
DEFINE_PROP(bool, noShortcutsInhibit, false)
|
||||||
|
DEFINE_PROP(bool, opaque, false)
|
||||||
|
DEFINE_PROP(bool, dimAround, false)
|
||||||
|
DEFINE_PROP(bool, RGBX, false)
|
||||||
|
DEFINE_PROP(bool, syncFullscreen, true)
|
||||||
|
DEFINE_PROP(bool, tearing, false)
|
||||||
|
DEFINE_PROP(bool, xray, false)
|
||||||
|
DEFINE_PROP(bool, renderUnfocused, false)
|
||||||
|
DEFINE_PROP(bool, noFollowMouse, false)
|
||||||
|
DEFINE_PROP(bool, noScreenShare, false)
|
||||||
|
DEFINE_PROP(bool, noVRR, false)
|
||||||
|
DEFINE_PROP(bool, persistentSize, false)
|
||||||
|
DEFINE_PROP(bool, stayFocused, false)
|
||||||
|
|
||||||
|
DEFINE_PROP(int, idleInhibitMode, false)
|
||||||
|
|
||||||
|
DEFINE_PROP(Hyprlang::INT, borderSize, {std::string("general:border_size") COMMA sc<Hyprlang::INT>(0) COMMA std::nullopt})
|
||||||
|
DEFINE_PROP(Hyprlang::INT, rounding, {std::string("decoration:rounding") COMMA sc<Hyprlang::INT>(0) COMMA std::nullopt})
|
||||||
|
|
||||||
|
DEFINE_PROP(Hyprlang::FLOAT, roundingPower, {std::string("decoration:rounding_power")})
|
||||||
|
DEFINE_PROP(Hyprlang::FLOAT, scrollMouse, {std::string("input:scroll_factor")})
|
||||||
|
DEFINE_PROP(Hyprlang::FLOAT, scrollTouchpad, {std::string("input:touchpad:scroll_factor")})
|
||||||
|
|
||||||
|
DEFINE_PROP(std::string, animationStyle, std::string(""))
|
||||||
|
|
||||||
|
DEFINE_PROP(Vector2D, maxSize, Vector2D{})
|
||||||
|
DEFINE_PROP(Vector2D, minSize, Vector2D{})
|
||||||
|
|
||||||
|
DEFINE_PROP(CGradientValueData, activeBorderColor, {})
|
||||||
|
DEFINE_PROP(CGradientValueData, inactiveBorderColor, {})
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::underlying_type_t<eRuleProperty>>> m_dynamicTags;
|
||||||
|
CTagKeeper m_tagKeeper;
|
||||||
|
|
||||||
|
#undef COMMA
|
||||||
|
#undef DEFINE_PROP
|
||||||
|
|
||||||
|
private:
|
||||||
|
PHLWINDOWREF m_window;
|
||||||
|
|
||||||
|
struct SRuleResult {
|
||||||
|
bool needsRelayout = false;
|
||||||
|
bool tagsChanged = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
SRuleResult applyDynamicRule(const SP<CWindowRule>& rule);
|
||||||
|
SRuleResult applyStaticRule(const SP<CWindowRule>& rule);
|
||||||
|
};
|
||||||
|
};
|
||||||
76
src/desktop/rule/windowRule/WindowRuleEffectContainer.cpp
Normal file
76
src/desktop/rule/windowRule/WindowRuleEffectContainer.cpp
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
#include "WindowRuleEffectContainer.hpp"
|
||||||
|
|
||||||
|
using namespace Desktop;
|
||||||
|
using namespace Desktop::Rule;
|
||||||
|
|
||||||
|
//
|
||||||
|
SP<CWindowRuleEffectContainer> Rule::windowEffects() {
|
||||||
|
static SP<CWindowRuleEffectContainer> container = makeShared<CWindowRuleEffectContainer>();
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const std::vector<std::string> EFFECT_STRINGS = {
|
||||||
|
"__internal_none", //
|
||||||
|
"float", //
|
||||||
|
"tile", //
|
||||||
|
"fullscreen", //
|
||||||
|
"maximize", //
|
||||||
|
"fullscreen_state", //
|
||||||
|
"move", //
|
||||||
|
"size", //
|
||||||
|
"center", //
|
||||||
|
"pseudo", //
|
||||||
|
"monitor", //
|
||||||
|
"workspace", //
|
||||||
|
"no_initial_focus", //
|
||||||
|
"pin", //
|
||||||
|
"group", //
|
||||||
|
"suppress_event", //
|
||||||
|
"content", //
|
||||||
|
"no_close_for", //
|
||||||
|
"rounding", //
|
||||||
|
"rounding_power", //
|
||||||
|
"persistent_size", //
|
||||||
|
"animation", //
|
||||||
|
"border_color", //
|
||||||
|
"idle_inhibit", //
|
||||||
|
"opacity", //
|
||||||
|
"tag", //
|
||||||
|
"max_size", //
|
||||||
|
"min_size", //
|
||||||
|
"border_size", //
|
||||||
|
"allows_input", //
|
||||||
|
"dim_around", //
|
||||||
|
"decorate", //
|
||||||
|
"focus_on_activate", //
|
||||||
|
"keep_aspect_ratio", //
|
||||||
|
"nearest_neighbor", //
|
||||||
|
"no_anim", //
|
||||||
|
"no_blur", //
|
||||||
|
"no_dim", //
|
||||||
|
"no_focus", //
|
||||||
|
"no_follow_mouse", //
|
||||||
|
"no_max_size", //
|
||||||
|
"no_shadow", //
|
||||||
|
"no_shortcuts_inhibit", //
|
||||||
|
"opaque", //
|
||||||
|
"force_rgbx", //
|
||||||
|
"sync_fullscreen", //
|
||||||
|
"immediate", //
|
||||||
|
"xray", //
|
||||||
|
"render_unfocused", //
|
||||||
|
"no_screen_share", //
|
||||||
|
"no_vrr", //
|
||||||
|
"scroll_mouse", //
|
||||||
|
"scroll_touchpad", //
|
||||||
|
"stay_focused", //
|
||||||
|
"__internal_last_static", //
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is here so that if we change the rules, we get reminded to update
|
||||||
|
// the strings.
|
||||||
|
static_assert(WINDOW_RULE_EFFECT_LAST_STATIC == 54);
|
||||||
|
|
||||||
|
CWindowRuleEffectContainer::CWindowRuleEffectContainer() : IEffectContainer<eWindowRuleEffect>(std::vector<std::string>{EFFECT_STRINGS}) {
|
||||||
|
;
|
||||||
|
}
|
||||||
79
src/desktop/rule/windowRule/WindowRuleEffectContainer.hpp
Normal file
79
src/desktop/rule/windowRule/WindowRuleEffectContainer.hpp
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../effect/EffectContainer.hpp"
|
||||||
|
#include "../../../helpers/memory/Memory.hpp"
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Desktop::Rule {
|
||||||
|
enum eWindowRuleEffect : uint8_t {
|
||||||
|
WINDOW_RULE_EFFECT_NONE = 0,
|
||||||
|
|
||||||
|
// static
|
||||||
|
WINDOW_RULE_EFFECT_FLOAT,
|
||||||
|
WINDOW_RULE_EFFECT_TILE,
|
||||||
|
WINDOW_RULE_EFFECT_FULLSCREEN,
|
||||||
|
WINDOW_RULE_EFFECT_MAXIMIZE,
|
||||||
|
WINDOW_RULE_EFFECT_FULLSCREENSTATE,
|
||||||
|
WINDOW_RULE_EFFECT_MOVE,
|
||||||
|
WINDOW_RULE_EFFECT_SIZE,
|
||||||
|
WINDOW_RULE_EFFECT_CENTER,
|
||||||
|
WINDOW_RULE_EFFECT_PSEUDO,
|
||||||
|
WINDOW_RULE_EFFECT_MONITOR,
|
||||||
|
WINDOW_RULE_EFFECT_WORKSPACE,
|
||||||
|
WINDOW_RULE_EFFECT_NOINITIALFOCUS,
|
||||||
|
WINDOW_RULE_EFFECT_PIN,
|
||||||
|
WINDOW_RULE_EFFECT_GROUP,
|
||||||
|
WINDOW_RULE_EFFECT_SUPPRESSEVENT,
|
||||||
|
WINDOW_RULE_EFFECT_CONTENT,
|
||||||
|
WINDOW_RULE_EFFECT_NOCLOSEFOR,
|
||||||
|
|
||||||
|
// dynamic
|
||||||
|
WINDOW_RULE_EFFECT_ROUNDING,
|
||||||
|
WINDOW_RULE_EFFECT_ROUNDING_POWER,
|
||||||
|
WINDOW_RULE_EFFECT_PERSISTENT_SIZE,
|
||||||
|
WINDOW_RULE_EFFECT_ANIMATION,
|
||||||
|
WINDOW_RULE_EFFECT_BORDER_COLOR,
|
||||||
|
WINDOW_RULE_EFFECT_IDLE_INHIBIT,
|
||||||
|
WINDOW_RULE_EFFECT_OPACITY,
|
||||||
|
WINDOW_RULE_EFFECT_TAG,
|
||||||
|
WINDOW_RULE_EFFECT_MAX_SIZE,
|
||||||
|
WINDOW_RULE_EFFECT_MIN_SIZE,
|
||||||
|
WINDOW_RULE_EFFECT_BORDER_SIZE,
|
||||||
|
WINDOW_RULE_EFFECT_ALLOWS_INPUT,
|
||||||
|
WINDOW_RULE_EFFECT_DIM_AROUND,
|
||||||
|
WINDOW_RULE_EFFECT_DECORATE,
|
||||||
|
WINDOW_RULE_EFFECT_FOCUS_ON_ACTIVATE,
|
||||||
|
WINDOW_RULE_EFFECT_KEEP_ASPECT_RATIO,
|
||||||
|
WINDOW_RULE_EFFECT_NEAREST_NEIGHBOR,
|
||||||
|
WINDOW_RULE_EFFECT_NO_ANIM,
|
||||||
|
WINDOW_RULE_EFFECT_NO_BLUR,
|
||||||
|
WINDOW_RULE_EFFECT_NO_DIM,
|
||||||
|
WINDOW_RULE_EFFECT_NO_FOCUS,
|
||||||
|
WINDOW_RULE_EFFECT_NO_FOLLOW_MOUSE,
|
||||||
|
WINDOW_RULE_EFFECT_NO_MAX_SIZE,
|
||||||
|
WINDOW_RULE_EFFECT_NO_SHADOW,
|
||||||
|
WINDOW_RULE_EFFECT_NO_SHORTCUTS_INHIBIT,
|
||||||
|
WINDOW_RULE_EFFECT_OPAQUE,
|
||||||
|
WINDOW_RULE_EFFECT_FORCE_RGBX,
|
||||||
|
WINDOW_RULE_EFFECT_SYNC_FULLSCREEN,
|
||||||
|
WINDOW_RULE_EFFECT_IMMEDIATE,
|
||||||
|
WINDOW_RULE_EFFECT_XRAY,
|
||||||
|
WINDOW_RULE_EFFECT_RENDER_UNFOCUSED,
|
||||||
|
WINDOW_RULE_EFFECT_NO_SCREEN_SHARE,
|
||||||
|
WINDOW_RULE_EFFECT_NO_VRR,
|
||||||
|
WINDOW_RULE_EFFECT_SCROLL_MOUSE,
|
||||||
|
WINDOW_RULE_EFFECT_SCROLL_TOUCHPAD,
|
||||||
|
WINDOW_RULE_EFFECT_STAY_FOCUSED,
|
||||||
|
|
||||||
|
WINDOW_RULE_EFFECT_LAST_STATIC,
|
||||||
|
};
|
||||||
|
|
||||||
|
class CWindowRuleEffectContainer : public IEffectContainer<eWindowRuleEffect> {
|
||||||
|
public:
|
||||||
|
CWindowRuleEffectContainer();
|
||||||
|
virtual ~CWindowRuleEffectContainer() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
SP<CWindowRuleEffectContainer> windowEffects();
|
||||||
|
};
|
||||||
153
src/desktop/types/OverridableVar.hpp
Normal file
153
src/desktop/types/OverridableVar.hpp
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <any>
|
||||||
|
#include <map>
|
||||||
|
#include "../../config/ConfigValue.hpp"
|
||||||
|
|
||||||
|
namespace Desktop::Types {
|
||||||
|
|
||||||
|
struct SAlphaValue {
|
||||||
|
float alpha = 1.F;
|
||||||
|
bool overridden = false;
|
||||||
|
|
||||||
|
float applyAlpha(float a) const {
|
||||||
|
if (overridden)
|
||||||
|
return alpha;
|
||||||
|
else
|
||||||
|
return alpha * a;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
enum eOverridePriority : uint8_t {
|
||||||
|
PRIORITY_LAYOUT = 0,
|
||||||
|
PRIORITY_WORKSPACE_RULE,
|
||||||
|
PRIORITY_WINDOW_RULE,
|
||||||
|
PRIORITY_SET_PROP,
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T clampOptional(T const& value, std::optional<T> const& min, std::optional<T> const& max) {
|
||||||
|
return std::clamp(value, min.value_or(std::numeric_limits<T>::min()), max.value_or(std::numeric_limits<T>::max()));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, bool Extended = std::is_same_v<T, bool> || std::is_same_v<T, Hyprlang::INT> || std::is_same_v<T, Hyprlang::FLOAT>>
|
||||||
|
class COverridableVar {
|
||||||
|
public:
|
||||||
|
COverridableVar(T const& value, eOverridePriority priority) {
|
||||||
|
m_values[priority] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
COverridableVar(T const& value) : m_defaultValue{value} {}
|
||||||
|
COverridableVar(T const& value, std::optional<T> const& min, std::optional<T> const& max = std::nullopt) : m_defaultValue{value}, m_minValue{min}, m_maxValue{max} {}
|
||||||
|
COverridableVar(std::string const& value)
|
||||||
|
requires(Extended && !std::is_same_v<T, bool>)
|
||||||
|
: m_configValue(SP<CConfigValue<T>>(new CConfigValue<T>(value))) {}
|
||||||
|
COverridableVar(std::string const& value, std::optional<T> const& min, std::optional<T> const& max = std::nullopt)
|
||||||
|
requires(Extended && !std::is_same_v<T, bool>)
|
||||||
|
: m_minValue(min), m_maxValue(max), m_configValue(SP<CConfigValue<T>>(new CConfigValue<T>(value))) {}
|
||||||
|
|
||||||
|
COverridableVar() = default;
|
||||||
|
~COverridableVar() = default;
|
||||||
|
|
||||||
|
COverridableVar& operator=(COverridableVar<T> const& other) {
|
||||||
|
// Self-assignment check
|
||||||
|
if (this == &other)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
for (auto const& value : other.m_values) {
|
||||||
|
if constexpr (Extended && !std::is_same_v<T, bool>)
|
||||||
|
m_values[value.first] = clampOptional(value.second, m_minValue, m_maxValue);
|
||||||
|
else
|
||||||
|
m_values[value.first] = value.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set(T value, eOverridePriority priority) {
|
||||||
|
m_values[priority] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unset(eOverridePriority priority) {
|
||||||
|
m_values.erase(priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasValue() const {
|
||||||
|
return !m_values.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
T value() const {
|
||||||
|
if (!m_values.empty())
|
||||||
|
return std::prev(m_values.end())->second;
|
||||||
|
else
|
||||||
|
throw std::bad_optional_access();
|
||||||
|
}
|
||||||
|
|
||||||
|
T valueOr(T const& other) const {
|
||||||
|
if (hasValue())
|
||||||
|
return value();
|
||||||
|
else
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
|
||||||
|
T valueOrDefault() const
|
||||||
|
requires(Extended && !std::is_same_v<T, bool>)
|
||||||
|
{
|
||||||
|
if (hasValue())
|
||||||
|
return value();
|
||||||
|
else if (m_defaultValue.has_value())
|
||||||
|
return m_defaultValue.value();
|
||||||
|
else
|
||||||
|
return **std::any_cast<SP<CConfigValue<T>>>(m_configValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
T valueOrDefault() const
|
||||||
|
requires(!Extended || std::is_same_v<T, bool>)
|
||||||
|
{
|
||||||
|
if (hasValue())
|
||||||
|
return value();
|
||||||
|
else if (!m_defaultValue.has_value())
|
||||||
|
throw std::bad_optional_access();
|
||||||
|
else
|
||||||
|
return m_defaultValue.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
eOverridePriority getPriority() const {
|
||||||
|
if (!m_values.empty())
|
||||||
|
return std::prev(m_values.end())->first;
|
||||||
|
else
|
||||||
|
throw std::bad_optional_access();
|
||||||
|
}
|
||||||
|
|
||||||
|
void increment(T const& other, eOverridePriority priority) {
|
||||||
|
if constexpr (std::is_same_v<T, bool>)
|
||||||
|
m_values[priority] = valueOr(false) ^ other;
|
||||||
|
else
|
||||||
|
m_values[priority] = clampOptional(valueOrDefault() + other, m_minValue, m_maxValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void matchOptional(std::optional<T> const& optValue, eOverridePriority priority) {
|
||||||
|
if (optValue.has_value())
|
||||||
|
m_values[priority] = optValue.value();
|
||||||
|
else
|
||||||
|
unset(priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator std::optional<T>() {
|
||||||
|
if (hasValue())
|
||||||
|
return value();
|
||||||
|
else
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<eOverridePriority, T> m_values;
|
||||||
|
std::optional<T> m_defaultValue; // used for toggling, so required for bool
|
||||||
|
std::optional<T> m_minValue;
|
||||||
|
std::optional<T> m_maxValue;
|
||||||
|
std::any m_configValue; // only there for select variables
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -135,31 +135,23 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
PWINDOW->m_X11ShouldntFocus = PWINDOW->m_X11ShouldntFocus || (PWINDOW->m_isX11 && PWINDOW->isX11OverrideRedirect() && !PWINDOW->m_xwaylandSurface->wantsFocus());
|
PWINDOW->m_X11ShouldntFocus = PWINDOW->m_X11ShouldntFocus || (PWINDOW->m_isX11 && PWINDOW->isX11OverrideRedirect() && !PWINDOW->m_xwaylandSurface->wantsFocus());
|
||||||
|
|
||||||
// window rules
|
// window rules
|
||||||
PWINDOW->m_matchedRules = g_pConfigManager->getMatchingRules(PWINDOW, false);
|
|
||||||
std::optional<eFullscreenMode> requestedInternalFSMode, requestedClientFSMode;
|
std::optional<eFullscreenMode> requestedInternalFSMode, requestedClientFSMode;
|
||||||
std::optional<SFullscreenState> requestedFSState;
|
std::optional<SFullscreenState> requestedFSState;
|
||||||
if (PWINDOW->m_wantsInitialFullscreen || (PWINDOW->m_isX11 && PWINDOW->m_xwaylandSurface->m_fullscreen))
|
if (PWINDOW->m_wantsInitialFullscreen || (PWINDOW->m_isX11 && PWINDOW->m_xwaylandSurface->m_fullscreen))
|
||||||
requestedClientFSMode = FSMODE_FULLSCREEN;
|
requestedClientFSMode = FSMODE_FULLSCREEN;
|
||||||
MONITORID requestedFSMonitor = PWINDOW->m_wantsInitialFullscreenMonitor;
|
MONITORID requestedFSMonitor = PWINDOW->m_wantsInitialFullscreenMonitor;
|
||||||
|
|
||||||
for (auto const& r : PWINDOW->m_matchedRules) {
|
PWINDOW->m_ruleApplicator->readStaticRules();
|
||||||
switch (r->m_ruleType) {
|
{
|
||||||
case CWindowRule::RULE_MONITOR: {
|
if (!PWINDOW->m_ruleApplicator->static_.monitor.empty()) {
|
||||||
try {
|
const auto& MONITORSTR = PWINDOW->m_ruleApplicator->static_.monitor;
|
||||||
const auto MONITORSTR = trim(r->m_rule.substr(r->m_rule.find(' ')));
|
|
||||||
|
|
||||||
if (MONITORSTR == "unset")
|
if (MONITORSTR == "unset")
|
||||||
PWINDOW->m_monitor = PMONITOR;
|
PWINDOW->m_monitor = PMONITOR;
|
||||||
else {
|
else {
|
||||||
const auto MONITOR = g_pCompositor->getMonitorFromString(MONITORSTR);
|
const auto MONITOR = g_pCompositor->getMonitorFromString(MONITORSTR);
|
||||||
|
|
||||||
if (MONITOR)
|
if (MONITOR) {
|
||||||
PWINDOW->m_monitor = MONITOR;
|
PWINDOW->m_monitor = MONITOR;
|
||||||
else {
|
|
||||||
Debug::log(ERR, "No monitor in monitor {} rule", MONITORSTR);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto PMONITORFROMID = PWINDOW->m_monitor.lock();
|
const auto PMONITORFROMID = PWINDOW->m_monitor.lock();
|
||||||
|
|
||||||
|
|
@ -172,12 +164,13 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
|
|
||||||
Debug::log(LOG, "Rule monitor, applying to {:mw}", PWINDOW);
|
Debug::log(LOG, "Rule monitor, applying to {:mw}", PWINDOW);
|
||||||
requestedFSMonitor = MONITOR_INVALID;
|
requestedFSMonitor = MONITOR_INVALID;
|
||||||
} catch (std::exception& e) { Debug::log(ERR, "Rule monitor failed, rule: {} -> {} | err: {}", r->m_rule, r->m_value, e.what()); }
|
} else
|
||||||
break;
|
Debug::log(ERR, "No monitor in monitor {} rule", MONITORSTR);
|
||||||
}
|
}
|
||||||
case CWindowRule::RULE_WORKSPACE: {
|
}
|
||||||
// check if it isn't unset
|
|
||||||
const auto WORKSPACERQ = r->m_rule.substr(r->m_rule.find_first_of(' ') + 1);
|
if (!PWINDOW->m_ruleApplicator->static_.workspace.empty()) {
|
||||||
|
const auto WORKSPACERQ = PWINDOW->m_ruleApplicator->static_.workspace;
|
||||||
|
|
||||||
if (WORKSPACERQ == "unset")
|
if (WORKSPACERQ == "unset")
|
||||||
requestedWorkspace = "";
|
requestedWorkspace = "";
|
||||||
|
|
@ -189,83 +182,55 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
if (JUSTWORKSPACE == PWORKSPACE->m_name || JUSTWORKSPACE == "name:" + PWORKSPACE->m_name)
|
if (JUSTWORKSPACE == PWORKSPACE->m_name || JUSTWORKSPACE == "name:" + PWORKSPACE->m_name)
|
||||||
requestedWorkspace = "";
|
requestedWorkspace = "";
|
||||||
|
|
||||||
Debug::log(LOG, "Rule workspace matched by {}, {} applied.", PWINDOW, r->m_value);
|
Debug::log(LOG, "Rule workspace matched by {}, {} applied.", PWINDOW, PWINDOW->m_ruleApplicator->static_.workspace);
|
||||||
requestedFSMonitor = MONITOR_INVALID;
|
requestedFSMonitor = MONITOR_INVALID;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case CWindowRule::RULE_FLOAT: {
|
|
||||||
PWINDOW->m_isFloating = true;
|
if (PWINDOW->m_ruleApplicator->static_.floating.has_value())
|
||||||
break;
|
PWINDOW->m_isFloating = PWINDOW->m_ruleApplicator->static_.floating.value();
|
||||||
}
|
|
||||||
case CWindowRule::RULE_TILE: {
|
if (PWINDOW->m_ruleApplicator->static_.pseudo)
|
||||||
PWINDOW->m_isFloating = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWindowRule::RULE_PSEUDO: {
|
|
||||||
PWINDOW->m_isPseudotiled = true;
|
PWINDOW->m_isPseudotiled = true;
|
||||||
break;
|
|
||||||
}
|
if (PWINDOW->m_ruleApplicator->static_.noInitialFocus)
|
||||||
case CWindowRule::RULE_NOINITIALFOCUS: {
|
|
||||||
PWINDOW->m_noInitialFocus = true;
|
PWINDOW->m_noInitialFocus = true;
|
||||||
break;
|
|
||||||
|
if (PWINDOW->m_ruleApplicator->static_.fullscreenStateClient || PWINDOW->m_ruleApplicator->static_.fullscreenStateInternal) {
|
||||||
|
requestedFSState = SFullscreenState{
|
||||||
|
.internal = sc<eFullscreenMode>(PWINDOW->m_ruleApplicator->static_.fullscreenStateInternal.value_or(0)),
|
||||||
|
.client = sc<eFullscreenMode>(PWINDOW->m_ruleApplicator->static_.fullscreenStateClient.value_or(0)),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
case CWindowRule::RULE_FULLSCREENSTATE: {
|
|
||||||
const auto ARGS = CVarList(r->m_rule.substr(r->m_rule.find_first_of(' ') + 1), 2, ' ');
|
if (!PWINDOW->m_ruleApplicator->static_.suppressEvent.empty()) {
|
||||||
int internalMode, clientMode;
|
for (const auto& var : PWINDOW->m_ruleApplicator->static_.suppressEvent) {
|
||||||
try {
|
if (var == "fullscreen")
|
||||||
internalMode = std::stoi(ARGS[0]);
|
|
||||||
} catch (std::exception& e) { internalMode = 0; }
|
|
||||||
try {
|
|
||||||
clientMode = std::stoi(ARGS[1]);
|
|
||||||
} catch (std::exception& e) { clientMode = 0; }
|
|
||||||
requestedFSState = SFullscreenState{.internal = sc<eFullscreenMode>(internalMode), .client = sc<eFullscreenMode>(clientMode)};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWindowRule::RULE_SUPPRESSEVENT: {
|
|
||||||
CVarList vars(r->m_rule, 0, 's', true);
|
|
||||||
for (size_t i = 1; i < vars.size(); ++i) {
|
|
||||||
if (vars[i] == "fullscreen")
|
|
||||||
PWINDOW->m_suppressedEvents |= SUPPRESS_FULLSCREEN;
|
PWINDOW->m_suppressedEvents |= SUPPRESS_FULLSCREEN;
|
||||||
else if (vars[i] == "maximize")
|
else if (var == "maximize")
|
||||||
PWINDOW->m_suppressedEvents |= SUPPRESS_MAXIMIZE;
|
PWINDOW->m_suppressedEvents |= SUPPRESS_MAXIMIZE;
|
||||||
else if (vars[i] == "activate")
|
else if (var == "activate")
|
||||||
PWINDOW->m_suppressedEvents |= SUPPRESS_ACTIVATE;
|
PWINDOW->m_suppressedEvents |= SUPPRESS_ACTIVATE;
|
||||||
else if (vars[i] == "activatefocus")
|
else if (var == "activatefocus")
|
||||||
PWINDOW->m_suppressedEvents |= SUPPRESS_ACTIVATE_FOCUSONLY;
|
PWINDOW->m_suppressedEvents |= SUPPRESS_ACTIVATE_FOCUSONLY;
|
||||||
else if (vars[i] == "fullscreenoutput")
|
else if (var == "fullscreenoutput")
|
||||||
PWINDOW->m_suppressedEvents |= SUPPRESS_FULLSCREEN_OUTPUT;
|
PWINDOW->m_suppressedEvents |= SUPPRESS_FULLSCREEN_OUTPUT;
|
||||||
else
|
else
|
||||||
Debug::log(ERR, "Error while parsing suppressevent windowrule: unknown event type {}", vars[i]);
|
Debug::log(ERR, "Error while parsing suppressevent windowrule: unknown event type {}", var);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case CWindowRule::RULE_PIN: {
|
|
||||||
|
if (PWINDOW->m_ruleApplicator->static_.pin)
|
||||||
PWINDOW->m_pinned = true;
|
PWINDOW->m_pinned = true;
|
||||||
break;
|
|
||||||
}
|
if (PWINDOW->m_ruleApplicator->static_.fullscreen)
|
||||||
case CWindowRule::RULE_FULLSCREEN: {
|
|
||||||
requestedInternalFSMode = FSMODE_FULLSCREEN;
|
requestedInternalFSMode = FSMODE_FULLSCREEN;
|
||||||
break;
|
|
||||||
}
|
if (PWINDOW->m_ruleApplicator->static_.maximize)
|
||||||
case CWindowRule::RULE_MAXIMIZE: {
|
|
||||||
requestedInternalFSMode = FSMODE_MAXIMIZED;
|
requestedInternalFSMode = FSMODE_MAXIMIZED;
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWindowRule::RULE_STAYFOCUSED: {
|
|
||||||
PWINDOW->m_stayFocused = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWindowRule::RULE_GROUP: {
|
|
||||||
if (PWINDOW->m_groupRules & GROUP_OVERRIDE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// `group` is a shorthand of `group set`
|
if (!PWINDOW->m_ruleApplicator->static_.group.empty()) {
|
||||||
if (trim(r->m_rule) == "group") {
|
if (!(PWINDOW->m_groupRules & GROUP_OVERRIDE) && trim(PWINDOW->m_ruleApplicator->static_.group) != "group") {
|
||||||
PWINDOW->m_groupRules |= GROUP_SET;
|
CVarList2 vars(std::string{PWINDOW->m_ruleApplicator->static_.group}, 0, 's');
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
CVarList vars(r->m_rule, 0, 's');
|
|
||||||
std::string vPrev = "";
|
std::string vPrev = "";
|
||||||
|
|
||||||
for (auto const& v : vars) {
|
for (auto const& v : vars) {
|
||||||
|
|
@ -302,26 +267,14 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
}
|
}
|
||||||
vPrev = v;
|
vPrev = v;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case CWindowRule::RULE_CONTENT: {
|
|
||||||
const CVarList VARS(r->m_rule, 0, ' ');
|
|
||||||
try {
|
|
||||||
PWINDOW->setContentType(NContentType::fromString(VARS[1]));
|
|
||||||
} catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->m_rule, e.what()); }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWindowRule::RULE_NOCLOSEFOR: {
|
|
||||||
const CVarList VARS(r->m_rule, 0, ' ');
|
|
||||||
try {
|
|
||||||
PWINDOW->m_closeableSince = Time::steadyNow() + std::chrono::milliseconds(std::stoull(VARS[1]));
|
|
||||||
} catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r->m_rule, e.what()); }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PWINDOW->applyDynamicRule(r);
|
if (PWINDOW->m_ruleApplicator->static_.content)
|
||||||
|
PWINDOW->setContentType(sc<NContentType::eContentType>(PWINDOW->m_ruleApplicator->static_.content.value()));
|
||||||
|
|
||||||
|
if (PWINDOW->m_ruleApplicator->static_.noCloseFor)
|
||||||
|
PWINDOW->m_closeableSince = Time::steadyNow() + std::chrono::milliseconds(PWINDOW->m_ruleApplicator->static_.noCloseFor.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
// make it uncloseable if it's a Hyprland dialog
|
// make it uncloseable if it's a Hyprland dialog
|
||||||
|
|
@ -333,7 +286,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
if (PWINDOW->m_pinned && !PWINDOW->m_isFloating)
|
if (PWINDOW->m_pinned && !PWINDOW->m_isFloating)
|
||||||
PWINDOW->m_pinned = false;
|
PWINDOW->m_pinned = false;
|
||||||
|
|
||||||
CVarList WORKSPACEARGS = CVarList(requestedWorkspace, 0, ' ');
|
CVarList2 WORKSPACEARGS = CVarList2(std::move(requestedWorkspace), 0, ' ', false, false);
|
||||||
|
|
||||||
if (!WORKSPACEARGS[0].empty()) {
|
if (!WORKSPACEARGS[0].empty()) {
|
||||||
WORKSPACEID requestedWorkspaceID;
|
WORKSPACEID requestedWorkspaceID;
|
||||||
|
|
@ -420,138 +373,29 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
|
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
|
||||||
PWINDOW->m_createdOverFullscreen = true;
|
PWINDOW->m_createdOverFullscreen = true;
|
||||||
|
|
||||||
// size and move rules
|
if (!PWINDOW->m_ruleApplicator->static_.size.empty()) {
|
||||||
for (auto const& r : PWINDOW->m_matchedRules) {
|
const auto COMPUTED = PWINDOW->calculateExpression(PWINDOW->m_ruleApplicator->static_.size);
|
||||||
switch (r->m_ruleType) {
|
if (!COMPUTED)
|
||||||
case CWindowRule::RULE_SIZE: {
|
Debug::log(ERR, "failed to parse {} as an expression", PWINDOW->m_ruleApplicator->static_.size);
|
||||||
try {
|
else {
|
||||||
auto stringToFloatClamp = [](const std::string& VALUE, const float CURR, const float REL) {
|
*PWINDOW->m_realSize = *COMPUTED;
|
||||||
if (VALUE.starts_with('<'))
|
|
||||||
return std::min(CURR, stringToPercentage(VALUE.substr(1, VALUE.length() - 1), REL));
|
|
||||||
else if (VALUE.starts_with('>'))
|
|
||||||
return std::max(CURR, stringToPercentage(VALUE.substr(1, VALUE.length() - 1), REL));
|
|
||||||
|
|
||||||
return stringToPercentage(VALUE, REL);
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto VALUE = r->m_rule.substr(r->m_rule.find(' ') + 1);
|
|
||||||
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
|
|
||||||
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
|
|
||||||
|
|
||||||
const auto MAXSIZE = PWINDOW->requestedMaxSize();
|
|
||||||
|
|
||||||
const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->m_size.x) :
|
|
||||||
stringToFloatClamp(SIZEXSTR, PWINDOW->m_realSize->goal().x, PMONITOR->m_size.x);
|
|
||||||
|
|
||||||
const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, PMONITOR->m_size.y) :
|
|
||||||
stringToFloatClamp(SIZEYSTR, PWINDOW->m_realSize->goal().y, PMONITOR->m_size.y);
|
|
||||||
|
|
||||||
Debug::log(LOG, "Rule size, applying to {}", PWINDOW);
|
|
||||||
|
|
||||||
PWINDOW->clampWindowSize(Vector2D{SIZEXSTR.starts_with("<") ? 0 : SIZEX, SIZEYSTR.starts_with("<") ? 0 : SIZEY}, Vector2D{SIZEX, SIZEY});
|
|
||||||
|
|
||||||
PWINDOW->setHidden(false);
|
PWINDOW->setHidden(false);
|
||||||
} catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r->m_rule, r->m_value); }
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CWindowRule::RULE_MOVE: {
|
|
||||||
try {
|
|
||||||
auto value = r->m_rule.substr(r->m_rule.find(' ') + 1);
|
|
||||||
|
|
||||||
const bool ONSCREEN = value.starts_with("onscreen");
|
|
||||||
|
|
||||||
if (ONSCREEN)
|
|
||||||
value = value.substr(value.find_first_of(' ') + 1);
|
|
||||||
|
|
||||||
const bool CURSOR = value.starts_with("cursor");
|
|
||||||
|
|
||||||
if (CURSOR)
|
|
||||||
value = value.substr(value.find_first_of(' ') + 1);
|
|
||||||
|
|
||||||
const auto POSXSTR = value.substr(0, value.find(' '));
|
|
||||||
const auto POSYSTR = value.substr(value.find(' ') + 1);
|
|
||||||
|
|
||||||
int posX = 0;
|
|
||||||
int posY = 0;
|
|
||||||
|
|
||||||
if (POSXSTR.starts_with("100%-")) {
|
|
||||||
const bool subtractWindow = POSXSTR.starts_with("100%-w-");
|
|
||||||
const auto POSXRAW = (subtractWindow) ? POSXSTR.substr(7) : POSXSTR.substr(5);
|
|
||||||
posX =
|
|
||||||
PMONITOR->m_size.x - (!POSXRAW.contains('%') ? std::stoi(POSXRAW) : std::stof(POSXRAW.substr(0, POSXRAW.length() - 1)) * 0.01 * PMONITOR->m_size.x);
|
|
||||||
|
|
||||||
if (subtractWindow)
|
|
||||||
posX -= PWINDOW->m_realSize->goal().x;
|
|
||||||
|
|
||||||
if (CURSOR)
|
|
||||||
Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!");
|
|
||||||
} else if (!CURSOR) {
|
|
||||||
posX = !POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PMONITOR->m_size.x;
|
|
||||||
} else {
|
|
||||||
// cursor
|
|
||||||
if (POSXSTR == "cursor") {
|
|
||||||
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->m_position.x;
|
|
||||||
} else {
|
|
||||||
posX = g_pInputManager->getMouseCoordsInternal().x - PMONITOR->m_position.x +
|
|
||||||
(!POSXSTR.contains('%') ? std::stoi(POSXSTR) : std::stof(POSXSTR.substr(0, POSXSTR.length() - 1)) * 0.01 * PWINDOW->m_realSize->goal().x);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (POSYSTR.starts_with("100%-")) {
|
if (!PWINDOW->m_ruleApplicator->static_.position.empty()) {
|
||||||
const bool subtractWindow = POSYSTR.starts_with("100%-h-");
|
const auto COMPUTED = PWINDOW->calculateExpression(PWINDOW->m_ruleApplicator->static_.position);
|
||||||
const auto POSYRAW = (subtractWindow) ? POSYSTR.substr(7) : POSYSTR.substr(5);
|
if (!COMPUTED)
|
||||||
posY =
|
Debug::log(ERR, "failed to parse {} as an expression", PWINDOW->m_ruleApplicator->static_.position);
|
||||||
PMONITOR->m_size.y - (!POSYRAW.contains('%') ? std::stoi(POSYRAW) : std::stof(POSYRAW.substr(0, POSYRAW.length() - 1)) * 0.01 * PMONITOR->m_size.y);
|
else {
|
||||||
|
*PWINDOW->m_realPosition = *COMPUTED + PMONITOR->m_position;
|
||||||
if (subtractWindow)
|
|
||||||
posY -= PWINDOW->m_realSize->goal().y;
|
|
||||||
|
|
||||||
if (CURSOR)
|
|
||||||
Debug::log(ERR, "Cursor is not compatible with 100%-, ignoring cursor!");
|
|
||||||
} else if (!CURSOR) {
|
|
||||||
posY = !POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PMONITOR->m_size.y;
|
|
||||||
} else {
|
|
||||||
// cursor
|
|
||||||
if (POSYSTR == "cursor") {
|
|
||||||
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->m_position.y;
|
|
||||||
} else {
|
|
||||||
posY = g_pInputManager->getMouseCoordsInternal().y - PMONITOR->m_position.y +
|
|
||||||
(!POSYSTR.contains('%') ? std::stoi(POSYSTR) : std::stof(POSYSTR.substr(0, POSYSTR.length() - 1)) * 0.01 * PWINDOW->m_realSize->goal().y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ONSCREEN) {
|
|
||||||
int borderSize = PWINDOW->getRealBorderSize();
|
|
||||||
|
|
||||||
posX = std::clamp(posX, sc<int>(PMONITOR->m_reservedTopLeft.x + borderSize),
|
|
||||||
std::max(sc<int>(PMONITOR->m_size.x - PMONITOR->m_reservedBottomRight.x - PWINDOW->m_realSize->goal().x - borderSize),
|
|
||||||
sc<int>(PMONITOR->m_reservedTopLeft.x + borderSize + 1)));
|
|
||||||
|
|
||||||
posY = std::clamp(posY, sc<int>(PMONITOR->m_reservedTopLeft.y + borderSize),
|
|
||||||
std::max(sc<int>(PMONITOR->m_size.y - PMONITOR->m_reservedBottomRight.y - PWINDOW->m_realSize->goal().y - borderSize),
|
|
||||||
sc<int>(PMONITOR->m_reservedTopLeft.y + borderSize + 1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug::log(LOG, "Rule move, applying to {}", PWINDOW);
|
|
||||||
|
|
||||||
*PWINDOW->m_realPosition = Vector2D(posX, posY) + PMONITOR->m_position;
|
|
||||||
|
|
||||||
PWINDOW->setHidden(false);
|
PWINDOW->setHidden(false);
|
||||||
} catch (...) { Debug::log(LOG, "Rule move failed, rule: {} -> {}", r->m_rule, r->m_value); }
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case CWindowRule::RULE_CENTER: {
|
}
|
||||||
auto RESERVEDOFFSET = Vector2D();
|
|
||||||
const auto ARGS = CVarList(r->m_rule, 2, ' ');
|
|
||||||
if (ARGS[1] == "1")
|
|
||||||
RESERVEDOFFSET = (PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight) / 2.f;
|
|
||||||
|
|
||||||
|
if (PWINDOW->m_ruleApplicator->static_.center) {
|
||||||
|
auto RESERVEDOFFSET = (PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight) / 2.f;
|
||||||
*PWINDOW->m_realPosition = PMONITOR->middle() - PWINDOW->m_realSize->goal() / 2.f + RESERVEDOFFSET;
|
*PWINDOW->m_realPosition = PMONITOR->middle() - PWINDOW->m_realSize->goal() / 2.f + RESERVEDOFFSET;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the pseudo size to the GOAL of our current size
|
// set the pseudo size to the GOAL of our current size
|
||||||
|
|
@ -564,28 +408,15 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
|
|
||||||
bool setPseudo = false;
|
bool setPseudo = false;
|
||||||
|
|
||||||
for (auto const& r : PWINDOW->m_matchedRules) {
|
if (!PWINDOW->m_ruleApplicator->static_.size.empty()) {
|
||||||
if (r->m_ruleType != CWindowRule::RULE_SIZE)
|
const auto COMPUTED = PWINDOW->calculateExpression(PWINDOW->m_ruleApplicator->static_.size);
|
||||||
continue;
|
if (!COMPUTED)
|
||||||
|
Debug::log(ERR, "failed to parse {} as an expression", PWINDOW->m_ruleApplicator->static_.size);
|
||||||
try {
|
else {
|
||||||
const auto VALUE = r->m_rule.substr(r->m_rule.find(' ') + 1);
|
|
||||||
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
|
|
||||||
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
|
|
||||||
|
|
||||||
const auto MAXSIZE = PWINDOW->requestedMaxSize();
|
|
||||||
|
|
||||||
const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, PMONITOR->m_size.x) : stringToPercentage(SIZEXSTR, PMONITOR->m_size.x);
|
|
||||||
|
|
||||||
const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, PMONITOR->m_size.y) : stringToPercentage(SIZEYSTR, PMONITOR->m_size.y);
|
|
||||||
|
|
||||||
Debug::log(LOG, "Rule size (tiled), applying to {}", PWINDOW);
|
|
||||||
|
|
||||||
setPseudo = true;
|
setPseudo = true;
|
||||||
PWINDOW->m_pseudoSize = Vector2D(SIZEX, SIZEY);
|
PWINDOW->m_pseudoSize = *COMPUTED;
|
||||||
|
|
||||||
PWINDOW->setHidden(false);
|
PWINDOW->setHidden(false);
|
||||||
} catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r->m_rule, r->m_value); }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!setPseudo)
|
if (!setPseudo)
|
||||||
|
|
@ -594,8 +425,8 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
|
|
||||||
const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_lastWindow.lock();
|
const auto PFOCUSEDWINDOWPREV = g_pCompositor->m_lastWindow.lock();
|
||||||
|
|
||||||
if (PWINDOW->m_windowData.allowsInput.valueOrDefault()) { // if default value wasn't set to false getPriority() would throw an exception
|
if (PWINDOW->m_ruleApplicator->allowsInput().valueOrDefault()) { // if default value wasn't set to false getPriority() would throw an exception
|
||||||
PWINDOW->m_windowData.noFocus = CWindowOverridableVar(false, PWINDOW->m_windowData.allowsInput.getPriority());
|
PWINDOW->m_ruleApplicator->noFocusOverride(Desktop::Types::COverridableVar(false, PWINDOW->m_ruleApplicator->allowsInput().getPriority()));
|
||||||
PWINDOW->m_noInitialFocus = false;
|
PWINDOW->m_noInitialFocus = false;
|
||||||
PWINDOW->m_X11ShouldntFocus = false;
|
PWINDOW->m_X11ShouldntFocus = false;
|
||||||
}
|
}
|
||||||
|
|
@ -615,12 +446,12 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
g_pCompositor->setWindowFullscreenInternal(PWINDOW->m_workspace->getFullscreenWindow(), FSMODE_NONE);
|
g_pCompositor->setWindowFullscreenInternal(PWINDOW->m_workspace->getFullscreenWindow(), FSMODE_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PWINDOW->m_windowData.noFocus.valueOrDefault() && !PWINDOW->m_noInitialFocus &&
|
if (!PWINDOW->m_ruleApplicator->noFocus().valueOrDefault() && !PWINDOW->m_noInitialFocus &&
|
||||||
(!PWINDOW->isX11OverrideRedirect() || (PWINDOW->m_isX11 && PWINDOW->m_xwaylandSurface->wantsFocus())) && !workspaceSilent && (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW) &&
|
(!PWINDOW->isX11OverrideRedirect() || (PWINDOW->m_isX11 && PWINDOW->m_xwaylandSurface->wantsFocus())) && !workspaceSilent && (!PFORCEFOCUS || PFORCEFOCUS == PWINDOW) &&
|
||||||
!g_pInputManager->isConstrained()) {
|
!g_pInputManager->isConstrained()) {
|
||||||
g_pCompositor->focusWindow(PWINDOW);
|
g_pCompositor->focusWindow(PWINDOW);
|
||||||
PWINDOW->m_activeInactiveAlpha->setValueAndWarp(*PACTIVEALPHA);
|
PWINDOW->m_activeInactiveAlpha->setValueAndWarp(*PACTIVEALPHA);
|
||||||
PWINDOW->m_dimPercent->setValueAndWarp(PWINDOW->m_windowData.noDim.valueOrDefault() ? 0.f : *PDIMSTRENGTH);
|
PWINDOW->m_dimPercent->setValueAndWarp(PWINDOW->m_ruleApplicator->noDim().valueOrDefault() ? 0.f : *PDIMSTRENGTH);
|
||||||
} else {
|
} else {
|
||||||
PWINDOW->m_activeInactiveAlpha->setValueAndWarp(*PINACTIVEALPHA);
|
PWINDOW->m_activeInactiveAlpha->setValueAndWarp(*PINACTIVEALPHA);
|
||||||
PWINDOW->m_dimPercent->setValueAndWarp(0);
|
PWINDOW->m_dimPercent->setValueAndWarp(0);
|
||||||
|
|
@ -639,9 +470,9 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
PWINDOW->m_realPosition->warp();
|
PWINDOW->m_realPosition->warp();
|
||||||
PWINDOW->m_realSize->warp();
|
PWINDOW->m_realSize->warp();
|
||||||
if (requestedFSState.has_value()) {
|
if (requestedFSState.has_value()) {
|
||||||
PWINDOW->m_windowData.syncFullscreen = CWindowOverridableVar(false, PRIORITY_WINDOW_RULE);
|
PWINDOW->m_ruleApplicator->syncFullscreenOverride(Desktop::Types::COverridableVar(false, Desktop::Types::PRIORITY_WINDOW_RULE));
|
||||||
g_pCompositor->setWindowFullscreenState(PWINDOW, requestedFSState.value());
|
g_pCompositor->setWindowFullscreenState(PWINDOW, requestedFSState.value());
|
||||||
} else if (requestedInternalFSMode.has_value() && requestedClientFSMode.has_value() && !PWINDOW->m_windowData.syncFullscreen.valueOrDefault())
|
} else if (requestedInternalFSMode.has_value() && requestedClientFSMode.has_value() && !PWINDOW->m_ruleApplicator->syncFullscreen().valueOrDefault())
|
||||||
g_pCompositor->setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = requestedInternalFSMode.value(), .client = requestedClientFSMode.value()});
|
g_pCompositor->setWindowFullscreenState(PWINDOW, SFullscreenState{.internal = requestedInternalFSMode.value(), .client = requestedClientFSMode.value()});
|
||||||
else if (requestedInternalFSMode.has_value())
|
else if (requestedInternalFSMode.has_value())
|
||||||
g_pCompositor->setWindowFullscreenInternal(PWINDOW, requestedInternalFSMode.value());
|
g_pCompositor->setWindowFullscreenInternal(PWINDOW, requestedInternalFSMode.value());
|
||||||
|
|
@ -653,6 +484,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
g_pInputManager->recheckIdleInhibitorStatus();
|
g_pInputManager->recheckIdleInhibitorStatus();
|
||||||
|
|
||||||
PWINDOW->updateToplevel();
|
PWINDOW->updateToplevel();
|
||||||
|
PWINDOW->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_ALL);
|
||||||
|
|
||||||
if (workspaceSilent) {
|
if (workspaceSilent) {
|
||||||
if (validMapped(PFOCUSEDWINDOWPREV)) {
|
if (validMapped(PFOCUSEDWINDOWPREV)) {
|
||||||
|
|
@ -689,7 +521,7 @@ void Events::listener_mapWindow(void* owner, void* data) {
|
||||||
PWINDOW->m_realSize->setCallbackOnEnd(setVector2DAnimToMove);
|
PWINDOW->m_realSize->setCallbackOnEnd(setVector2DAnimToMove);
|
||||||
|
|
||||||
// recalc the values for this window
|
// recalc the values for this window
|
||||||
g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW);
|
PWINDOW->updateDecorationValues();
|
||||||
// avoid this window being visible
|
// avoid this window being visible
|
||||||
if (PWORKSPACE->m_hasFullscreenWindow && !PWINDOW->isFullscreen() && !PWINDOW->m_isFloating)
|
if (PWORKSPACE->m_hasFullscreenWindow && !PWINDOW->isFullscreen() && !PWINDOW->m_isFloating)
|
||||||
PWINDOW->m_alpha->setValueAndWarp(0.f);
|
PWINDOW->m_alpha->setValueAndWarp(0.f);
|
||||||
|
|
@ -736,8 +568,7 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
||||||
g_pEventManager->postEvent(SHyprIPCEvent{"closewindow", std::format("{:x}", PWINDOW)});
|
g_pEventManager->postEvent(SHyprIPCEvent{"closewindow", std::format("{:x}", PWINDOW)});
|
||||||
EMIT_HOOK_EVENT("closeWindow", PWINDOW);
|
EMIT_HOOK_EVENT("closeWindow", PWINDOW);
|
||||||
|
|
||||||
if (PWINDOW->m_isFloating && !PWINDOW->m_isX11 &&
|
if (PWINDOW->m_isFloating && !PWINDOW->m_isX11 && PWINDOW->m_ruleApplicator->persistentSize().valueOrDefault()) {
|
||||||
std::ranges::any_of(PWINDOW->m_matchedRules, [](const auto& r) { return r->m_ruleType == CWindowRule::RULE_PERSISTENTSIZE; })) {
|
|
||||||
Debug::log(LOG, "storing floating size {}x{} for window {}::{} on close", PWINDOW->m_realSize->value().x, PWINDOW->m_realSize->value().y, PWINDOW->m_class,
|
Debug::log(LOG, "storing floating size {}x{} for window {}::{} on close", PWINDOW->m_realSize->value().x, PWINDOW->m_realSize->value().y, PWINDOW->m_class,
|
||||||
PWINDOW->m_title);
|
PWINDOW->m_title);
|
||||||
g_pConfigManager->storeFloatingSize(PWINDOW, PWINDOW->m_realSize->value());
|
g_pConfigManager->storeFloatingSize(PWINDOW, PWINDOW->m_realSize->value());
|
||||||
|
|
|
||||||
|
|
@ -975,3 +975,13 @@ std::string getBuiltSystemLibraryNames() {
|
||||||
result += std::format("Aquamarine: built against {}, system has {}\n", AQUAMARINE_VERSION, getSystemLibraryVersion("aquamarine"));
|
result += std::format("Aquamarine: built against {}, system has {}\n", AQUAMARINE_VERSION, getSystemLibraryVersion("aquamarine"));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool truthy(const std::string& str) {
|
||||||
|
if (str == "1")
|
||||||
|
return true;
|
||||||
|
|
||||||
|
std::string cpy = str;
|
||||||
|
std::ranges::transform(cpy, cpy.begin(), ::tolower);
|
||||||
|
|
||||||
|
return cpy.starts_with("true") || cpy.starts_with("yes") || cpy.starts_with("on");
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ std::expected<std::string, std::string> binaryNameForPid(pid_t pid);
|
||||||
std::string deviceNameToInternalString(std::string in);
|
std::string deviceNameToInternalString(std::string in);
|
||||||
std::string getSystemLibraryVersion(const std::string& name);
|
std::string getSystemLibraryVersion(const std::string& name);
|
||||||
std::string getBuiltSystemLibraryNames();
|
std::string getBuiltSystemLibraryNames();
|
||||||
|
bool truthy(const std::string& str);
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
[[deprecated("use std::format instead")]] std::string getFormat(std::format_string<Args...> fmt, Args&&... args) {
|
[[deprecated("use std::format instead")]] std::string getFormat(std::format_string<Args...> fmt, Args&&... args) {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
#include "../managers/animation/DesktopAnimationManager.hpp"
|
#include "../managers/animation/DesktopAnimationManager.hpp"
|
||||||
#include "../managers/input/InputManager.hpp"
|
#include "../managers/input/InputManager.hpp"
|
||||||
#include "../hyprerror/HyprError.hpp"
|
#include "../hyprerror/HyprError.hpp"
|
||||||
|
#include "../i18n/Engine.hpp"
|
||||||
#include "sync/SyncTimeline.hpp"
|
#include "sync/SyncTimeline.hpp"
|
||||||
#include "time/Time.hpp"
|
#include "time/Time.hpp"
|
||||||
#include "../desktop/LayerSurface.hpp"
|
#include "../desktop/LayerSurface.hpp"
|
||||||
|
|
@ -176,6 +177,10 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
m_forceSize = SIZE;
|
m_forceSize = SIZE;
|
||||||
|
|
||||||
SMonitorRule rule = m_activeMonitorRule;
|
SMonitorRule rule = m_activeMonitorRule;
|
||||||
|
|
||||||
|
if (SIZE == rule.resolution)
|
||||||
|
return;
|
||||||
|
|
||||||
rule.resolution = SIZE;
|
rule.resolution = SIZE;
|
||||||
|
|
||||||
applyMonitorRule(&rule);
|
applyMonitorRule(&rule);
|
||||||
|
|
@ -811,8 +816,8 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) {
|
||||||
if (!m_state.test())
|
if (!m_state.test())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto errorMessage =
|
auto errorMessage = I18n::i18nEngine()->localize(I18n::TXT_KEY_NOTIF_MONITOR_MODE_FAIL,
|
||||||
std::format("Monitor {} failed to set any requested modes, falling back to mode {:X0}@{:.2f}Hz", m_name, mode->pixelSize, mode->refreshRate / 1000.f);
|
{{"name", m_name}, {"mode", std::format("{:X0}@{:.2f}Hz", mode->pixelSize, mode->refreshRate / 1000.f)}});
|
||||||
Debug::log(WARN, errorMessage);
|
Debug::log(WARN, errorMessage);
|
||||||
g_pHyprNotificationOverlay->addNotification(errorMessage, CHyprColor(0xff0000ff), 5000, ICON_WARNING);
|
g_pHyprNotificationOverlay->addNotification(errorMessage, CHyprColor(0xff0000ff), 5000, ICON_WARNING);
|
||||||
|
|
||||||
|
|
@ -939,7 +944,9 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) {
|
||||||
Debug::log(ERR, "Invalid scale passed to monitor, {} found suggestion {}", m_scale, searchScale);
|
Debug::log(ERR, "Invalid scale passed to monitor, {} found suggestion {}", m_scale, searchScale);
|
||||||
static auto PDISABLENOTIFICATION = CConfigValue<Hyprlang::INT>("misc:disable_scale_notification");
|
static auto PDISABLENOTIFICATION = CConfigValue<Hyprlang::INT>("misc:disable_scale_notification");
|
||||||
if (!*PDISABLENOTIFICATION)
|
if (!*PDISABLENOTIFICATION)
|
||||||
g_pHyprNotificationOverlay->addNotification(std::format("Invalid scale passed to monitor: {}, using suggested scale: {}", m_scale, searchScale),
|
g_pHyprNotificationOverlay->addNotification(
|
||||||
|
I18n::i18nEngine()->localize(I18n::TXT_KEY_NOTIF_MONITOR_AUTO_SCALE,
|
||||||
|
{{"name", m_name}, {"scale", std::format("{:.2f}", m_scale)}, {"fixed_scale", std::format("{:.2f}", searchScale)}}),
|
||||||
CHyprColor(1.0, 0.0, 0.0, 1.0), 5000, ICON_WARNING);
|
CHyprColor(1.0, 0.0, 0.0, 1.0), 5000, ICON_WARNING);
|
||||||
}
|
}
|
||||||
m_scale = searchScale;
|
m_scale = searchScale;
|
||||||
|
|
@ -1509,6 +1516,10 @@ CBox CMonitor::logicalBox() {
|
||||||
return {m_position, m_size};
|
return {m_position, m_size};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CBox CMonitor::logicalBoxMinusExtents() {
|
||||||
|
return {m_position + m_reservedTopLeft, m_size - m_reservedTopLeft - m_reservedBottomRight};
|
||||||
|
}
|
||||||
|
|
||||||
void CMonitor::scheduleDone() {
|
void CMonitor::scheduleDone() {
|
||||||
if (m_doneScheduled)
|
if (m_doneScheduled)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -298,6 +298,7 @@ class CMonitor {
|
||||||
WORKSPACEID activeWorkspaceID();
|
WORKSPACEID activeWorkspaceID();
|
||||||
WORKSPACEID activeSpecialWorkspaceID();
|
WORKSPACEID activeSpecialWorkspaceID();
|
||||||
CBox logicalBox();
|
CBox logicalBox();
|
||||||
|
CBox logicalBoxMinusExtents();
|
||||||
void scheduleDone();
|
void scheduleDone();
|
||||||
uint32_t isSolitaryBlocked(bool full = false);
|
uint32_t isSolitaryBlocked(bool full = false);
|
||||||
void recheckSolitary();
|
void recheckSolitary();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include "TagKeeper.hpp"
|
#include "TagKeeper.hpp"
|
||||||
|
|
||||||
bool CTagKeeper::isTagged(const std::string& tag, bool strict) {
|
bool CTagKeeper::isTagged(const std::string& tag, bool strict) const {
|
||||||
const bool NEGATIVE = tag.starts_with("negative");
|
const bool NEGATIVE = tag.starts_with("negative");
|
||||||
const auto MATCH = NEGATIVE ? tag.substr(9) : tag;
|
const auto MATCH = NEGATIVE ? tag.substr(9) : tag;
|
||||||
const bool TAGGED = m_tags.contains(MATCH) || (!strict && m_tags.contains(MATCH + "*"));
|
const bool TAGGED = m_tags.contains(MATCH) || (!strict && m_tags.contains(MATCH + "*"));
|
||||||
|
|
@ -38,6 +38,6 @@ bool CTagKeeper::applyTag(const std::string& tag, bool dynamic) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CTagKeeper::removeDynamicTags() {
|
bool CTagKeeper::removeDynamicTag(const std::string& s) {
|
||||||
return std::erase_if(m_tags, [](const auto& tag) { return tag.ends_with("*"); });
|
return std::erase_if(m_tags, [&s](const auto& tag) { return tag == s + "*"; });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@
|
||||||
|
|
||||||
class CTagKeeper {
|
class CTagKeeper {
|
||||||
public:
|
public:
|
||||||
bool isTagged(const std::string& tag, bool strict = false);
|
bool isTagged(const std::string& tag, bool strict = false) const;
|
||||||
bool applyTag(const std::string& tag, bool dynamic = false);
|
bool applyTag(const std::string& tag, bool dynamic = false);
|
||||||
bool removeDynamicTags();
|
bool removeDynamicTag(const std::string& tag);
|
||||||
|
|
||||||
const auto& getTags() const {
|
const auto& getTags() const {
|
||||||
return m_tags;
|
return m_tags;
|
||||||
|
|
|
||||||
22
src/helpers/math/Expression.cpp
Normal file
22
src/helpers/math/Expression.cpp
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
#include "Expression.hpp"
|
||||||
|
#include "muParser.h"
|
||||||
|
#include "../../debug/Log.hpp"
|
||||||
|
|
||||||
|
using namespace Math;
|
||||||
|
|
||||||
|
CExpression::CExpression() : m_parser(makeUnique<mu::Parser>()) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CExpression::addVariable(const std::string& name, double val) {
|
||||||
|
m_parser->DefineConst(name, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<double> CExpression::compute(const std::string& expr) {
|
||||||
|
try {
|
||||||
|
m_parser->SetExpr(expr);
|
||||||
|
return m_parser->Eval();
|
||||||
|
} catch (mu::Parser::exception_type& e) { Debug::log(ERR, "CExpression::compute: mu threw: {}", e.GetMsg()); }
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
28
src/helpers/math/Expression.hpp
Normal file
28
src/helpers/math/Expression.hpp
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../memory/Memory.hpp"
|
||||||
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace mu {
|
||||||
|
class Parser;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Math {
|
||||||
|
class CExpression {
|
||||||
|
public:
|
||||||
|
CExpression();
|
||||||
|
~CExpression() = default;
|
||||||
|
|
||||||
|
CExpression(const CExpression&) = delete;
|
||||||
|
CExpression(CExpression&) = delete;
|
||||||
|
CExpression(CExpression&&) = delete;
|
||||||
|
|
||||||
|
void addVariable(const std::string& name, double val);
|
||||||
|
|
||||||
|
std::optional<double> compute(const std::string& expr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
UP<mu::Parser> m_parser;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <hyprutils/string/VarList.hpp>
|
#include <hyprutils/string/VarList.hpp>
|
||||||
|
#include <hyprutils/string/VarList2.hpp>
|
||||||
|
|
||||||
//NOLINTNEXTLINE
|
//NOLINTNEXTLINE
|
||||||
using namespace Hyprutils::String;
|
using namespace Hyprutils::String;
|
||||||
|
|
|
||||||
988
src/i18n/Engine.cpp
Normal file
988
src/i18n/Engine.cpp
Normal file
|
|
@ -0,0 +1,988 @@
|
||||||
|
#include "Engine.hpp"
|
||||||
|
|
||||||
|
#include <hyprutils/i18n/I18nEngine.hpp>
|
||||||
|
|
||||||
|
using namespace I18n;
|
||||||
|
using namespace Hyprutils::I18n;
|
||||||
|
|
||||||
|
static SP<Hyprutils::I18n::CI18nEngine> huEngine;
|
||||||
|
static std::string localeStr;
|
||||||
|
|
||||||
|
//
|
||||||
|
SP<I18n::CI18nEngine> I18n::i18nEngine() {
|
||||||
|
static SP<I18n::CI18nEngine> engine = makeShared<I18n::CI18nEngine>();
|
||||||
|
return engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
I18n::CI18nEngine::CI18nEngine() {
|
||||||
|
huEngine = makeShared<Hyprutils::I18n::CI18nEngine>();
|
||||||
|
huEngine->setFallbackLocale("en_US");
|
||||||
|
localeStr = huEngine->getSystemLocale().locale();
|
||||||
|
|
||||||
|
// be_BY (Belarusian)
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_ANR_TITLE, "Праграма не адказвае");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_ANR_CONTENT, "Праграма {title} - {class} не адказвае.\nШто хочаце з ёй зрабіць?");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_ANR_OPTION_TERMINATE, "Прымусова спыніць");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_ANR_OPTION_WAIT, "Пачакаць");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_ANR_PROP_UNKNOWN, "(невядома)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "Праграма <b>{app}</b> запытвае невядомы дазвол.");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "Праграма <b>{app}</b> спрабуе здымаць экран.\n\nЦі хочаце дазволіць?");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "Праграма <b>{app}</b> спрабуе загрузіць плагін: <b>{plugin}</b>.\n\nХочаце дазволіць?");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "Выяўленая новая клавіятура: <b>{keyboard}</b>.\n\nХочаце дазволіць яе выкарыстанне?");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(невядома)");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_PERMISSION_TITLE, "Запыт дазволу");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "Падказка: вы можаце задаць пастаянныя правілы для гэтага ў файле канфігурацыі Hyprland.");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_PERMISSION_ALLOW, "Дазволіць");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "Дазволіць і запомніць");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_PERMISSION_ALLOW_ONCE, "Дазволіць аднойчы");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_PERMISSION_DENY, "Забараніць");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "Невядомая праграма (Ідэнтыфікатар кліента wayland {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"Выглядае, што вашая пераменная асяроддзя XDG_CURRENT_DESKTOP зададзеная звонку, цяперашняе значэнне: {value}.\nГэта можа выклікаць праблемы, калі "
|
||||||
|
"гэта не зроблена наўмысна.");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"У вашай сістэме не ўсталяваны hyprland-guiutils, што выкарыстоўваецца для некаторых дыялогавых вокнаў. Разгледзьце ўсталёўку пакета.");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_NOTIF_FAILED_ASSETS, [](const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
int assetsNo = std::stoi(vars.at("count"));
|
||||||
|
if (assetsNo <= 1)
|
||||||
|
return "Hyprland не змог загрузіць {count} важны рэсурс, вінавацьце ў гэтым адказнага за зборку пакетаў для свайго дыстрыбутыва!";
|
||||||
|
return "Hyprland не змог загрузіць {count} важных рэсурсаў, вінавацьце ў гэтым адказнага за зборку пакетаў для свайго дыстрыбутыва!";
|
||||||
|
});
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"Макет манітораў наладжаны некарэктна. Манітор {name} накладаецца на іншы(я) манітор(ы).\nДля падрабязнасцей звярніцеся да Wiki (Старонка Monitors). "
|
||||||
|
"Гэта <b>абавязкова</b> створыць праблемы.");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "Манітор {name} не змог наладзіць ніводны з запатрабаваных рэжымаў, аварыйна ўжыты рэжым {mode}.");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE, "Няверна зададзены маштаб для манітора {name}: {scale}, ужываецца прапанаваны маштаб: {fixed_scale}");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "Не атрымалася загрузіць плагін {name}: {error}");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "Не атрымалася перазагрузіць шэйдар CM, аварыйна ўжываецца rgba/rgbx.");
|
||||||
|
huEngine->registerEntry("be_BY", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "Манітор {name}: пашыраны каляровы дыяпазон уключаны, але экран не ў рэжыме 10-біт.");
|
||||||
|
|
||||||
|
// en_US (English)
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_ANR_TITLE, "Application Not Responding");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_ANR_CONTENT, "An application {title} - {class} is not responding.\nWhat do you want to do with it?");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_ANR_OPTION_TERMINATE, "Terminate");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_ANR_OPTION_WAIT, "Wait");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_ANR_PROP_UNKNOWN, "(unknown)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "An application <b>{app}</b> is requesting an unknown permission.");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "An application <b>{app}</b> is trying to capture your screen.\n\nDo you want to allow it to?");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "An application <b>{app}</b> is trying to load a plugin: <b>{plugin}</b>.\n\nDo you want to allow it to?");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "A new keyboard has been detected: <b>{keyboard}</b>.\n\nDo you want to allow it to operate?");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(unknown)");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_TITLE, "Permission request");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "Hint: you can set persistent rules for these in the Hyprland config file.");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_ALLOW, "Allow");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "Allow and remember");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_ALLOW_ONCE, "Allow once");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_DENY, "Deny");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "Unknown application (wayland client ID {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"en_US", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"Your XDG_CURRENT_DESKTOP environment seems to be managed externally, and the current value is {value}.\nThis might cause issues unless it's intentional.");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"Your system does not have hyprland-guiutils installed. This is a runtime dependency for some dialogs. Consider installing it.");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_NOTIF_FAILED_ASSETS, [](const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
int assetsNo = std::stoi(vars.at("count"));
|
||||||
|
if (assetsNo <= 1)
|
||||||
|
return "Hyprland failed to load {count} essential asset, blame your distro's packager for doing a bad job at packaging!";
|
||||||
|
return "Hyprland failed to load {count} essential assets, blame your distro's packager for doing a bad job at packaging!";
|
||||||
|
});
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"Your monitor layout is set up incorrectly. Monitor {name} overlaps with other monitor(s) in the layout.\nPlease see the wiki (Monitors page) for "
|
||||||
|
"more. This <b>will</b> cause issues.");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "Monitor {name} failed to set any requested modes, falling back to mode {mode}.");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE, "Invalid scale passed to monitor {name}: {scale}, using suggested scale: {fixed_scale}");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "Failed to load plugin {name}: {error}");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "CM shader reload failed, falling back to rgba/rgbx.");
|
||||||
|
huEngine->registerEntry("en_US", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "Monitor {name}: wide color gamut is enabled but the display is not in 10-bit mode.");
|
||||||
|
|
||||||
|
// as_IN (Assamese)
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_ANR_TITLE, "এপ্লিকেচনে উত্তৰ দিয়া নাই");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_ANR_CONTENT, "এপ্লিকেচন {title} - {class}-এ উত্তৰ দিয়া নাই।\nআপুনি এয়াৰ লগত কি কৰিব বিচাৰে?");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_ANR_OPTION_TERMINATE, "সমাপ্ত কৰক");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_ANR_OPTION_WAIT, "অপেক্ষা কৰক");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_ANR_PROP_UNKNOWN, "(অজ্ঞাত)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "এপ্লিকেচন <b>{app}</b>-এ এটা অজ্ঞাত অনুমতি বিচাৰিছে।");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "এটা এপ্লিকেচন <b>{app}</b>-এ আপোনাৰ স্ক্ৰীণ কেপচাৰ কৰিবলৈ চেষ্টা কৰিছে।\n\nআপুনি ইয়াক অনুমতি দিব বিচাৰেনে?");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_PERMISSION_REQUEST_PLUGIN,
|
||||||
|
"এপ্লিকেচন <b>{app}</b>-এ এটা প্লাগিন লোড কৰিবলৈ চেষ্টা কৰিছে: <b>{plugin}</b>।\n\nআপুনি ইয়াক অনুমতি দিব বিচাৰেনে?");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "এটা নতুন কিবৰ্ড ধৰা পৰিছে: <b>{keyboard}</b>।\n\nআপুনি ইয়াক চলাবলৈ অনুমতি দিব বিচাৰেনে?");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(অজ্ঞাত)");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_PERMISSION_TITLE, "অনুমতিৰ অনুৰোধ");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "ইঙ্গিত: আপুনি হাইপাৰলেণ্ড কনফিগ ফাইলত এইবোৰৰ বাবে স্থায়ী নিয়ম স্থাপন কৰিব পাৰে।");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_PERMISSION_ALLOW, "অনুমতি দিয়ক");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "অনুমতি দি মনত ৰাখক");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_PERMISSION_ALLOW_ONCE, "এবাৰ অনুমতি দিয়ক");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_PERMISSION_DENY, "অস্বীকাৰ কৰক");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "অজ্ঞাত এপ্লিকেচন (ৱেইলেণ্ড ক্লায়েণ্ট আইডি {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"as_IN", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"আপোনাৰ XDG_CURRENT_DESKTOP পৰিৱেশটো বাহ্যিকভাৱে পৰিচালিত হোৱা যেন লাগিছে, আৰু বৰ্তমানৰ মান হৈছে {value}।\nযদি ই ইচ্ছাকৃতভাৱে নহয়, তেনে হলে সমস্যাৰ সৃষ্টি হ'ব পাৰে।");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"আপোনাৰ চিষ্টেমত hyprland-guiutils ইনষ্টল কৰা নাই। কিছুমান ডাইলগৰ বাবে ই এটা ৰানটাইম নিৰ্ভৰশীলতা। ইয়াক ইনষ্টল কৰাৰ কথা চিন্তা কৰক।");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_NOTIF_FAILED_ASSETS,
|
||||||
|
"হাইপাৰলেণ্ড {count}-টা প্ৰয়োজনীয় সম্পদ লোড কৰাত অসফল হৈছে, বেয়া পেকজিং কৰাৰ বাবে আপোনাৰ ডিষ্ট্ৰ'ৰ পেকেজাৰক দোষাৰোপ কৰক!");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"আপোনাৰ মনিটৰৰ লেআউট ভুলকৈ ছেট কৰা হৈছে। মনিটৰ {name} লেআউটত আন মনিটৰ(সমূহ)ৰ সৈতে ওপৰা-উপৰি হৈ আছে।\nঅধিক তথ্যৰ বাবে অনুগ্ৰহ কৰি ৱিকি (মনিটৰ পৃষ্ঠা) চাওক। ই "
|
||||||
|
"<b>সমস্যাৰ</b> সৃষ্টি কৰিব।");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "মনিটৰ {name}-এ কোনো অনুৰোধ কৰা মোড ছেট কৰাত অসফল হৈছে, মোড {mode}-লৈ ঘূৰি আহিছে।");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE, "মনিটৰ {name}: {scale}-লৈ অবৈধ মাপন দিয়া হৈছে, পৰামৰ্শ দিয়া মাপন ব্যৱহাৰ কৰা যাব: {fixed_scale}");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "প্লাগিন {name} লোড কৰাত অসফল হৈছে: {error}");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "CM শ্বেডাৰ ৰিলোড কৰাত অসফল হৈছে, rgba/rgbx-লৈ ঘূৰি আহিছে।");
|
||||||
|
huEngine->registerEntry("as_IN", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "প্ৰসাৰিত ৰঙৰ বৰ্গ সক্ষম কৰা হৈছে কিন্তু ডিচপ্লে 10-বিট মোডত নাই।");
|
||||||
|
|
||||||
|
// de_DE (German)
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_ANR_TITLE, "Anwendung Reagiert Nicht");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_ANR_CONTENT, "Eine Anwendung {title} - {class} reagiert nicht.\nWas möchten Sie damit tun?");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_ANR_OPTION_TERMINATE, "Beenden");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_ANR_OPTION_WAIT, "Warten");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_ANR_PROP_UNKNOWN, "(unbekannt)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "Eine Anwendung <b>{app}</b> fordert eine unbekannte Berechtigung an.");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "Eine Anwendung <b>{app}</b> versucht Ihren Bildschrim aufzunehmen.\n\nMöchten Sie dies erlauben?");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "Eine Anwendung <b>{app}</b> versucht ein Plugin zu laden: <b>{plugin}</b>.\n\nMöchten Sie dies erlauben?");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "Eine neue Tastatur wurde erkannt: <b>{keyboard}</b>.\n\nMöchten Sie diese in Betrieb nehmen?");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(unbekannt)");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_PERMISSION_TITLE, "Berechtigungsanfrage");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "Tip: Sie können dafür permanente Regeln in der Hyprland-Konfigurationsdatei festlegen.");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_PERMISSION_ALLOW, "Erlauben");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "Erlauben und merken");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_PERMISSION_ALLOW_ONCE, "Einmal erlauben");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_PERMISSION_DENY, "Verweigern");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "Unbekannte Anwendung (wayland client ID {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"Ihre XDG_CURRENT_DESKTOP umgebung scheint extern gemanagt zu werden, und der aktuelle Wert ist {value}.\nDies könnte zu Problemen führen sofern es "
|
||||||
|
"nicht absichtlich so ist.");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"Ihr System hat hyprland-guiutils nicht installiert. Dies ist eine Laufzeitabhängigkeit für einige Dialoge. Es ist empfohlen diese zu installieren.");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_NOTIF_FAILED_ASSETS, [](const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
int assetsNo = std::stoi(vars.at("count"));
|
||||||
|
if (assetsNo <= 1)
|
||||||
|
return "Hyprland konnte {count} essentielle Ressource nicht laden, geben Sie dem Packager ihrer Distribution die Schuld für ein schlechtes Package!";
|
||||||
|
return "Hyprland konnte {count} essentielle Ressroucen nicht laden, geben Sie dem Packager ihrer Distribution die Schuld für ein schlechtes Package!";
|
||||||
|
});
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"de_DE", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"Ihr Bildschirmlayout ist fehlerhaft aufgesetzt. Der Bildschirm {name} überlappt mit anderen Bildschirm(en) im Layout.\nBitte siehe im Wiki (Monitors Seite) für "
|
||||||
|
"mehr Informationen. Dies <b>wird</b> zu Problemen führen.");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "Bildschirm {name} konnte keinen der angeforderten Modi setzen fällt auf den Modus {mode} zurück.");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE,
|
||||||
|
"Ungültiger Skalierungsfaktor {scale} für Bildschirm {name}, es wird der empfohlene Faktor {fixed_scale} verwendet.");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "Plugin {name} konnte nicht geladen werden: {error}");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "CM shader konnte nicht neu geladen werden und es wird auf rgba/rgbx zurückgefallen.");
|
||||||
|
huEngine->registerEntry("de_DE", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "Bildschirm {name}: wide color gamut ist aktiviert aber der Bildschirm ist nicht im 10-bit Modus.");
|
||||||
|
|
||||||
|
// de_CH (Swiss German)
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_ANR_TITLE, "Aawändig Reagiert Ned");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_ANR_CONTENT, "En Aawändig {title} - {class} reagiert ned.\nWas wend Sie demet mache?");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_ANR_OPTION_TERMINATE, "Beände");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_ANR_OPTION_WAIT, "Warte");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_ANR_PROP_UNKNOWN, "(onbekannt)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "En Aawändig <b>{app}</b> fordert en onbekannti Berächtigong aa.");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "En Aawändig <b>{app}</b> versuecht Ehre Beldscherm uufznäh.\n\nWend Sie das erlaube?");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "En Aawändig <b>{app}</b> versuecht es Plugin z'lade: <b>{plugin}</b>.\n\nWend Sie das erlaube?");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "En neui Tastatur esch erkönne worde: <b>{keyboard}</b>.\n\nWend sie die in Betreb nä?");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(onbekannt)");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_PERMISSION_TITLE, "Berächtigongsaafrog");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "Tip: Sie chönd permanenti Regle deför i ehrere Hyprland-Konfigurationsdatei festlegge.");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_PERMISSION_ALLOW, "Erlaube");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "Erlaube ond merke");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_PERMISSION_ALLOW_ONCE, "Einisch erlaube");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_PERMISSION_DENY, "Verweigere");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "Onbekannti Aawändig (wayland client ID {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"de_CH", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"Ehri XDG_CURRENT_DESKTOP omgäbig schiint extern gmanagt z'wärde, ond de aktuelli Wärt esch {value}.\nDas chönnt zo Problem füehre sofärn das ned absechtlech so esch.");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"Ehres System hed hyprland-guiutils ned installiert. Das esch en Laufziitabhängigkeit för es paar Dialog. Es werd empfohle sie z'installiere.");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_NOTIF_FAILED_ASSETS,
|
||||||
|
"Hyprland hed {count} essentielli Ressource ned chönne lade, gäbed Sie im Packager vo ehrere Distribution schold för es schlächts Package!");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"Ehres Beldschermlayout esch fählerhaft uufgsetzt. De Beldscherm {name} öberlappt met andere Beldscherm(e) im Layout.\nBitte lueged sie im Wiki "
|
||||||
|
"(Monitors Siite) för meh Informatione. Das <b>werd</b> zo Problem füehre.");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "De Beldscherm {name} hed keine vode aagforderete Modi chönne setze, ond fallt uf de Modus {mode} zrogg.");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE,
|
||||||
|
"Ongöltige Skalierigsfaktor {scale} för de Beldscherm {name}, es werd de empfohleni Faktor {fixed_scale} verwändet.");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "S Plugin {name} hed ned chönne glade wärde: {error}");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "CM shader hed ned chönne neu glade wärde, es werd uf rgba/rgbx zrogggfalle.");
|
||||||
|
huEngine->registerEntry("de_CH", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "Beldscherm {name}: wide color gamut esch aktiviert aber de Beldscherm esch ned im 10-bit Modus.");
|
||||||
|
|
||||||
|
// pt_BR (Brazilian Portuguese)
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_ANR_TITLE, "O aplicativo não está respondendo");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_ANR_CONTENT, "O aplicativo {title} - {class} não está respondendo.\nO que você deseja fazer?");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_ANR_OPTION_TERMINATE, "Encerrar");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_ANR_OPTION_WAIT, "Esperar");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_ANR_PROP_UNKNOWN, "(Desconhecido)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "O aplicativo <b>{app}</b> está pedindo uma permissão desconhecida.");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "O aplicativo <b>{app}</b> está tentando capturar sua tela.\n\nVocê deseja permitir?");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "O aplicativo <b>{app}</b> está tentando carregar um plugin: <b>{plugin}</b>.\n\nVocê deseja permitir?");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "Um novo teclado foi detectado: <b>{keyboard}</b>.\n\nVocê deseja permitir seu uso?");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(Desconhecido)");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_PERMISSION_TITLE, "Solicitação de permissão");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_PERMISSION_PERSISTENCE_HINT,
|
||||||
|
"Dica: você pode definir regras persistentes para essas permissões no arquivo de configuração do Hyprland");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_PERMISSION_ALLOW, "Permitir");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "Permitir e lembrar");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_PERMISSION_ALLOW_ONCE, "Permitir uma vez");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_PERMISSION_DENY, "Negar");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "Aplicativo desconhecido (wayland client ID {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"Seu XDG_CURRENT_DESKTOP parece estar sendo gerenciado externamente, e atualmente é {value}.\nIsso pode causar problemas caso não seja intencional.");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"Seu sistema não possui hyprland-guiutils instalado. Essa é uma dependência de execução para alguns diálogos. Considere instalá-lo.");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_NOTIF_FAILED_ASSETS, [](const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
int assetsNo = std::stoi(vars.at("count"));
|
||||||
|
if (assetsNo <= 1)
|
||||||
|
return "O Hyprland falhou ao carregar {count} recurso essencial, culpe o empacotador da sua distro por fazer um péssimo trabalho!";
|
||||||
|
return "O Hyprland falhou ao carregar {count} recursos essenciais, culpe o empacotador da sua distro por fazer um péssimo trabalho!";
|
||||||
|
});
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"Sua disposição de monitores está configurada incorretamente. O monitor {name} se sobrepõe a outro(s) monitor(es) na disposição.\nPor favor consulte "
|
||||||
|
"a wiki (Monitors page) para "
|
||||||
|
"mais informações. Isso <b>vai</b> causar problemas.");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "O monitor {name} falhou em definir qualquer um dos modos solicitados, voltando ao modo {mode}.");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE,
|
||||||
|
"Um fator de escala inválido foi passado para o monitor {name}: {scale}, usando o fator sugerido: {fixed_scale}");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "Falha ao carregar o plugin {name}: {error}");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "Falha ao carregar o shader CM, voltando para rgba/rgbx.");
|
||||||
|
huEngine->registerEntry("pt_BR", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "Monitor {name}: o modo de gama de cores amplo está ativado, mas a tela não está configurada para 10 bits.");
|
||||||
|
|
||||||
|
// es (Spanish)
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_ANR_TITLE, "La aplicación no responde");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_ANR_CONTENT, "Una aplicación {title} - {class} no responde.\n¿Qué quieres hacer?");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_ANR_OPTION_TERMINATE, "Terminar");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_ANR_OPTION_WAIT, "Esperar");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_ANR_PROP_UNKNOWN, "(desconocido)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "Una aplicación <b>{app}</b> está solicitando un permiso desconocido.");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "Una aplicación <b>{app}</b> está intentando capturar la pantalla.\n\n¿Quieres permitirlo?");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "Una aplicación <b>{app}</b> está intentando cargar un plugin: <b>{plugin}</b>.\n\n¿Quieres permitirlo?");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "Se ha detectado un nuevo teclado: <b>{keyboard}</b>.\n\n¿Quieres permitir su funcionamiento?");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(desconocido)");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_PERMISSION_TITLE, "Solicitud de permiso");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "Sugerencia: puedes establecer reglas persistentes para estos en el archivo de configuración de Hyprland.");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_PERMISSION_ALLOW, "Permitir");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "Permitir y recordar");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_PERMISSION_ALLOW_ONCE, "Permitir una vez");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_PERMISSION_DENY, "Denegar");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "Aplicación desconocida (wayland client ID {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"La variable de entorno XDG_CURRENT_DESKTOP parece estar gestionada externamente, y el valor actual es {value}.\nEsto podría causar problemas, a menos "
|
||||||
|
"que sea intencionado.");
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"es", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"Tu sistema no tiene instalado hyprland-guiutils. Se trata de una dependencia de tiempo de ejecución para algunos diálogos. Considera la posibilidad de instalarlo.");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_NOTIF_FAILED_ASSETS, [](const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
int assetsNo = std::stoi(vars.at("count"));
|
||||||
|
if (assetsNo <= 1)
|
||||||
|
return "No se ha podido cargar {count} recurso clave, ¡culpa a tu empaquetador por hacer un mal trabajo!";
|
||||||
|
return "No se ha podido cargar {count} recursos clave, ¡culpa a tu empaquetador por hacer un mal trabajo!";
|
||||||
|
});
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"es", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"La configuración de su monitor no es correcta. El monitor {name} se superpone con otros monitores en la configuración. Consulte la wiki (página Monitors, en inglés) "
|
||||||
|
"para obtener más información. Esto <b>provocará</b> problemas.");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_NOTIF_MONITOR_MODE_FAIL,
|
||||||
|
"El monitor {name} no ha podido configurar ninguno de los modos solicitados, por lo que ha recurrido al modo {mode}.");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE, "Escala no válida pasada al monitor {name}: {scale}, utilizando la escala sugerida: {fixed_scale}");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "Error al cargar el plugin {name}: {error}");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "Error al recargar el sombreador CM, recurriendo a rgba/rgbx.");
|
||||||
|
huEngine->registerEntry("es", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "Monitor {name}: la gama de colores amplia está habilitada, pero la pantalla no está en modo de 10-bit.");
|
||||||
|
|
||||||
|
// fa_IR (Persian)
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_ANR_TITLE, "برنامه پاسخ نمیدهد");
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_ANR_CONTENT, "برنامه {title} - {class} پاسخی نمیدهد.\nمیخواهید چه کاری انجام شود؟");
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_ANR_OPTION_TERMINATE, "بستن برنامه");
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_ANR_OPTION_WAIT, "صبر کنید");
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_ANR_PROP_UNKNOWN, "(نامشخص)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "برنامه <b>{app}</b> در حال درخواست یک مجوز ناشناخته است.");
|
||||||
|
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY,
|
||||||
|
"برنامه <b>{app}</b> میخواهد صفحهنمایش شما را ضبط کند.\n\nآیا اجازه میدهید؟");
|
||||||
|
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"fa_IR", TXT_KEY_PERMISSION_REQUEST_PLUGIN,
|
||||||
|
"برنامه <b>{app}</b> میخواهد پلاگین <b>{plugin}</b> را بارگذاری کند.\n\nآیا اجازه میدهید پلاگین بارگذاری "
|
||||||
|
"شود؟");
|
||||||
|
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_PERMISSION_REQUEST_KEYBOARD,
|
||||||
|
"یک کیبورد جدید شناسایی شد: <b>{keyboard}</b>.\n\nآیا اجازه استفاده از آن را صادر میکنید؟");
|
||||||
|
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(نامشخص)");
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_PERMISSION_TITLE, "درخواست مجوز");
|
||||||
|
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_PERMISSION_PERSISTENCE_HINT,
|
||||||
|
"نکته: میتوانید قوانین دائمی مرتبط را در فایل تنظیمات هایپرلند تعریف کنید.");
|
||||||
|
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_PERMISSION_ALLOW, "اجازه");
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "اجازه و ذخیره");
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_PERMISSION_ALLOW_ONCE, "اجازه یکبار");
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_PERMISSION_DENY, "عدم اجازه");
|
||||||
|
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "برنامه ناشناخته (شناسه Wayland: {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"متغیر XDG_CURRENT_DESKTOP توسط محیطی خارجی تنظیم شده است و مقدار فعلی آن {value} است.\n"
|
||||||
|
"اگر این کار عمدی نباشد ممکن است باعث ایجاد مشکل شود.");
|
||||||
|
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"fa_IR", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"بستهٔ hyprland-guiutils در سیستم نصب نیست. این بسته برای برخی از پنجرهها و دیالوگها لازم است. نصب "
|
||||||
|
"آن "
|
||||||
|
"پیشنهاد "
|
||||||
|
"میشود.");
|
||||||
|
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_NOTIF_FAILED_ASSETS, [](const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
int assetsNo = std::stoi(vars.at("count"));
|
||||||
|
if (assetsNo <= 1)
|
||||||
|
return "هایپرلند نتوانست یک فایل ضروری را بارگذاری کند؛ ممکن است بستهبندی توزیع مشکل داشته "
|
||||||
|
"باشد.";
|
||||||
|
return "هایپرلند نتوانست {count} فایل ضروری را بارگذاری کند؛ ممکن است بستهبندی توزیع مشکل داشته "
|
||||||
|
"باشد.";
|
||||||
|
});
|
||||||
|
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"چیدمان مانیتورها صحیح نیست. مانیتور {name} با یک یا چند مانیتور دیگر تداخل دارد.\n"
|
||||||
|
"برای اطلاعات بیشتر به صفحهٔ مانیتورها در ویکی مراجعه کنید. این موضوع <b>حتماً</b> باعث مشکل "
|
||||||
|
"میشود.");
|
||||||
|
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"fa_IR", TXT_KEY_NOTIF_MONITOR_MODE_FAIL,
|
||||||
|
"مانیتور {name} نتوانست هیچکدام از حالتهای درخواستی را اعمال کند؛ بازگشت به حالت {mode}.");
|
||||||
|
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE, "مقیاس واردشده برای مانیتور {name} نامعتبر است: {scale}. مقیاس پیشنهادی اعمال شد: {fixed_scale}");
|
||||||
|
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "بارگذاری پلاگین {name} با خطا روبهرو شد: {error}");
|
||||||
|
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "بارگذاری دوبارهٔ شیدر CM ناموفق بود؛ از حالت rgba/rgbx استفاده شد.");
|
||||||
|
|
||||||
|
huEngine->registerEntry("fa_IR", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "مانیتور {name}: گسترهٔ رنگ وسیع فعال است اما نمایشگر در حالت ۱۰ بیتی نیست.");
|
||||||
|
|
||||||
|
// fr_FR (French)
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_ANR_TITLE, "L'application ne répond plus");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_ANR_CONTENT, "L'application {title} - {class} ne répond plus.\nQue voulez-vous faire?");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_ANR_OPTION_TERMINATE, "Forcer l'arrêt");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_ANR_OPTION_WAIT, "Attendre");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_ANR_PROP_UNKNOWN, "(inconnu)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "Une application <b>{app}</b> demande une autorisation inconnue.");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "Une application <b>{app}</b> tente de capturer votre écran.\n\nVoulez-vous l'y autoriser?");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "Une application <b>{app}</b> tente de charger un module : <b>{plugin}</b>.\n\nVoulez-vous l'y autoriser?");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "Un nouveau clavier a été détecté : <b>{keyboard}</b>.\n\nVouslez-vous l'autoriser à fonctioner?");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(inconnu)");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_PERMISSION_TITLE, "Demande d'autorisation");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "Astuce: vous pouvez définir des règles persistantes dans le fichier de configuration de Hyprland.");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_PERMISSION_ALLOW, "Autoriser");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "Autoriser et mémoriser");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_PERMISSION_ALLOW_ONCE, "Autoriser une fois");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_PERMISSION_DENY, "Refuser");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "Application inconnue (ID client wayland {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"Votre variable d'environnement XDG_CURRENT_DESKTOP semble être gérée de manière externe, et sa valeur actuelle est {value}.\nCela peut provoquer des "
|
||||||
|
"problèmes si ce n'est pas intentionnel.");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"Vous système n'a pas hyprland-guiutils installé. C'est une dépendance d'éxécution pour certains dialogues. Envisagez de l'installer.");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_NOTIF_FAILED_ASSETS, [](const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
int assetsNo = std::stoi(vars.at("count"));
|
||||||
|
if (assetsNo <= 1)
|
||||||
|
return "Hyprland n'a pas pu charger {count} ressource essentielle, cela indique très probablement un problème dans le paquet de votre distribution.";
|
||||||
|
return "Hyprland n'a pas pu charger {count} ressources essentielles, cela indique très probablement un problème dans le paquet de votre distribution.";
|
||||||
|
});
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"Votre disposition d'écrans est incorrecte. Le moniteur {name} chevauche un ou plusieurs autres.\nVeuillez consulter le wiki (page Moniteurs) pour"
|
||||||
|
"en savoir plus. Cela <b>causera</> des problèmes.");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "Le moniteur {name} n'a pu appliquer aucun des modes demandés, retour au mode {mode}.");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE, "Échelle invalide pour le moniteur {name}: {scale}. Utilisation de l'échelle suggérée: {fixed_scale}.");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "Échec du chargement du module {name} : {error}");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "Le rechargement du shader CM a échoué, retour aux formats rgba/rgbx");
|
||||||
|
huEngine->registerEntry("fr_FR", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "Moniteur {name} : l'espace colorimétrique étendu est activé, mais l'écran n'est pas en mode 10-bits.");
|
||||||
|
|
||||||
|
// hi_IN (Hindi)
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_ANR_TITLE, "एप्लिकेशन प्रतिक्रिया नहीं दे रहा है");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_ANR_CONTENT,
|
||||||
|
"एक एप्लिकेशन {title} - {class} प्रतिक्रिया नहीं दे रहा "
|
||||||
|
"है।\nआप इसके साथ क्या करना चाहेंगे?");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_ANR_OPTION_TERMINATE, "समाप्त करें");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_ANR_OPTION_WAIT, "इंतजार करें");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_ANR_PROP_UNKNOWN, "(अज्ञात)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "एक एप्लिकेशन <b>{app}</b> एक अज्ञात अनुमति का अनुरोध कर रहा है।");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY,
|
||||||
|
"एक एप्लिकेशन <b>{app}</b> आपकी स्क्रीन कैप्चर करने की "
|
||||||
|
"कोशिश कर रहा है।\n\nक्या आप इसे अनुमति देना चाहते हैं?");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_PERMISSION_REQUEST_PLUGIN,
|
||||||
|
"एक एप्लिकेशन <b>{app}</b> एक प्लगइन लोड करने की कोशिश कर रहा है: "
|
||||||
|
"<b>{plugin}</b>.\n\nक्या आप इसे अनुमति देना चाहते हैं?");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_PERMISSION_REQUEST_KEYBOARD,
|
||||||
|
"नया कीबोर्ड पाया गया: <b>{keyboard}</b>.\n\nक्या आप "
|
||||||
|
"इसे काम करने की अनुमति देना चाहते हैं?");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(अज्ञात)");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_PERMISSION_TITLE, "अनुमति अनुरोध");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "संकेत: आप Hyprland कॉन्फ़िग फ़ाइल में इनके लिए स्थायी नियम सेट कर सकते हैं।");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_PERMISSION_ALLOW, "अनुमति दें");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "अनुमति दें और याद रखें");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_PERMISSION_ALLOW_ONCE, "एक बार अनुमति दें");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_PERMISSION_DENY, "अस्वीकार करें");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "अज्ञात एप्लिकेशन (wayland क्लाइंट ID {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"आपका XDG_CURRENT_DESKTOP परिवेश बाहरी रूप से प्रबंधित लगता है, और वर्तमान मान "
|
||||||
|
"{value} है।\nयह समस्या पैदा कर सकता "
|
||||||
|
"है जब तक कि यह जानबूझकर न किया गया हो।");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"आपके सिस्टम में hyprland-guiutils इंस्टॉल नहीं है। यह कुछ संवादों के लिए एक रनटाइम "
|
||||||
|
"निर्भरता है। इसे इंस्टॉल करने पर विचार करें।");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_NOTIF_FAILED_ASSETS, [](const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
int assetsNo = std::stoi(vars.at("count"));
|
||||||
|
if (assetsNo <= 1)
|
||||||
|
return "Hyprland {count} आवश्यक संसाधन लोड करने में विफल रहा, अपने डिस्ट्रो "
|
||||||
|
"के पैकेजर को पैकेजिंग में खराब काम करने का दोष दें!";
|
||||||
|
return "Hyprland {count} आवश्यक संसाधनों को लोड करने में विफल रहा, अपने "
|
||||||
|
"डिस्ट्रो के पैकेजर को पैकेजिंग में खराब काम करने का दोष दें!";
|
||||||
|
});
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"आपका मॉनिटर लेआउट गलत तरीके से सेट है। मॉनिटर {name} लेआउट में अन्य मॉनिटर(ओं) के "
|
||||||
|
"साथ ओवरलैप कर रहा है।\nकृपया विकि "
|
||||||
|
" (Monitors पेज) देखें। यह <b>समस्याएँ</b> पैदा करेगा।");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_NOTIF_MONITOR_MODE_FAIL,
|
||||||
|
"मॉनिटर {name} ने किसी भी अनुरोधित मोड को सेट करने में "
|
||||||
|
"विफल रहा, मोड {mode} पर वापस जा रहा है।");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE,
|
||||||
|
"मॉनिटर {name} को अवैध स्केल दिया गया: {scale}, सुझाया "
|
||||||
|
"गया स्केल इस्तेमाल किया जा रहा है: {fixed_scale}");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "प्लगइन {name} लोड करने में विफल: {error}");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "CM शेडर रीलोड विफल हुआ, rgba/rgbx पर वापस जा रहा है।");
|
||||||
|
huEngine->registerEntry("hi_IN", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "मॉनिटर {name}: वाइड कलर गैम सक्षम है लेकिन डिस्प्ले 10-बिट मोड में नहीं है।");
|
||||||
|
|
||||||
|
// it_IT (Italian)
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_ANR_TITLE, "L'applicazione non risponde");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_ANR_CONTENT, "Un'applicazione {title} - {class} non risponde.\nCosa vuoi fare?");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_ANR_OPTION_TERMINATE, "Termina");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_ANR_OPTION_WAIT, "Attendi");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_ANR_PROP_UNKNOWN, "(sconosciuto)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "Un'applicazione <b>{app}</b> richiede un'autorizzazione sconosciuta.");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "Un'applicazione <b>{app}</b> sta provando a catturare il tuo schermo.\n\nGlie lo vuoi permettere?");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_PERMISSION_REQUEST_PLUGIN,
|
||||||
|
"Un'applicazione <b>{app}</b> sta provando a caricare un plugin: <b>{plugin}</b>.\n\nGlie lo vuoi permettere?");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "È stata rilevata una nuova tastiera: <b>{keyboard}</b>.\n\nLe vuoi permettere di operare?");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(sconosciuto)");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_PERMISSION_TITLE, "Richiesta di autorizzazione");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "Consiglio: Puoi impostare una regola persistente nel tuo file di configurazione di Hyprland.");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_PERMISSION_ALLOW, "Permetti");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "Permetti e ricorda");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_PERMISSION_ALLOW_ONCE, "Permetti una volta");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_PERMISSION_DENY, "Nega");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "Applicazione sconosciuta (wayland client ID {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"L'ambiente XDG_CURRENT_DESKTOP sembra essere gestito esternamente, il valore attuale è {value}.\nSe non è voluto, potrebbe causare problemi.");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"Sembra che hyprland-guiutils non sia installato. È una dipendenza richiesta per alcuni dialoghi che potresti voler installare.");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_NOTIF_FAILED_ASSETS,
|
||||||
|
"Hyprland non ha potuto caricare {count} asset, dai la colpa al packager della tua distribuzione per il suo cattivo lavoro!");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"I tuoi schermi sono configurati incorrettamente. Lo schermo {name} si sovrappone con altri nel layout.\nConsulta la wiki (voce Schermi) per "
|
||||||
|
"altre informazioni. Questo <b>causerà</b> problemi.");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "Lo schermo {name} non ha potuto impostare alcuna modalità richiesta, sarà usata la modalità {mode}.");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE,
|
||||||
|
"Fattore di scala non valido per lo schermo {name}: {scale}, utilizzando il fattore suggerito: {fixed_scale}");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "Impossibile caricare il plugin {name}: {error}");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "Impossibile ricaricare gli shader CM, sarà usato rgba/rgbx.");
|
||||||
|
huEngine->registerEntry("it_IT", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "Schermo {name}: la gamma di colori ampia è abilitata ma lo schermo non è in modalità 10-bit.");
|
||||||
|
|
||||||
|
// ja_JP (Japanese)
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_ANR_TITLE, "アプリは応答しません");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_ANR_CONTENT, "アプリ {title} ー {class}は応答しません。\n何をしたいですか?");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_ANR_OPTION_TERMINATE, "強制終了");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_ANR_OPTION_WAIT, "待機");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_ANR_PROP_UNKNOWN, "(不明)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "アプリ<b>{app}</b>は不明な許可を要求します。");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "アプリ<b>{app}</b>は画面へのアクセスを要求します。\n\n許可したいですか?");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "アプリ<b>{app}</b>は以下のプラグインをロード許可を要求します:<b>{plugin}</b>。\n\n許可したいですか?");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "新しいキーボードを見つけた:<b>{keyboard}</b>。\n\n稼働を許可したいですか?");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(不明)");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_PERMISSION_TITLE, "許可要求");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "ヒント:Hyprlandのコンフィグで通常の許可や却下を設定できます。");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_PERMISSION_ALLOW, "許可");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "保存して許可");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_PERMISSION_ALLOW_ONCE, "一度許可");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_PERMISSION_DENY, "却下");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "不明なアプリ (waylandクライアントID {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"エンバイアロンメント変数「XDG_CURRENT_DESKTOP」は外部から「{value}」に設定しました。\n意図的ではなければ、問題は発生可能性があります。");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_NOTIF_NO_GUIUTILS, "システムにhyprland-guiutilsはインストールしていません。このパッケージをインストールしてください。");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_NOTIF_FAILED_ASSETS,
|
||||||
|
"{count}つの根本的なアセットをロードできませんでした。これはパッケージャーのせいだから、パッケージャーに文句してください。");
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"ja_JP", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"画面の位置設定は誤用です。画面{name}は他の画面の区域と重ね合わせます。\nウィキのモニターページで詳細を確認してください。これは<b>絶対に</b>問題になります。");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "画面{name}は設定したモードを正常に受け入れませんでした。{mode}を使いました。");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE, "画面{name}のスケールは無効:{scale}、代わりにおすすめのスケール{fixed_scale}を使いました。");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "プラグイン{name}のロード失敗: {error}");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "CMシェーダーのリロード失敗、rgba/rgbxを使いました。");
|
||||||
|
huEngine->registerEntry("ja_JP", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "画面{name}:広い色域は設定していますけど、画面は10ビットモードに設定されていません。");
|
||||||
|
|
||||||
|
// hu_HU (Hungarian)
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_ANR_TITLE, "Az alkalmazás nem válaszol");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_ANR_CONTENT, "A(z) {title} - {class} alkalmazás nem válaszol.\nMit szeretne tenni vele?");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_ANR_OPTION_TERMINATE, "Leállítás");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_ANR_OPTION_WAIT, "Várakozás");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_ANR_PROP_UNKNOWN, "(ismeretlen)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "A(z) <b>{app}</b> alkalmazás ismeretlen engedélyt kér.");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "A(z) <b>{app}</b> alkalmazás megpróbálja rögzíteni a képernyőjét.\n\nEngedélyezi?");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "A(z) <b>{app}</b> alkalmazás megpróbál egy bővítményt betölteni: <b>{plugin}</b>.\n\nEngedélyezi?");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "Új billentyűzetet észleltünk: <b>{keyboard}</b>.\n\nEngedélyezi a használatát?");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(ismeretlen)");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_PERMISSION_TITLE, "Engedélykérés");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "Tipp: Állandó szabályokat állíthat be a Hyprland konfigurációs fájlban.");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_PERMISSION_ALLOW, "Engedélyezés");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "Mindig engedélyez");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_PERMISSION_ALLOW_ONCE, "Egyszeri engedélyezés");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_PERMISSION_DENY, "Elutasítás");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "Ismeretlen alkalmazás (wayland kliens ID {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"Úgy tűnik, hogy az XDG_CURRENT_DESKTOP környezetet külsőleg kezelik, és a jelenlegi érték {value}.\nEz problémákat okozhat, hacsak nem szándékos.");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"A rendszerében nincs telepítve a hyprland-guiutils. Ez egy futásidejű függőség néhány párbeszédablakhoz. Fontolja meg a telepítését.");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_NOTIF_FAILED_ASSETS, [](const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
int assetsNo = std::stoi(vars.at("count"));
|
||||||
|
if (assetsNo <= 1)
|
||||||
|
return "A Hyprland nem tudta betölteni az 1 szükséges erőforrást. Kérjük, jelezze a hibát a disztribúció csomagolójának.";
|
||||||
|
return "A Hyprland nem tudott betölteni {count} szükséges erőforrást. Kérjük, jelezze a hibát a disztribúció csomagolójának.";
|
||||||
|
});
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"hu_HU", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"A monitor elrendezése helytelenül van beállítva. A(z) {name} monitor átfedi a többi monitort az elrendezésben.\nKérjük, további információkért tekintse meg a wikit "
|
||||||
|
"(Monitors oldal). Ez <b>problémákat</b> fog okozni.");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "A(z) {name} monitor nem tudta beállítani a kért módokat, visszaáll a(z) {mode} módra.");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE, "Érvénytelen skálázás a(z) {name} monitorhoz: {scale}, a javasolt skálázás használata: {fixed_scale}");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "Nem sikerült betölteni a(z) {name} bővítményt: {error}");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "A CM shader újratöltése sikertelen, visszaáll rgba/rgbx-re.");
|
||||||
|
huEngine->registerEntry("hu_HU", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "Monitor {name}: A széles színtartomány engedélyezve van, de a kijelző nem 10 bites módban van.");
|
||||||
|
// ml_IN (Malayalam)
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_ANR_TITLE, "ആപ്ലിക്കേഷൻ പ്രതികരിക്കുന്നില്ല");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_ANR_CONTENT, "ആപ്ലിക്കേഷൻ {title} - {class} പ്രതികരിക്കുന്നില്ല.\nഇതിന് നിങ്ങൾ എന്ത് ചെയ്യാൻ ആഗ്രഹിക്കുന്നു?");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_ANR_OPTION_TERMINATE, "അവസാനിപ്പിക്കുക");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_ANR_OPTION_WAIT, "കാത്തിരിക്കുക");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_ANR_PROP_UNKNOWN, "(അജ്ഞാതം)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "ആപ്ലിക്കേഷൻ <b>{app}</b> ഒരു അജ്ഞാത അനുമതി അഭ്യർത്ഥിക്കുന്നു.");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "ആപ്ലിക്കേഷൻ <b>{app}</b> നിങ്ങളുടെ സ്ക്രീൻ പകർത്താൻ ശ്രമിക്കുന്നു.\n\nനിങ്ങൾ അത് അനുവദിക്കണോ?");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "ആപ്ലിക്കേഷൻ <b>{app}</b> ഒരു പ്ലഗിൻ ലോഡ് ചെയ്യാൻ ശ്രമിക്കുന്നു: <b>{plugin}</b>.\n\nഇത് അനുവദിക്കണോ?");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "പുതിയ കീബോർഡ് കണ്ടെത്തി: <b>{keyboard}</b>.\n\nഇത് പ്രവർത്തിക്കാൻ അനുവദിക്കണോ?");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(അജ്ഞാതം)");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_PERMISSION_TITLE, "അനുമതി അഭ്യർത്ഥന");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "സൂചന: Hyprland കോൺഫിഗ് ഫയലിൽ സ്ഥിരനിയമങ്ങൾ സജ്ജമാക്കാം.");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_PERMISSION_ALLOW, "അനുവദിക്കുക");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "അനുവദിച്ച് ഓർക്കുക");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_PERMISSION_ALLOW_ONCE, "ഒന്നുതവണ അനുവദിക്കുക");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_PERMISSION_DENY, "നിരസിക്കുക");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "അജ്ഞാത അപ്ലിക്കേഷൻ (wayland client ID {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"നിങ്ങളുടെ XDG_CURRENT_DESKTOP പരിസ്ഥിതി പുറത്ത് നിന്ന് നിയന്ത്രിക്കപ്പെടുന്നു, ഇപ്പോഴത്തെ മൂല്യം "
|
||||||
|
"{value}.\nഇത് ഉദ്ദേശ്യമായല്ലെങ്കിൽ പ്രശ്നങ്ങൾ ഉണ്ടാകും.");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"നിങ്ങളുടെ സിസ്റ്റത്തിൽ hyprland-guiutils ഇൻസ്റ്റാൾ ചെയ്തിട്ടില്ല. ഇത് ചില ഡയലോഗുകൾക്ക് ആവശ്യമായ "
|
||||||
|
"റൺടൈം ആശ്രയമാണ്. ഇൻസ്റ്റാൾ ചെയ്യുക.");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_NOTIF_FAILED_ASSETS, [](const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
int assetsNo = std::stoi(vars.at("count"));
|
||||||
|
if (assetsNo <= 1)
|
||||||
|
return "Hyprland {count} പ്രധാന അസറ്റ് ലോഡുചെയ്യാൻ പരാജയപ്പെട്ടു, നിങ്ങളുടെ "
|
||||||
|
"ഡിസ്ട്രോ "
|
||||||
|
"പാക്കേജർ പിശക് ചെയ്തിരിക്കുന്നു!";
|
||||||
|
return "Hyprland {count} പ്രധാന അസറ്റുകൾ ലോഡുചെയ്യാൻ പരാജയപ്പെട്ടു, നിങ്ങളുടെ "
|
||||||
|
"ഡിസ്ട്രോ "
|
||||||
|
"പാക്കേജർ പിശക് ചെയ്തിരിക്കുന്നു!";
|
||||||
|
});
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"മോണിറ്റർ ലേയൗട്ട് തെറ്റാണ്. മോണിറ്റർ {name} മറ്റുള്ളവയുമായ് ഒതുങ്ങുന്നു.\nകൂടുതൽ വിവരങ്ങൾക്ക് Wiki "
|
||||||
|
"(Monitors page) കാണുക. ഇത് <b>പ്രശ്നങ്ങൾ ഉണ്ടാക്കും</b>.");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "മോണിറ്റർ {name} ആവശ്യപ്പെട്ട മോഡുകൾ സജ്ജമാക്കാൻ പരാജയപ്പെട്ടു, ഇപ്പോൾ {mode} ഉപയോഗിക്കുന്നു.");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE, "മോണിറ്റർ {name} ന് അസാധുവായ സ്കെയിൽ: {scale}, നിർദ്ദേശിച്ച സ്കെയിൽ: {fixed_scale}");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "പ്ലഗിൻ {name} ലോഡ് ചെയ്യാൻ പരാജയപ്പെട്ടു: {error}");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "CM ഷേഡർ റീലോഡ് പരാജയപ്പെട്ടു, rgba/rgbx ലേക്ക് മാറുന്നു.");
|
||||||
|
huEngine->registerEntry("ml_IN", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "മോണിറ്റർ {name}: വൈഡ് കളർ ഗാമട്ട് പ്രവർത്തനക്ഷമമാണെങ്കിലും, മോഡ് 10-bit അല്ല.");
|
||||||
|
|
||||||
|
// nb_NO (Norwegian Bokmål)
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_ANR_TITLE, "Applikasjonen svarer ikke");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_ANR_CONTENT, "En applikasjon {title} - {class} svarer ikke.\nHva vil du gjøre med den?");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_ANR_OPTION_TERMINATE, "Avslutt");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_ANR_OPTION_WAIT, "Vent");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_ANR_PROP_UNKNOWN, "(ukjent)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "En applikasjon <b>{app}</b> ber om en ukjent tillatelse.");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "En applikasjon <b>{app}</b> prøver å fange skjermen din.\n\nVil du tillate den?");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "En applikasjon <b>{app}</b> prøver å laste en plugin: <b>{plugin}</b>.\n\nVil du tillate den?");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "Et nytt tastatur er oppdaget: <b>{keyboard}</b>.\n\nVil du tillate at det opererer?");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(ukjent)");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_PERMISSION_TITLE, "Tillatelsesforespørsel");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "Hint: du kan angi vedvarende regler for disse i Hyprland konfigurasjonsfilen.");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_PERMISSION_ALLOW, "Tillat");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "Tillat og husk");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_PERMISSION_ALLOW_ONCE, "Tillat en gang");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_PERMISSION_DENY, "Nekte");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "Ukjent applikasjon (wayland client ID {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"nb_NO", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"Ditt XDG_CURRENT_DESKTOP miljø ser ut til å være eksternt administrert, og den nåværende verdien er {value}.\nDette kan forårsake problemer med mindre det er bevisst.");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"Ditt system har ikke hyprland-guiutils installert. Dette er en kjøretidsavhengighet for noen dialoger. Vurder å installere den.");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_NOTIF_FAILED_ASSETS, [](const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
int assetsNo = std::stoi(vars.at("count"));
|
||||||
|
if (assetsNo <= 1)
|
||||||
|
return "Hyprland kunne ikke laste {count} essensiell ressurs, skyld på distroens pakkeansvarlig for å ha gjort en dårlig jobb med pakkingen!";
|
||||||
|
return "Hyprland kunne ikke laste {count} essensielle ressurser, skyld på distroens pakkeansvarlig for å ha gjort en dårlig jobb med pakkingen!";
|
||||||
|
});
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"Skjermoppsettet ditt er satt opp feil. Skjerm {name} overlapper med skjerm(er) i oppsettet.\nSjekk wiki (Skjerm oppsett siden) for "
|
||||||
|
"mer. Dette <b>vil</b> skape problemer.");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "Skjerm {name} feilet å sette de forespurte modusene, faller tilbake til modus {mode}.");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE, "Ugyldig skala sendt til skjerm {name}: {scale}, bruker foreslått skala: {fixed_scale}");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "Feilet å laste plugin {name}: {error}");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "CM shader omlading feilet, faller tilbake til rgba/rgbx.");
|
||||||
|
huEngine->registerEntry("nb_NO", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "Skjerm {name}: bredt fargespekter er aktivert, men skjermen er ikke i 10-bit modus.");
|
||||||
|
|
||||||
|
// nl_NL (Dutch)
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_ANR_TITLE, "Applicatie Reageert Niet");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_ANR_CONTENT, "Een applicatie {title} - {class} reageert niet.\nWat wilt u doen?");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_ANR_OPTION_TERMINATE, "Beëindigen");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_ANR_OPTION_WAIT, "Wachten");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_ANR_PROP_UNKNOWN, "(onbekend)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "Een applicatie <b>{app}</b> vraagt om een onbekende machtiging.");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "Een applicatie <b>{app}</b> probeert uw scherm op te nemen.\n\nWilt u dit toestaan?");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "Een applicatie <b>{app}</b> probeert een plugin te laden: <b>{plugin}</b>.\n\nWilt u dit toestaan?");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_PERMISSION_REQUEST_KEYBOARD,
|
||||||
|
"Een nieuw toetsenbord is gedetecteerd: <b>{keyboard}</b>.\n\nWilt u toestemming geven dat het wordt gebruikt?");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(onbekend)");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_PERMISSION_TITLE, "Toestemmingsverzoek");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "Tip: U kunt hiervoor vaste regels instellen in het Hyprland-configuratiebestand.");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_PERMISSION_ALLOW, "Toestaan");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "Toestaan en onthouden");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_PERMISSION_ALLOW_ONCE, "Één keer toestaan");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_PERMISSION_DENY, "Weigeren");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "Onbekende applicatie (wayland client ID {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"nl_NL", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"De XDG_CURRENT_DESKTOP omgevingsvariabele lijkt extern beheerd te worden en de huidige waarde is {value}.\nDit kan problemen veroorzaken, tenzij dit opzettelijk is.");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"Hyprland-guiutils is niet op uw systeem geïnstalleerd. Dit is een runtime-afhankelijkheid voor sommige dialogen. Overweeg het te installeren.");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_NOTIF_FAILED_ASSETS, [](const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
int assetsNo = std::stoi(vars.at("count"));
|
||||||
|
if (assetsNo <= 1)
|
||||||
|
return "Hyprland kon {count} essentieel bestand niet laden, geef de pakketbeheerder van uw distro de schuld voor slecht verpakkingswerk!";
|
||||||
|
return "Hyprland kon {count} essentiële bestanden niet laden, geef de pakketbeheerder van uw distro de schuld voor slecht verpakkingswerk!";
|
||||||
|
});
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"Uw monitorindeling is onjuist ingesteld. Monitor {name} overlapt met één of meerdere andere monitoren in de indeling.\n"
|
||||||
|
"Zie de wiki (Monitors pagina) voor meer informatie. Dit <b>zal</b> problemen veroorzaken.");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_NOTIF_MONITOR_MODE_FAIL,
|
||||||
|
"Monitor {name} is er niet in geslaagd om een van de aangevraagde modi toe te passen en gebruikt nu de modus {mode}.");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE,
|
||||||
|
"Ongeldige schaal opgegeven voor monitor {name}: {scale}, de voorgestelde schaal {fixed_scale} wordt gebruikt.");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "Plugin {name} kon niet worden geladen: {error}");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "Het opnieuw laden van de CM-shader is mislukt. Er wordt teruggevallen op rgba/rgbx.");
|
||||||
|
huEngine->registerEntry("nl_NL", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "Monitor {name}: breed kleurbereik is ingeschakeld maar het scherm staat niet in 10-bitmodus.");
|
||||||
|
|
||||||
|
// pl_PL (Polish)
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_ANR_TITLE, "Aplikacja Nie Odpowiada");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_ANR_CONTENT, "Aplikacja {title} - {class} nie odpowiada.\nCo chcesz z nią zrobić?");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_ANR_OPTION_TERMINATE, "Zakończ proces");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_ANR_OPTION_WAIT, "Czekaj");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_ANR_PROP_UNKNOWN, "(nieznane)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "Aplikacja <b>{app}</b> prosi o pozwolenie na nieznany typ operacji.");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "Aplikacja <b>{app}</b> prosi o dostęp do twojego ekranu.\n\nCzy chcesz jej na to pozwolić?");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "Aplikacja <b>{app}</b> próbuje załadować plugin: <b>{plugin}</b>.\n\nCzy chcesz jej na to pozwolić?");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "Wykryto nową klawiaturę: <b>{keyboard}</b>.\n\nCzy chcesz jej pozwolić operować?");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(nieznane)");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_PERMISSION_TITLE, "Prośba o pozwolenie");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "Podpowiedź: możesz ustawić stałe zasady w konfiguracji Hyprland'a.");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_PERMISSION_ALLOW, "Zezwól");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "Zezwól i zapamiętaj");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_PERMISSION_ALLOW_ONCE, "Zezwól raz");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_PERMISSION_DENY, "Odmów");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "Nieznana aplikacja (ID klienta wayland {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"Zmienna środowiska XDG_CURRENT_DESKTOP została ustawiona zewnętrznie na {value}.\nTo może sprawić problemy, chyba, że jest celowe.");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_NOTIF_NO_GUIUTILS, "Twój system nie ma hyprland-guiutils zainstalowanych, co może sprawić problemy. Zainstaluj pakiet.");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_NOTIF_FAILED_ASSETS, [](const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
int assetsNo = std::stoi(vars.at("count"));
|
||||||
|
if (assetsNo == 1)
|
||||||
|
return "Nie udało się załadować {count} kluczowego zasobu, wiń swojego packager'a za robienie słabej roboty!";
|
||||||
|
|
||||||
|
return "Nie udało się załadować {count} kluczowych zasobów, wiń swojego packager'a za robienie słabej roboty!";
|
||||||
|
});
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"Pozycje twoich monitorów nie są ustawione poprawnie. Monitor {name} wchodzi na inne monitory.\nWejdź na wiki (stronę Monitory) "
|
||||||
|
"po więcej. To <b>będzie</b> sprawiać problemy.");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "Monitor {name} nie zaakceptował żadnego wybranego programu. Użyto {mode}.");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE, "Nieprawidłowa skala dla monitora {name}: {scale}, użyto proponowanej skali: {fixed_scale}");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "Nie udało się załadować plugin'a {name}: {error}");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "Nie udało się przeładować shader'a CM, użyto rgba/rgbx.");
|
||||||
|
huEngine->registerEntry("pl_PL", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "Monitor {name}: skonfigurowano szeroką głębię barw, ale monitor nie jest w trybie 10-bit.");
|
||||||
|
|
||||||
|
// zh_CN (Simplified Chinese)
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_ANR_TITLE, "应用程序未响应");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_ANR_CONTENT, "应用程序 {title} - {class} 未响应。\n你想要采取什么行动?");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_ANR_OPTION_TERMINATE, "终止");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_ANR_OPTION_WAIT, "等待");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_ANR_PROP_UNKNOWN, "(未知)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "应用程序 <b>{app}</b> 正在请求一个未知的权限。");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "应用程序 <b>{app}</b> 想要捕获你的屏幕。\n\n允许它这么做吗?");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "应用程序 <b>{app}</b> 想要加载插件: <b>{plugin}</b>。\n\n允许它这么做吗?");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "检测到新的键盘 <b>{keyboard}</b> 接入了。\n\n允许这个键盘操作你的系统吗?");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(未知)");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_PERMISSION_TITLE, "权限请求");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "提示:你可以在Hyprland配置中为他们创建永久性的规则。");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_PERMISSION_ALLOW, "允许");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "总是允许");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_PERMISSION_ALLOW_ONCE, "允许一次");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_PERMISSION_DENY, "阻止");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "未知的应用程序 (Wayland客户端ID {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"你的环境变量XDG_CURRENT_DESKTOP似乎被外部管理,且当前的值为{value}。如果你不是有意这么做,这可能会导致问题。");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_NOTIF_NO_GUIUTILS, "你的系统似乎没有安装hyprland-guiutils。这是一个用于部分对话框的运行时依赖。请考虑安装。");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_NOTIF_FAILED_ASSETS, "Hyprland无法加载{count}个重要资产,问问你发行版的打包者在打包个什么玩意!?");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"你的显示器没有被正确设置。显示器 {name} 和其他显示器的布局重叠了。请看wiki中的“显示器”一章获取更多信息。这<b>会</b>导致问题。");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "显示器 {name} 无法被设置为任何请求的模式,将使用 {mode} 兜底。");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE, "显示器 {name} 被设置了非法的缩放:{scale},将使用建议的缩放:{fixed_scale}");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "无法加载插件 {name}:{error}");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "无法重新加载CM着色器,将使用rgba/rgbx兜底。");
|
||||||
|
huEngine->registerEntry("zh_CN", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "显示器 {name}:宽色域被启用了,但是显示器并不在10-bit模式。");
|
||||||
|
|
||||||
|
// ar (Arabic - Modern Standard)
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_ANR_TITLE, "التطبيق لا يستجيب");
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_ANR_CONTENT, "التطبيق {title} - {class} لا يستجيب.\nما الذي تريد فعله؟");
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_ANR_OPTION_TERMINATE, "إنهاء");
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_ANR_OPTION_WAIT, "الانتظار");
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_ANR_PROP_UNKNOWN, "(غير معروف)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "يطلب التطبيق <b>{app}</b> صلاحية غير معروفة.");
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "يحاول التطبيق <b>{app}</b> التقاط الشاشة.\n\nهل تريد السماح له بذلك؟");
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "يحاول التطبيق <b>{app}</b> تحميل إضافة: <b>{plugin}</b>.\n\nهل تريد السماح له بذلك؟");
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "تم اكتشاف لوحة مفاتيح جديدة: <b>{keyboard}</b>.\n\nهل تريد السماح لها بالعمل؟");
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(غير معروف)");
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_PERMISSION_TITLE, "طلب الإذن");
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "تلميح: يمكنك تعيين قواعد دائمة لهذه الطلبات في ملف إعدادات Hyprland.");
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_PERMISSION_ALLOW, "السماح");
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "السماح مع تذكّر الاختيار");
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_PERMISSION_ALLOW_ONCE, "السماح لمرة واحدة");
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_PERMISSION_DENY, "الرفض");
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "تطبيق غير معروف (معرّف عميل Wayland {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"يبدو أنّ متغيّر البيئة XDG_CURRENT_DESKTOP يُدار من خارج النظام، والقيمة الحالية هي {value}.\n"
|
||||||
|
"قد يؤدي ذلك إلى مشكلات ما لم يكن مقصودًا.");
|
||||||
|
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_NOTIF_NO_GUIUTILS, "لا يحتوي نظامك على الحزمة hyprland-guiutils مثبتة. هذه حزمة مطلوبة أثناء التشغيل لبعض مربعات الحوار. يُنصَح بتثبيتها.");
|
||||||
|
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_NOTIF_FAILED_ASSETS, [](const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
int assetsNo = std::stoi(vars.at("count"));
|
||||||
|
if (assetsNo <= 1)
|
||||||
|
return "فشل Hyprland في تحميل مورد أساسي ({count}). قد يكون السبب سوء تغليف الحزم في التوزيعة.";
|
||||||
|
return "فشل Hyprland في تحميل {count} من الموارد الأساسية. قد يكون السبب سوء تغليف الحزم في التوزيعة.";
|
||||||
|
});
|
||||||
|
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"تم إعداد مخطط الشاشات لديك بشكل غير صحيح. الشاشة {name} تتداخل مع شاشة أو أكثر في المخطط.\n"
|
||||||
|
"يرجى مراجعة صفحة الشاشات في الويكي لمزيد من التفاصيل. هذا <b>سيسبب</b> مشكلات.");
|
||||||
|
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "فشلت الشاشة {name} في ضبط أي من الأوضاع المطلوبة، وسيتم الرجوع إلى الوضع {mode}.");
|
||||||
|
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE, "تم تمرير قيمة تحجيم غير صالحة إلى الشاشة {name}: {scale}. سيتم استخدام قيمة التحجيم المقترحة: {fixed_scale}.");
|
||||||
|
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "فشل تحميل الإضافة {name}: {error}");
|
||||||
|
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "فشلت إعادة تحميل نظام إدارة الألوان (CM). سيتم الرجوع إلى صيغة الألوان rgba/rgbx.");
|
||||||
|
|
||||||
|
huEngine->registerEntry("ar", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "الشاشة {name}: تم تفعيل نطاق الألوان الواسع، لكن العرض ليس في وضع 10 بت.");
|
||||||
|
|
||||||
|
// ru_RU (Russian)
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_ANR_TITLE, "Приложение не отвечает");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_ANR_CONTENT, "Приложение {title} - {class} не отвечает.\nЧто вы хотите сделать?");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_ANR_OPTION_TERMINATE, "Завершить");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_ANR_OPTION_WAIT, "Подождать");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_ANR_PROP_UNKNOWN, "(неизвестно)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "Приложение <b>{app}</b> запрашивает неизвестное разрешение.");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "Приложение <b>{app}</b> пытается получить доступ к вашему экрану.\n\nРазрешить?");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "Приложение <b>{app}</b> пытается загрузить плагин: <b>{plugin}</b>.\n\nРазрешить?");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "Обнаружена новая клавиатура: <b>{keyboard}</b>.\n\nРазрешить ей работать?");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(неизвестно)");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_PERMISSION_TITLE, "Запрос разрешения");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "Подсказка: вы можете настроить постоянные правила для этого в конфигурационном файле Hyprland.");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_PERMISSION_ALLOW, "Разрешить");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "Разрешить и запомнить");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_PERMISSION_ALLOW_ONCE, "Разрешить в этот раз");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_PERMISSION_DENY, "Отклонить");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "Неизвестное приложение (wayland client ID {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"ru_RU", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"Переменная окружения XDG_CURRENT_DESKTOP установлена извне, текущее значение: {value}.\nЭто может вызвать проблемы, если только это не сделано намеренно.");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_NOTIF_NO_GUIUTILS, "Пакет hyprland-guiutils не установлен. Он необходим для некоторых диалогов. Рекомендуется установить его.");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_NOTIF_FAILED_ASSETS, [](const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
int assetsNo = std::stoi(vars.at("count"));
|
||||||
|
if (assetsNo <= 1)
|
||||||
|
return "Не удалось загрузить {count} критически важный ресурс, пожалуйтесь мейнтейнеру вашего дистрибутива за кривую сборку пакета!";
|
||||||
|
return "Не удалось загрузить {count} критически важных ресурсов, пожалуйтесь мейнтейнеру вашего дистрибутива за кривую сборку пакета!";
|
||||||
|
});
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"ru_RU", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"Неправильно настроен макет мониторов. Монитор {name} перекрывает другие.\nПодробнее см. в документации (страница Monitors). Это <b>обязательно</b> вызовет проблемы.");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "Монитор {name} не смог установить ни один из запрошенных режимов, выбран режим {mode}.");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE, "Недопустимый масштаб для монитора {name}: {scale}, используется предложенный масштаб: {fixed_scale}");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "Не удалось загрузить плагин {name}: {error}");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "Не удалось перезагрузить CM shader, используется rgba/rgbx.");
|
||||||
|
huEngine->registerEntry("ru_RU", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "Монитор {name}: расширенный цветовой охват включён, но дисплей не в 10-bit режиме.");
|
||||||
|
|
||||||
|
// sr_RS (Serbian)
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_ANR_TITLE, "Апликација не реагује");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_ANR_CONTENT, "Апликација {title} - {class} не реагује.\nШта желите да урадите са њом?");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_ANR_OPTION_TERMINATE, "Прекини");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_ANR_OPTION_WAIT, "Чекај");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_ANR_PROP_UNKNOWN, "(непознато)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "Апликација <b>{app}</b> захтева непознату дозволу.");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "Апликација <b>{app}</b> покушава да снима твој екран.\n\nДа ли желиш да то дозволиш?");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "Апликација <b>{app}</b> покушава да учита додатак: <b>{plugin}</b>.\n\nДа ли желиш да то дозволиш?");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "Нова тастатура је детектована: <b>{keyboard}</b>.\n\nДа ли желиш да дозволиш њен рад?");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(непознато)");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_PERMISSION_TITLE, "Захтев за дозволу");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "Савет: можеш направити трајна правила за ово у Hyprland конфигурационој датотеци.");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_PERMISSION_ALLOW, "Дозволи");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "Дозволи и запамти");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_PERMISSION_ALLOW_ONCE, "Дозволи једном");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_PERMISSION_DENY, "Одбиј");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "Непозната апликација (wayland client ID {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"Изгледа да се твојим XDG_CURRENT_DESKTOP окружењем управља споља, и тренутна вредност је {value}.\nОво може правити проблеме осим ако је намерно.");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"Твој систем нема инсталиран hyprland-guiutils. Ово је зависност при покретању за неке дијалоге. Размотри инсталацију.");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_NOTIF_FAILED_ASSETS, [](const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
int assetsNo = std::stoi(vars.at("count"));
|
||||||
|
if (assetsNo <= 1)
|
||||||
|
return "Hyprland није успео да учита {count} кључни ресурс, криви пакера твоје дистрибуције за лоше одрађен посао!";
|
||||||
|
if (assetsNo <= 4)
|
||||||
|
return "Hyprland није успео да учита {count} кључна ресурса, криви пакера твоје дистрибуције за лоше одрађен посао!";
|
||||||
|
return "Hyprland није успео да учита {count} кључних ресурса, криви пакера твоје дистрибуције за лоше одрађен посао!";
|
||||||
|
});
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"sr_RS", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"Твој распоред монитора је неправилно постављен. Монитор {name} се преклапа са другим монитором/мониторима у распореду.\nМолим те погледај вики (Monitors страницу) за "
|
||||||
|
"више информација. Ово <b>ће</b> изазвати проблеме.");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "Монитор {name} није успео да постави ниједан тражени режим, враћање на режим {mode}.");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE, "Невалидна скала прослеђена монитору {name}: {scale}, користи се препоручена скала: {fixed_scale}");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "Неуспешно учитавање додатка {name}: {error}");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "Поново учитавање CM шејдера није успело, враћање на rgba/rgbx.");
|
||||||
|
huEngine->registerEntry("sr_RS", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "Монитор {name}: широк спектар боја је омогућен али екран није у 10-битном режиму.");
|
||||||
|
|
||||||
|
// sr_RS@latin (Serbian Latin)
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_ANR_TITLE, "Aplikacija ne reaguje");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_ANR_CONTENT, "Aplikacija {title} - {class} ne reaguje.\nŠta želite da uradite sa njom?");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_ANR_OPTION_TERMINATE, "Prekini");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_ANR_OPTION_WAIT, "Čekaj");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_ANR_PROP_UNKNOWN, "(nepoznato)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "Aplikacija <b>{app}</b> zahteva nepoznatu dozvolu.");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "Aplikacija <b>{app}</b> pokušava da snima tvoj ekran.\n\nDa li želiš da to dozvoliš?");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "Aplikacija <b>{app}</b> pokušava da učita dodatak: <b>{plugin}</b>.\n\nDa li želiš da to dozvoliš?");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "Nova tastatura je detektovana: <b>{keyboard}</b>.\n\nDa li želiš da dozvoliš njen rad?");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(nepoznato)");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_PERMISSION_TITLE, "Zahtev za dozvolu");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "Savet: možeš napraviti trajna pravila za ovo u Hyprland konfiguracionoj datoteci.");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_PERMISSION_ALLOW, "Dozvoli");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "Dozvoli i zapamti");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_PERMISSION_ALLOW_ONCE, "Dozvoli jednom");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_PERMISSION_DENY, "Odbij");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "Nepoznata aplikacija (wayland client ID {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"Izgleda da se tvojim XDG_CURRENT_DESKTOP okruženjem upravlja spolja, i trenutna vrednost je {value}.\nOvo može praviti probleme osim ako je namerno.");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"Tvoj sistem nema instaliran hyprland-guiutils. Ovo je zavisnost pri pokretanju za neke dijaloge. Razmotri instalaciju.");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_NOTIF_FAILED_ASSETS, [](const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
int assetsNo = std::stoi(vars.at("count"));
|
||||||
|
if (assetsNo <= 1)
|
||||||
|
return "Hyprland nije uspeo da učita {count} ključni resurs, krivi pakera tvoje distribucije za loše odrađen posao!";
|
||||||
|
if (assetsNo <= 4)
|
||||||
|
return "Hyprland nije uspeo da učita {count} ključna resursa, krivi pakera tvoje distribucije za loše odrađen posao!";
|
||||||
|
return "Hyprland nije uspeo da učita {count} ključnih resursa, krivi pakera tvoje distribucije za loše odrađen posao!";
|
||||||
|
});
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"sr_RS@latin", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"Tvoj raspored monitora je nepravilno postavljen. Monitor {name} se preklapa sa drugim monitorom/monitorima u rasporedu.\nMolim te pogledaj wiki (Monitors stranicu) za "
|
||||||
|
"više informacija. Ovo <b>će</b> izazvati probleme.");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "Monitor {name} nije uspeo da postavi nijedan traženi režim, vraćanje na režim {mode}.");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE, "Nevalidna skala prosleđena monitoru {name}: {scale}, koristi se preporučena skala: {fixed_scale}");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "Neuspešno učitavanje dodatka {name}: {error}");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "Ponovno učitavanje CM šejdera nije uspelo, vraćanje na rgba/rgbx.");
|
||||||
|
huEngine->registerEntry("sr_RS@latin", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "Monitor {name}: širok spektar boja je omogućen ali ekran nije u 10-bitnom režimu.");
|
||||||
|
|
||||||
|
// tr_TR (Turkish)
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_ANR_TITLE, "Uygulama Yanıt Vermiyor");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_ANR_CONTENT, "Bir uygulama {title} - {class} yanıt vermiyor.\nBununla ne yapmak istiyorsun?");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_ANR_OPTION_TERMINATE, "Sonlandır");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_ANR_OPTION_WAIT, "Bekle");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_ANR_PROP_UNKNOWN, "(bilinmiyor)");
|
||||||
|
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_PERMISSION_REQUEST_UNKNOWN, "Bir uygulama <b>{app}</b> bilinmeyen bir izin istiyor.");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_PERMISSION_REQUEST_SCREENCOPY, "Bir uygulama <b>{app}</b> ekran kaydı yapmaya çalışıyor.\n\nİzin vermek istiyor musun?");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_PERMISSION_REQUEST_PLUGIN, "Bir uygulama <b>{app}</b> bir eklenti kurmaya çalışıyor: <b>{plugin}</b>.\n\nİzin vermek istiyor musun?");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_PERMISSION_REQUEST_KEYBOARD, "Yeni bir klavye algılandı: <b>{keyboard}</b>.\n\nÇalışmasına izin vermek istiyor musun?");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_PERMISSION_UNKNOWN_NAME, "(bilinmiyor)");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_PERMISSION_TITLE, "İzin isteği");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_PERMISSION_PERSISTENCE_HINT, "İpucu: Hyprland config dosyasında bunlar için kalıcı kurallar atayabilirsin.");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_PERMISSION_ALLOW, "İzin ver");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER, "İzin ver ve seçimimi hatırla");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_PERMISSION_ALLOW_ONCE, "Yalnızca bir defa izin ver");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_PERMISSION_DENY, "Reddet");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP, "Bilinmeyen uygulama (wayland istemci ID {wayland_id})");
|
||||||
|
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
"XDG_CURRENT_DESKTOP ortamın harici olarak yönetiliyor gibi gözüküyor, ve mevcut değeri {value}.\nEğer bu bilinçli değilse sorunlara yol açabilir.");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
"Sisteminde hyprland-guiutils yüklü değil. Bu bazı diyaloglar için bir çalışma zamanı bağımlılığı. İndirmeyi göz önünde bulundurabilirsin.");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_NOTIF_FAILED_ASSETS,
|
||||||
|
"Hyprland {count} gerekli dosyayı yüklemekte başarısız oldu, kötü bir iş çıkardığı için kullandığın distronun paketleyicisini suçla!");
|
||||||
|
huEngine->registerEntry(
|
||||||
|
"tr_TR", TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
"Monitör düzenin yanlış ayarlanmış. Monitör {name} düzenindeki başka monitörlerle çakışıyor.\nLütfen daha fazla bilgi için wiki'ye (Monitörler sayfası) göz at. "
|
||||||
|
"Bu <b>sorunlara yol açacak</b>.");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_NOTIF_MONITOR_MODE_FAIL, "Monitör {name} istenen modları ayarlamada başarısız oldu, {mode} moduna geri dönülüyor.");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_NOTIF_MONITOR_AUTO_SCALE, "Monitöre geçersiz ölçek iletildi {name}: {scale}, önerilen ölçek kullanılıyor: {fixed_scale}");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN, "{name} plugini yüklenemedi: {error}");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_NOTIF_CM_RELOAD_FAILED, "CM shader yeniden yüklemesi başarısız, rgba/rgbx'e geri dönülüyor.");
|
||||||
|
huEngine->registerEntry("tr_TR", TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B, "Monitör {name}: wide color gamut etkinleştirildi ama ekran 10-bit modunda değil.");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string I18n::CI18nEngine::localize(eI18nKeys key, const Hyprutils::I18n::translationVarMap& vars) {
|
||||||
|
return huEngine->localizeEntry(localeStr, key, vars);
|
||||||
|
}
|
||||||
50
src/i18n/Engine.hpp
Normal file
50
src/i18n/Engine.hpp
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../helpers/memory/Memory.hpp"
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace I18n {
|
||||||
|
|
||||||
|
enum eI18nKeys : uint8_t {
|
||||||
|
TXT_KEY_ANR_TITLE = 0,
|
||||||
|
TXT_KEY_ANR_CONTENT,
|
||||||
|
TXT_KEY_ANR_OPTION_TERMINATE,
|
||||||
|
TXT_KEY_ANR_OPTION_WAIT,
|
||||||
|
TXT_KEY_ANR_PROP_UNKNOWN,
|
||||||
|
|
||||||
|
TXT_KEY_PERMISSION_REQUEST_UNKNOWN,
|
||||||
|
TXT_KEY_PERMISSION_REQUEST_SCREENCOPY,
|
||||||
|
TXT_KEY_PERMISSION_REQUEST_PLUGIN,
|
||||||
|
TXT_KEY_PERMISSION_REQUEST_KEYBOARD,
|
||||||
|
TXT_KEY_PERMISSION_UNKNOWN_NAME,
|
||||||
|
TXT_KEY_PERMISSION_TITLE,
|
||||||
|
TXT_KEY_PERMISSION_PERSISTENCE_HINT,
|
||||||
|
TXT_KEY_PERMISSION_ALLOW,
|
||||||
|
TXT_KEY_PERMISSION_ALLOW_AND_REMEMBER,
|
||||||
|
TXT_KEY_PERMISSION_ALLOW_ONCE,
|
||||||
|
TXT_KEY_PERMISSION_DENY,
|
||||||
|
TXT_KEY_PERMISSION_UNKNOWN_WAYLAND_APP,
|
||||||
|
|
||||||
|
TXT_KEY_NOTIF_EXTERNAL_XDG_DESKTOP,
|
||||||
|
TXT_KEY_NOTIF_NO_GUIUTILS,
|
||||||
|
TXT_KEY_NOTIF_FAILED_ASSETS,
|
||||||
|
TXT_KEY_NOTIF_INVALID_MONITOR_LAYOUT,
|
||||||
|
TXT_KEY_NOTIF_MONITOR_MODE_FAIL,
|
||||||
|
TXT_KEY_NOTIF_MONITOR_AUTO_SCALE,
|
||||||
|
TXT_KEY_NOTIF_FAILED_TO_LOAD_PLUGIN,
|
||||||
|
TXT_KEY_NOTIF_CM_RELOAD_FAILED,
|
||||||
|
TXT_KEY_NOTIF_WIDE_COLOR_NOT_10B,
|
||||||
|
};
|
||||||
|
|
||||||
|
class CI18nEngine {
|
||||||
|
public:
|
||||||
|
CI18nEngine();
|
||||||
|
~CI18nEngine() = default;
|
||||||
|
|
||||||
|
std::string localize(eI18nKeys key, const std::unordered_map<std::string, std::string>& vars = {});
|
||||||
|
};
|
||||||
|
|
||||||
|
SP<CI18nEngine> i18nEngine();
|
||||||
|
};
|
||||||
|
|
@ -9,51 +9,14 @@
|
||||||
#include "../managers/EventManager.hpp"
|
#include "../managers/EventManager.hpp"
|
||||||
#include "xwayland/XWayland.hpp"
|
#include "xwayland/XWayland.hpp"
|
||||||
|
|
||||||
SWorkspaceGaps CHyprDwindleLayout::getWorkspaceGaps(const PHLWORKSPACE& pWorkspace) {
|
|
||||||
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(pWorkspace);
|
|
||||||
static auto PGAPSINDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_in");
|
|
||||||
static auto PGAPSOUTDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_out");
|
|
||||||
auto* const PGAPSIN = sc<CCssGapData*>((PGAPSINDATA.ptr())->getData());
|
|
||||||
auto* const PGAPSOUT = sc<CCssGapData*>((PGAPSOUTDATA.ptr())->getData());
|
|
||||||
|
|
||||||
SWorkspaceGaps gaps;
|
|
||||||
gaps.in = WORKSPACERULE.gapsIn.value_or(*PGAPSIN);
|
|
||||||
gaps.out = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT);
|
|
||||||
return gaps;
|
|
||||||
}
|
|
||||||
|
|
||||||
SNodeDisplayEdgeFlags CHyprDwindleLayout::getNodeDisplayEdgeFlags(const CBox& box, const PHLMONITOR& monitor) {
|
|
||||||
return {
|
|
||||||
.top = STICKS(box.y, monitor->m_position.y + monitor->m_reservedTopLeft.y),
|
|
||||||
.bottom = STICKS(box.y + box.h, monitor->m_position.y + monitor->m_size.y - monitor->m_reservedBottomRight.y),
|
|
||||||
.left = STICKS(box.x, monitor->m_position.x + monitor->m_reservedTopLeft.x),
|
|
||||||
.right = STICKS(box.x + box.w, monitor->m_position.x + monitor->m_size.x - monitor->m_reservedBottomRight.x),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverride, bool verticalOverride) {
|
void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverride, bool verticalOverride) {
|
||||||
if (children[0]) {
|
if (children[0]) {
|
||||||
static auto PSMARTSPLIT = CConfigValue<Hyprlang::INT>("dwindle:smart_split");
|
static auto PSMARTSPLIT = CConfigValue<Hyprlang::INT>("dwindle:smart_split");
|
||||||
static auto PPRESERVESPLIT = CConfigValue<Hyprlang::INT>("dwindle:preserve_split");
|
static auto PPRESERVESPLIT = CConfigValue<Hyprlang::INT>("dwindle:preserve_split");
|
||||||
static auto PFLMULT = CConfigValue<Hyprlang::FLOAT>("dwindle:split_width_multiplier");
|
static auto PFLMULT = CConfigValue<Hyprlang::FLOAT>("dwindle:split_width_multiplier");
|
||||||
|
|
||||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(workspaceID);
|
|
||||||
if (!PWORKSPACE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto PMONITOR = PWORKSPACE->m_monitor.lock();
|
|
||||||
if (!PMONITOR)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const auto edges = layout->getNodeDisplayEdgeFlags(box, PMONITOR);
|
|
||||||
auto [gapsIn, gapsOut] = layout->getWorkspaceGaps(PWORKSPACE);
|
|
||||||
|
|
||||||
const Vector2D availableSize = box.size() -
|
|
||||||
Vector2D{(edges.left ? gapsOut.m_left : gapsIn.m_left / 2.f) + (edges.right ? gapsOut.m_right : gapsIn.m_right / 2.f),
|
|
||||||
(edges.top ? gapsOut.m_top : gapsIn.m_top / 2.f) + (edges.bottom ? gapsOut.m_bottom : gapsIn.m_bottom / 2.f)};
|
|
||||||
|
|
||||||
if (*PPRESERVESPLIT == 0 && *PSMARTSPLIT == 0)
|
if (*PPRESERVESPLIT == 0 && *PSMARTSPLIT == 0)
|
||||||
splitTop = availableSize.y * *PFLMULT > availableSize.x;
|
splitTop = box.h * *PFLMULT > box.w;
|
||||||
|
|
||||||
if (verticalOverride)
|
if (verticalOverride)
|
||||||
splitTop = true;
|
splitTop = true;
|
||||||
|
|
@ -64,26 +27,12 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverrid
|
||||||
|
|
||||||
if (SPLITSIDE) {
|
if (SPLITSIDE) {
|
||||||
// split left/right
|
// split left/right
|
||||||
const float gapsAppliedToChild1 = (edges.left ? gapsOut.m_left : gapsIn.m_left / 2.f) + gapsIn.m_right / 2.f;
|
const float FIRSTSIZE = box.w / 2.0 * splitRatio;
|
||||||
const float gapsAppliedToChild2 = gapsIn.m_left / 2.f + (edges.right ? gapsOut.m_right : gapsIn.m_right / 2.f);
|
|
||||||
const float totalGaps = gapsAppliedToChild1 + gapsAppliedToChild2;
|
|
||||||
const float totalAvailable = box.w - totalGaps;
|
|
||||||
|
|
||||||
const float child1Available = totalAvailable * (splitRatio / 2.f);
|
|
||||||
const float FIRSTSIZE = child1Available + gapsAppliedToChild1;
|
|
||||||
|
|
||||||
children[0]->box = CBox{box.x, box.y, FIRSTSIZE, box.h}.noNegativeSize();
|
children[0]->box = CBox{box.x, box.y, FIRSTSIZE, box.h}.noNegativeSize();
|
||||||
children[1]->box = CBox{box.x + FIRSTSIZE, box.y, box.w - FIRSTSIZE, box.h}.noNegativeSize();
|
children[1]->box = CBox{box.x + FIRSTSIZE, box.y, box.w - FIRSTSIZE, box.h}.noNegativeSize();
|
||||||
} else {
|
} else {
|
||||||
// split top/bottom
|
// split top/bottom
|
||||||
const float gapsAppliedToChild1 = (edges.top ? gapsOut.m_top : gapsIn.m_top / 2.f) + gapsIn.m_bottom / 2.f;
|
const float FIRSTSIZE = box.h / 2.0 * splitRatio;
|
||||||
const float gapsAppliedToChild2 = gapsIn.m_top / 2.f + (edges.bottom ? gapsOut.m_bottom : gapsIn.m_bottom / 2.f);
|
|
||||||
const float totalGaps = gapsAppliedToChild1 + gapsAppliedToChild2;
|
|
||||||
const float totalAvailable = box.h - totalGaps;
|
|
||||||
|
|
||||||
const float child1Available = totalAvailable * (splitRatio / 2.f);
|
|
||||||
const float FIRSTSIZE = child1Available + gapsAppliedToChild1;
|
|
||||||
|
|
||||||
children[0]->box = CBox{box.x, box.y, box.w, FIRSTSIZE}.noNegativeSize();
|
children[0]->box = CBox{box.x, box.y, box.w, FIRSTSIZE}.noNegativeSize();
|
||||||
children[1]->box = CBox{box.x, box.y + FIRSTSIZE, box.w, box.h - FIRSTSIZE}.noNegativeSize();
|
children[1]->box = CBox{box.x, box.y + FIRSTSIZE, box.w, box.h - FIRSTSIZE}.noNegativeSize();
|
||||||
}
|
}
|
||||||
|
|
@ -167,7 +116,10 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||||
}
|
}
|
||||||
|
|
||||||
// for gaps outer
|
// for gaps outer
|
||||||
const auto edges = getNodeDisplayEdgeFlags(pNode->box, PMONITOR);
|
const bool DISPLAYLEFT = STICKS(pNode->box.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x);
|
||||||
|
const bool DISPLAYRIGHT = STICKS(pNode->box.x + pNode->box.w, PMONITOR->m_position.x + PMONITOR->m_size.x - PMONITOR->m_reservedBottomRight.x);
|
||||||
|
const bool DISPLAYTOP = STICKS(pNode->box.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y);
|
||||||
|
const bool DISPLAYBOTTOM = STICKS(pNode->box.y + pNode->box.h, PMONITOR->m_position.y + PMONITOR->m_size.y - PMONITOR->m_reservedBottomRight.y);
|
||||||
|
|
||||||
const auto PWINDOW = pNode->pWindow.lock();
|
const auto PWINDOW = pNode->pWindow.lock();
|
||||||
// get specific gaps and rules for this workspace,
|
// get specific gaps and rules for this workspace,
|
||||||
|
|
@ -183,7 +135,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||||
if (PWINDOW->isFullscreen() && !pNode->ignoreFullscreenChecks)
|
if (PWINDOW->isFullscreen() && !pNode->ignoreFullscreenChecks)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PWINDOW->unsetWindowData(PRIORITY_LAYOUT);
|
PWINDOW->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT);
|
||||||
PWINDOW->updateWindowData();
|
PWINDOW->updateWindowData();
|
||||||
|
|
||||||
static auto PGAPSINDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_in");
|
static auto PGAPSINDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_in");
|
||||||
|
|
@ -228,9 +180,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto GAPOFFSETTOPLEFT = Vector2D(sc<double>(edges.left ? gapsOut.m_left : gapsIn.m_left), sc<double>(edges.top ? gapsOut.m_top : gapsIn.m_top));
|
const auto GAPOFFSETTOPLEFT = Vector2D(sc<double>(DISPLAYLEFT ? gapsOut.m_left : gapsIn.m_left), sc<double>(DISPLAYTOP ? gapsOut.m_top : gapsIn.m_top));
|
||||||
|
|
||||||
const auto GAPOFFSETBOTTOMRIGHT = Vector2D(sc<double>(edges.right ? gapsOut.m_right : gapsIn.m_right), sc<double>(edges.bottom ? gapsOut.m_bottom : gapsIn.m_bottom));
|
const auto GAPOFFSETBOTTOMRIGHT = Vector2D(sc<double>(DISPLAYRIGHT ? gapsOut.m_right : gapsIn.m_right), sc<double>(DISPLAYBOTTOM ? gapsOut.m_bottom : gapsIn.m_bottom));
|
||||||
|
|
||||||
calcPos = calcPos + GAPOFFSETTOPLEFT + ratioPadding / 2;
|
calcPos = calcPos + GAPOFFSETTOPLEFT + ratioPadding / 2;
|
||||||
calcSize = calcSize - GAPOFFSETTOPLEFT - GAPOFFSETBOTTOMRIGHT - ratioPadding;
|
calcSize = calcSize - GAPOFFSETTOPLEFT - GAPOFFSETBOTTOMRIGHT - ratioPadding;
|
||||||
|
|
@ -272,9 +224,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||||
Vector2D monitorAvailable = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight -
|
Vector2D monitorAvailable = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight -
|
||||||
Vector2D{(double)(gapsOut.m_left + gapsOut.m_right), (double)(gapsOut.m_top + gapsOut.m_bottom)} - Vector2D{2.0 * borderSize, 2.0 * borderSize};
|
Vector2D{(double)(gapsOut.m_left + gapsOut.m_right), (double)(gapsOut.m_top + gapsOut.m_bottom)} - Vector2D{2.0 * borderSize, 2.0 * borderSize};
|
||||||
|
|
||||||
Vector2D minSize = PWINDOW->m_windowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}).clamp(Vector2D{0, 0}, monitorAvailable);
|
Vector2D minSize = PWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}).clamp(Vector2D{0, 0}, monitorAvailable);
|
||||||
Vector2D maxSize =
|
Vector2D maxSize = PWINDOW->isFullscreen() ? Vector2D{INFINITY, INFINITY} :
|
||||||
PWINDOW->isFullscreen() ? Vector2D{INFINITY, INFINITY} : PWINDOW->m_windowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY}).clamp(Vector2D{0, 0}, monitorAvailable);
|
PWINDOW->m_ruleApplicator->maxSize().valueOr(Vector2D{INFINITY, INFINITY}).clamp(Vector2D{0, 0}, monitorAvailable);
|
||||||
calcSize = calcSize.clamp(minSize, maxSize);
|
calcSize = calcSize.clamp(minSize, maxSize);
|
||||||
|
|
||||||
calcPos += (availableSpace - calcSize) / 2.0;
|
calcPos += (availableSpace - calcSize) / 2.0;
|
||||||
|
|
@ -398,6 +350,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the node under our cursor
|
// get the node under our cursor
|
||||||
|
|
||||||
m_dwindleNodesData.emplace_back();
|
m_dwindleNodesData.emplace_back();
|
||||||
const auto NEWPARENT = &m_dwindleNodesData.back();
|
const auto NEWPARENT = &m_dwindleNodesData.back();
|
||||||
|
|
||||||
|
|
@ -410,17 +363,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir
|
||||||
|
|
||||||
static auto PWIDTHMULTIPLIER = CConfigValue<Hyprlang::FLOAT>("dwindle:split_width_multiplier");
|
static auto PWIDTHMULTIPLIER = CConfigValue<Hyprlang::FLOAT>("dwindle:split_width_multiplier");
|
||||||
|
|
||||||
const auto edges = getNodeDisplayEdgeFlags(NEWPARENT->box, PMONITOR);
|
|
||||||
|
|
||||||
const auto WORKSPACE = g_pCompositor->getWorkspaceByID(PNODE->workspaceID);
|
|
||||||
auto [gapsIn, gapsOut] = getWorkspaceGaps(WORKSPACE);
|
|
||||||
|
|
||||||
// if cursor over first child, make it first, etc
|
// if cursor over first child, make it first, etc
|
||||||
const Vector2D availableSize = NEWPARENT->box.size() -
|
const auto SIDEBYSIDE = NEWPARENT->box.w > NEWPARENT->box.h * *PWIDTHMULTIPLIER;
|
||||||
Vector2D{(edges.left ? gapsOut.m_left : gapsIn.m_left / 2.f) + (edges.right ? gapsOut.m_right : gapsIn.m_right / 2.f),
|
|
||||||
(edges.top ? gapsOut.m_top : gapsIn.m_top / 2.f) + (edges.bottom ? gapsOut.m_bottom : gapsIn.m_bottom / 2.f)};
|
|
||||||
|
|
||||||
const auto SIDEBYSIDE = availableSize.x > availableSize.y * *PWIDTHMULTIPLIER;
|
|
||||||
NEWPARENT->splitTop = !SIDEBYSIDE;
|
NEWPARENT->splitTop = !SIDEBYSIDE;
|
||||||
|
|
||||||
static auto PFORCESPLIT = CConfigValue<Hyprlang::INT>("dwindle:force_split");
|
static auto PFORCESPLIT = CConfigValue<Hyprlang::INT>("dwindle:force_split");
|
||||||
|
|
@ -547,7 +491,7 @@ void CHyprDwindleLayout::onWindowRemovedTiling(PHLWINDOW pWindow) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pWindow->unsetWindowData(PRIORITY_LAYOUT);
|
pWindow->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT);
|
||||||
pWindow->updateWindowData();
|
pWindow->updateWindowData();
|
||||||
|
|
||||||
if (pWindow->isFullscreen())
|
if (pWindow->isFullscreen())
|
||||||
|
|
@ -601,6 +545,8 @@ void CHyprDwindleLayout::recalculateMonitor(const MONITORID& monid) {
|
||||||
|
|
||||||
#ifndef NO_XWAYLAND
|
#ifndef NO_XWAYLAND
|
||||||
CBox box = g_pCompositor->calculateX11WorkArea();
|
CBox box = g_pCompositor->calculateX11WorkArea();
|
||||||
|
if (!g_pXWayland || !g_pXWayland->m_wm)
|
||||||
|
return;
|
||||||
g_pXWayland->m_wm->updateWorkArea(box.x, box.y, box.w, box.h);
|
g_pXWayland->m_wm->updateWorkArea(box.x, box.y, box.w, box.h);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -662,9 +608,9 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||||
const auto PNODE = getNodeFromWindow(PWINDOW);
|
const auto PNODE = getNodeFromWindow(PWINDOW);
|
||||||
|
|
||||||
if (!PNODE) {
|
if (!PNODE) {
|
||||||
*PWINDOW->m_realSize =
|
*PWINDOW->m_realSize = (PWINDOW->m_realSize->goal() + pixResize)
|
||||||
(PWINDOW->m_realSize->goal() + pixResize)
|
.clamp(PWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}),
|
||||||
.clamp(PWINDOW->m_windowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_windowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY}));
|
PWINDOW->m_ruleApplicator->maxSize().valueOr(Vector2D{INFINITY, INFINITY}));
|
||||||
PWINDOW->updateWindowDecos();
|
PWINDOW->updateWindowDecos();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -674,7 +620,10 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||||
|
|
||||||
// get some data about our window
|
// get some data about our window
|
||||||
const auto PMONITOR = PWINDOW->m_monitor.lock();
|
const auto PMONITOR = PWINDOW->m_monitor.lock();
|
||||||
const auto edges = getNodeDisplayEdgeFlags(CBox{PWINDOW->m_position, PWINDOW->m_size}, PMONITOR);
|
const bool DISPLAYLEFT = STICKS(PWINDOW->m_position.x, PMONITOR->m_position.x + PMONITOR->m_reservedTopLeft.x);
|
||||||
|
const bool DISPLAYRIGHT = STICKS(PWINDOW->m_position.x + PWINDOW->m_size.x, PMONITOR->m_position.x + PMONITOR->m_size.x - PMONITOR->m_reservedBottomRight.x);
|
||||||
|
const bool DISPLAYTOP = STICKS(PWINDOW->m_position.y, PMONITOR->m_position.y + PMONITOR->m_reservedTopLeft.y);
|
||||||
|
const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_position.y + PWINDOW->m_size.y, PMONITOR->m_position.y + PMONITOR->m_size.y - PMONITOR->m_reservedBottomRight.y);
|
||||||
|
|
||||||
if (PWINDOW->m_isPseudotiled) {
|
if (PWINDOW->m_isPseudotiled) {
|
||||||
if (!m_pseudoDragFlags.started) {
|
if (!m_pseudoDragFlags.started) {
|
||||||
|
|
@ -707,8 +656,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||||
CBox wbox = PNODE->box;
|
CBox wbox = PNODE->box;
|
||||||
wbox.round();
|
wbox.round();
|
||||||
|
|
||||||
Vector2D minSize = PWINDOW->m_windowData.minSize.valueOr(Vector2D{30.0, 30.0});
|
Vector2D minSize = PWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D{30.0, 30.0});
|
||||||
Vector2D maxSize = PWINDOW->m_windowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY});
|
Vector2D maxSize = PWINDOW->m_ruleApplicator->maxSize().valueOr(Vector2D{INFINITY, INFINITY});
|
||||||
Vector2D upperBound = Vector2D{std::min(maxSize.x, wbox.w), std::min(maxSize.y, wbox.h)};
|
Vector2D upperBound = Vector2D{std::min(maxSize.x, wbox.w), std::min(maxSize.y, wbox.h)};
|
||||||
|
|
||||||
PWINDOW->m_pseudoSize = PWINDOW->m_pseudoSize.clamp(minSize, upperBound);
|
PWINDOW->m_pseudoSize = PWINDOW->m_pseudoSize.clamp(minSize, upperBound);
|
||||||
|
|
@ -722,10 +671,10 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||||
|
|
||||||
// construct allowed movement
|
// construct allowed movement
|
||||||
Vector2D allowedMovement = pixResize;
|
Vector2D allowedMovement = pixResize;
|
||||||
if (edges.left && edges.right)
|
if (DISPLAYLEFT && DISPLAYRIGHT)
|
||||||
allowedMovement.x = 0;
|
allowedMovement.x = 0;
|
||||||
|
|
||||||
if (edges.bottom && edges.top)
|
if (DISPLAYBOTTOM && DISPLAYTOP)
|
||||||
allowedMovement.y = 0;
|
allowedMovement.y = 0;
|
||||||
|
|
||||||
if (*PSMARTRESIZING == 1) {
|
if (*PSMARTRESIZING == 1) {
|
||||||
|
|
@ -735,10 +684,10 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn
|
||||||
SDwindleNodeData* PHOUTER = nullptr;
|
SDwindleNodeData* PHOUTER = nullptr;
|
||||||
SDwindleNodeData* PHINNER = nullptr;
|
SDwindleNodeData* PHINNER = nullptr;
|
||||||
|
|
||||||
const auto LEFT = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT || edges.right;
|
const auto LEFT = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT || DISPLAYRIGHT;
|
||||||
const auto TOP = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT || edges.bottom;
|
const auto TOP = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT || DISPLAYBOTTOM;
|
||||||
const auto RIGHT = corner == CORNER_TOPRIGHT || corner == CORNER_BOTTOMRIGHT || edges.left;
|
const auto RIGHT = corner == CORNER_TOPRIGHT || corner == CORNER_BOTTOMRIGHT || DISPLAYLEFT;
|
||||||
const auto BOTTOM = corner == CORNER_BOTTOMLEFT || corner == CORNER_BOTTOMRIGHT || edges.top;
|
const auto BOTTOM = corner == CORNER_BOTTOMLEFT || corner == CORNER_BOTTOMRIGHT || DISPLAYTOP;
|
||||||
const auto NONE = corner == CORNER_NONE;
|
const auto NONE = corner == CORNER_NONE;
|
||||||
|
|
||||||
for (auto PCURRENT = PNODE; PCURRENT && PCURRENT->pParent; PCURRENT = PCURRENT->pParent) {
|
for (auto PCURRENT = PNODE; PCURRENT && PCURRENT->pParent; PCURRENT = PCURRENT->pParent) {
|
||||||
|
|
@ -868,7 +817,7 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFu
|
||||||
*pWindow->m_realPosition = pWindow->m_lastFloatingPosition;
|
*pWindow->m_realPosition = pWindow->m_lastFloatingPosition;
|
||||||
*pWindow->m_realSize = pWindow->m_lastFloatingSize;
|
*pWindow->m_realSize = pWindow->m_lastFloatingSize;
|
||||||
|
|
||||||
pWindow->unsetWindowData(PRIORITY_LAYOUT);
|
pWindow->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT);
|
||||||
pWindow->updateWindowData();
|
pWindow->updateWindowData();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "IHyprLayout.hpp"
|
#include "IHyprLayout.hpp"
|
||||||
#include "../config/ConfigDataValues.hpp"
|
|
||||||
#include "../desktop/DesktopTypes.hpp"
|
#include "../desktop/DesktopTypes.hpp"
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
@ -13,15 +12,6 @@
|
||||||
class CHyprDwindleLayout;
|
class CHyprDwindleLayout;
|
||||||
enum eFullscreenMode : int8_t;
|
enum eFullscreenMode : int8_t;
|
||||||
|
|
||||||
struct SNodeDisplayEdgeFlags {
|
|
||||||
bool top = false, bottom = false, left = false, right = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SWorkspaceGaps {
|
|
||||||
CCssGapData in;
|
|
||||||
CCssGapData out;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SDwindleNodeData {
|
struct SDwindleNodeData {
|
||||||
SDwindleNodeData* pParent = nullptr;
|
SDwindleNodeData* pParent = nullptr;
|
||||||
bool isNode = false;
|
bool isNode = false;
|
||||||
|
|
@ -75,9 +65,6 @@ class CHyprDwindleLayout : public IHyprLayout {
|
||||||
virtual void onDisable();
|
virtual void onDisable();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SWorkspaceGaps getWorkspaceGaps(const PHLWORKSPACE& pWorkspace);
|
|
||||||
SNodeDisplayEdgeFlags getNodeDisplayEdgeFlags(const CBox& box, const PHLMONITOR& monitor);
|
|
||||||
|
|
||||||
std::list<SDwindleNodeData> m_dwindleNodesData;
|
std::list<SDwindleNodeData> m_dwindleNodesData;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,12 @@
|
||||||
#include "../managers/EventManager.hpp"
|
#include "../managers/EventManager.hpp"
|
||||||
#include "../managers/HookSystemManager.hpp"
|
#include "../managers/HookSystemManager.hpp"
|
||||||
#include "../managers/cursor/CursorShapeOverrideController.hpp"
|
#include "../managers/cursor/CursorShapeOverrideController.hpp"
|
||||||
|
#include "../desktop/rule/windowRule/WindowRule.hpp"
|
||||||
|
|
||||||
void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) {
|
void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) {
|
||||||
CBox desiredGeometry = g_pXWaylandManager->getGeometryForWindow(pWindow);
|
CBox desiredGeometry = g_pXWaylandManager->getGeometryForWindow(pWindow);
|
||||||
|
|
||||||
const bool HASPERSISTENTSIZE = std::ranges::any_of(pWindow->m_matchedRules, [](const auto& rule) { return rule->m_ruleType == CWindowRule::RULE_PERSISTENTSIZE; });
|
const bool HASPERSISTENTSIZE = pWindow->m_ruleApplicator->persistentSize().valueOrDefault();
|
||||||
|
|
||||||
const auto STOREDSIZE = HASPERSISTENTSIZE ? g_pConfigManager->getStoredFloatingSize(pWindow) : std::nullopt;
|
const auto STOREDSIZE = HASPERSISTENTSIZE ? g_pConfigManager->getStoredFloatingSize(pWindow) : std::nullopt;
|
||||||
|
|
||||||
|
|
@ -77,7 +78,7 @@ void IHyprLayout::onWindowRemoved(PHLWINDOW pWindow) {
|
||||||
|
|
||||||
pWindow->updateWindowDecos();
|
pWindow->updateWindowDecos();
|
||||||
PWINDOWPREV->getGroupCurrent()->updateWindowDecos();
|
PWINDOWPREV->getGroupCurrent()->updateWindowDecos();
|
||||||
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
|
pWindow->updateDecorationValues();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -637,10 +638,10 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||||
} else if (g_pInputManager->m_dragMode == MBIND_RESIZE || g_pInputManager->m_dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->m_dragMode == MBIND_RESIZE_BLOCK_RATIO) {
|
} else if (g_pInputManager->m_dragMode == MBIND_RESIZE || g_pInputManager->m_dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->m_dragMode == MBIND_RESIZE_BLOCK_RATIO) {
|
||||||
if (DRAGGINGWINDOW->m_isFloating) {
|
if (DRAGGINGWINDOW->m_isFloating) {
|
||||||
|
|
||||||
Vector2D MINSIZE = DRAGGINGWINDOW->requestedMinSize().clamp(DRAGGINGWINDOW->m_windowData.minSize.valueOr(Vector2D(MIN_WINDOW_SIZE, MIN_WINDOW_SIZE)));
|
Vector2D MINSIZE = DRAGGINGWINDOW->requestedMinSize().clamp(DRAGGINGWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D(MIN_WINDOW_SIZE, MIN_WINDOW_SIZE)));
|
||||||
Vector2D MAXSIZE;
|
Vector2D MAXSIZE;
|
||||||
if (DRAGGINGWINDOW->m_windowData.maxSize.hasValue())
|
if (DRAGGINGWINDOW->m_ruleApplicator->maxSize().hasValue())
|
||||||
MAXSIZE = DRAGGINGWINDOW->requestedMaxSize().clamp({}, DRAGGINGWINDOW->m_windowData.maxSize.value());
|
MAXSIZE = DRAGGINGWINDOW->requestedMaxSize().clamp({}, DRAGGINGWINDOW->m_ruleApplicator->maxSize().value());
|
||||||
else
|
else
|
||||||
MAXSIZE = DRAGGINGWINDOW->requestedMaxSize().clamp({}, Vector2D(std::numeric_limits<double>::max(), std::numeric_limits<double>::max()));
|
MAXSIZE = DRAGGINGWINDOW->requestedMaxSize().clamp({}, Vector2D(std::numeric_limits<double>::max(), std::numeric_limits<double>::max()));
|
||||||
|
|
||||||
|
|
@ -657,7 +658,7 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) {
|
||||||
newSize = newSize + Vector2D(-DELTA.x, DELTA.y);
|
newSize = newSize + Vector2D(-DELTA.x, DELTA.y);
|
||||||
|
|
||||||
eMouseBindMode mode = g_pInputManager->m_dragMode;
|
eMouseBindMode mode = g_pInputManager->m_dragMode;
|
||||||
if (DRAGGINGWINDOW->m_windowData.keepAspectRatio.valueOrDefault() && mode != MBIND_RESIZE_BLOCK_RATIO)
|
if (DRAGGINGWINDOW->m_ruleApplicator->keepAspectRatio().valueOrDefault() && mode != MBIND_RESIZE_BLOCK_RATIO)
|
||||||
mode = MBIND_RESIZE_FORCE_RATIO;
|
mode = MBIND_RESIZE_FORCE_RATIO;
|
||||||
|
|
||||||
if (m_beginDragSizeXY.x >= 1 && m_beginDragSizeXY.y >= 1 && mode == MBIND_RESIZE_FORCE_RATIO) {
|
if (m_beginDragSizeXY.x >= 1 && m_beginDragSizeXY.y >= 1 && mode == MBIND_RESIZE_FORCE_RATIO) {
|
||||||
|
|
@ -803,14 +804,15 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) {
|
||||||
|
|
||||||
g_pHyprRenderer->damageMonitor(pWindow->m_monitor.lock());
|
g_pHyprRenderer->damageMonitor(pWindow->m_monitor.lock());
|
||||||
|
|
||||||
pWindow->unsetWindowData(PRIORITY_LAYOUT);
|
pWindow->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT);
|
||||||
pWindow->updateWindowData();
|
pWindow->updateWindowData();
|
||||||
|
|
||||||
if (pWindow == m_lastTiledWindow)
|
if (pWindow == m_lastTiledWindow)
|
||||||
m_lastTiledWindow.reset();
|
m_lastTiledWindow.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
|
pWindow->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_ON_WORKSPACE | Desktop::Rule::RULE_PROP_FLOATING);
|
||||||
|
pWindow->updateDecorationValues();
|
||||||
pWindow->updateToplevel();
|
pWindow->updateToplevel();
|
||||||
g_pHyprRenderer->damageWindow(pWindow);
|
g_pHyprRenderer->damageWindow(pWindow);
|
||||||
}
|
}
|
||||||
|
|
@ -826,19 +828,20 @@ void IHyprLayout::fitFloatingWindowOnMonitor(PHLWINDOW w, std::optional<CBox> tb
|
||||||
|
|
||||||
const auto EXTENTS = w->getWindowExtentsUnified(RESERVED_EXTENTS | INPUT_EXTENTS);
|
const auto EXTENTS = w->getWindowExtentsUnified(RESERVED_EXTENTS | INPUT_EXTENTS);
|
||||||
CBox targetBoxMonLocal = tb.value_or(w->getWindowMainSurfaceBox()).translate(-PMONITOR->m_position).addExtents(EXTENTS);
|
CBox targetBoxMonLocal = tb.value_or(w->getWindowMainSurfaceBox()).translate(-PMONITOR->m_position).addExtents(EXTENTS);
|
||||||
|
const auto MONITOR_LOCAL_BOX = PMONITOR->logicalBoxMinusExtents().translate(-PMONITOR->m_position);
|
||||||
|
|
||||||
if (targetBoxMonLocal.w < PMONITOR->m_size.x) {
|
if (targetBoxMonLocal.w < MONITOR_LOCAL_BOX.w) {
|
||||||
if (targetBoxMonLocal.x < 0)
|
if (targetBoxMonLocal.x < MONITOR_LOCAL_BOX.x)
|
||||||
targetBoxMonLocal.x = 0;
|
targetBoxMonLocal.x = MONITOR_LOCAL_BOX.x;
|
||||||
else if (targetBoxMonLocal.x + targetBoxMonLocal.w > PMONITOR->m_size.x)
|
else if (targetBoxMonLocal.x + targetBoxMonLocal.w > MONITOR_LOCAL_BOX.w)
|
||||||
targetBoxMonLocal.x = PMONITOR->m_size.x - targetBoxMonLocal.w;
|
targetBoxMonLocal.x = MONITOR_LOCAL_BOX.w - targetBoxMonLocal.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetBoxMonLocal.h < PMONITOR->m_size.y) {
|
if (targetBoxMonLocal.h < MONITOR_LOCAL_BOX.h) {
|
||||||
if (targetBoxMonLocal.y < 0)
|
if (targetBoxMonLocal.y < MONITOR_LOCAL_BOX.y)
|
||||||
targetBoxMonLocal.y = 0;
|
targetBoxMonLocal.y = MONITOR_LOCAL_BOX.y;
|
||||||
else if (targetBoxMonLocal.y + targetBoxMonLocal.h > PMONITOR->m_size.y)
|
else if (targetBoxMonLocal.y + targetBoxMonLocal.h > MONITOR_LOCAL_BOX.h)
|
||||||
targetBoxMonLocal.y = PMONITOR->m_size.y - targetBoxMonLocal.h;
|
targetBoxMonLocal.y = MONITOR_LOCAL_BOX.h - targetBoxMonLocal.h;
|
||||||
}
|
}
|
||||||
|
|
||||||
*w->m_realPosition = (targetBoxMonLocal.pos() + PMONITOR->m_position + EXTENTS.topLeft).round();
|
*w->m_realPosition = (targetBoxMonLocal.pos() + PMONITOR->m_position + EXTENTS.topLeft).round();
|
||||||
|
|
@ -884,7 +887,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) {
|
||||||
// find whether there is a floating window below this one
|
// find whether there is a floating window below this one
|
||||||
for (auto const& w : g_pCompositor->m_windows) {
|
for (auto const& w : g_pCompositor->m_windows) {
|
||||||
if (w->m_isMapped && !w->isHidden() && w->m_isFloating && !w->isX11OverrideRedirect() && w->m_workspace == pWindow->m_workspace && !w->m_X11ShouldntFocus &&
|
if (w->m_isMapped && !w->isHidden() && w->m_isFloating && !w->isX11OverrideRedirect() && w->m_workspace == pWindow->m_workspace && !w->m_X11ShouldntFocus &&
|
||||||
!w->m_windowData.noFocus.valueOrDefault() && w != pWindow) {
|
!w->m_ruleApplicator->noFocus().valueOrDefault() && w != pWindow) {
|
||||||
if (VECINRECT((pWindow->m_size / 2.f + pWindow->m_position), w->m_position.x, w->m_position.y, w->m_position.x + w->m_size.x, w->m_position.y + w->m_size.y)) {
|
if (VECINRECT((pWindow->m_size / 2.f + pWindow->m_position), w->m_position.x, w->m_position.y, w->m_position.x + w->m_size.x, w->m_position.y + w->m_size.y)) {
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
@ -903,7 +906,7 @@ PHLWINDOW IHyprLayout::getNextWindowCandidate(PHLWINDOW pWindow) {
|
||||||
// if not, floating window
|
// if not, floating window
|
||||||
for (auto const& w : g_pCompositor->m_windows) {
|
for (auto const& w : g_pCompositor->m_windows) {
|
||||||
if (w->m_isMapped && !w->isHidden() && w->m_isFloating && !w->isX11OverrideRedirect() && w->m_workspace == pWindow->m_workspace && !w->m_X11ShouldntFocus &&
|
if (w->m_isMapped && !w->isHidden() && w->m_isFloating && !w->isX11OverrideRedirect() && w->m_workspace == pWindow->m_workspace && !w->m_X11ShouldntFocus &&
|
||||||
!w->m_windowData.noFocus.valueOrDefault() && w != pWindow)
|
!w->m_ruleApplicator->noFocus().valueOrDefault() && w != pWindow)
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -952,7 +955,7 @@ Vector2D IHyprLayout::predictSizeForNewWindowFloating(PHLWINDOW pWindow) { // ge
|
||||||
if (g_pCompositor->m_lastMonitor) {
|
if (g_pCompositor->m_lastMonitor) {
|
||||||
|
|
||||||
// If `persistentsize` is set, use the stored size if available.
|
// If `persistentsize` is set, use the stored size if available.
|
||||||
const bool HASPERSISTENTSIZE = std::ranges::any_of(pWindow->m_matchedRules, [](const auto& rule) { return rule->m_ruleType == CWindowRule::RULE_PERSISTENTSIZE; });
|
const bool HASPERSISTENTSIZE = pWindow->m_ruleApplicator->persistentSize().valueOrDefault();
|
||||||
|
|
||||||
const auto STOREDSIZE = HASPERSISTENTSIZE ? g_pConfigManager->getStoredFloatingSize(pWindow) : std::nullopt;
|
const auto STOREDSIZE = HASPERSISTENTSIZE ? g_pConfigManager->getStoredFloatingSize(pWindow) : std::nullopt;
|
||||||
|
|
||||||
|
|
@ -961,27 +964,10 @@ Vector2D IHyprLayout::predictSizeForNewWindowFloating(PHLWINDOW pWindow) { // ge
|
||||||
return STOREDSIZE.value();
|
return STOREDSIZE.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) {
|
if (!pWindow->m_ruleApplicator->static_.size.empty()) {
|
||||||
if (r->m_ruleType != CWindowRule::RULE_SIZE)
|
const auto SIZE = Desktop::Rule::parseRelativeVector(pWindow, pWindow->m_ruleApplicator->static_.size);
|
||||||
continue;
|
if (SIZE)
|
||||||
|
return SIZE.value();
|
||||||
try {
|
|
||||||
const auto VALUE = r->m_rule.substr(r->m_rule.find(' ') + 1);
|
|
||||||
const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' '));
|
|
||||||
const auto SIZEYSTR = VALUE.substr(VALUE.find(' ') + 1);
|
|
||||||
|
|
||||||
const auto MAXSIZE = pWindow->requestedMaxSize();
|
|
||||||
|
|
||||||
const float SIZEX = SIZEXSTR == "max" ? std::clamp(MAXSIZE.x, MIN_WINDOW_SIZE, g_pCompositor->m_lastMonitor->m_size.x) :
|
|
||||||
stringToPercentage(SIZEXSTR, g_pCompositor->m_lastMonitor->m_size.x);
|
|
||||||
|
|
||||||
const float SIZEY = SIZEYSTR == "max" ? std::clamp(MAXSIZE.y, MIN_WINDOW_SIZE, g_pCompositor->m_lastMonitor->m_size.y) :
|
|
||||||
stringToPercentage(SIZEYSTR, g_pCompositor->m_lastMonitor->m_size.y);
|
|
||||||
|
|
||||||
sizeOverride = {SIZEX, SIZEY};
|
|
||||||
|
|
||||||
} catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r->m_rule, r->m_value); }
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -989,17 +975,7 @@ Vector2D IHyprLayout::predictSizeForNewWindowFloating(PHLWINDOW pWindow) { // ge
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2D IHyprLayout::predictSizeForNewWindow(PHLWINDOW pWindow) {
|
Vector2D IHyprLayout::predictSizeForNewWindow(PHLWINDOW pWindow) {
|
||||||
bool shouldBeFloated = g_pXWaylandManager->shouldBeFloated(pWindow, true);
|
bool shouldBeFloated = g_pXWaylandManager->shouldBeFloated(pWindow, true) || pWindow->m_ruleApplicator->static_.floating.value_or(false);
|
||||||
|
|
||||||
if (!shouldBeFloated) {
|
|
||||||
for (auto const& r : g_pConfigManager->getMatchingRules(pWindow, true, true)) {
|
|
||||||
if (r->m_ruleType != CWindowRule::RULE_FLOAT)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
shouldBeFloated = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2D sizePredicted = {};
|
Vector2D sizePredicted = {};
|
||||||
|
|
||||||
|
|
@ -1042,7 +1018,7 @@ bool IHyprLayout::updateDragWindow() {
|
||||||
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
|
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
|
||||||
*DRAGGINGWINDOW->m_realPosition = MOUSECOORDS - DRAGGINGWINDOW->m_realSize->goal() / 2.f;
|
*DRAGGINGWINDOW->m_realPosition = MOUSECOORDS - DRAGGINGWINDOW->m_realSize->goal() / 2.f;
|
||||||
} else if (!DRAGGINGWINDOW->m_isFloating && g_pInputManager->m_dragMode == MBIND_MOVE) {
|
} else if (!DRAGGINGWINDOW->m_isFloating && g_pInputManager->m_dragMode == MBIND_MOVE) {
|
||||||
Vector2D MINSIZE = DRAGGINGWINDOW->requestedMinSize().clamp(DRAGGINGWINDOW->m_windowData.minSize.valueOr(Vector2D(MIN_WINDOW_SIZE, MIN_WINDOW_SIZE)));
|
Vector2D MINSIZE = DRAGGINGWINDOW->requestedMinSize().clamp(DRAGGINGWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D(MIN_WINDOW_SIZE, MIN_WINDOW_SIZE)));
|
||||||
DRAGGINGWINDOW->m_lastFloatingSize = (DRAGGINGWINDOW->m_realSize->goal() * 0.8489).clamp(MINSIZE, Vector2D{}).floor();
|
DRAGGINGWINDOW->m_lastFloatingSize = (DRAGGINGWINDOW->m_realSize->goal() * 0.8489).clamp(MINSIZE, Vector2D{}).floor();
|
||||||
*DRAGGINGWINDOW->m_realPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_realSize->goal() / 2.f;
|
*DRAGGINGWINDOW->m_realPosition = g_pInputManager->getMouseCoordsInternal() - DRAGGINGWINDOW->m_realSize->goal() / 2.f;
|
||||||
if (g_pInputManager->m_dragThresholdReached) {
|
if (g_pInputManager->m_dragThresholdReached) {
|
||||||
|
|
|
||||||
|
|
@ -242,7 +242,7 @@ void CHyprMasterLayout::onWindowRemovedTiling(PHLWINDOW pWindow) {
|
||||||
const auto MASTERSLEFT = getMastersOnWorkspace(WORKSPACEID);
|
const auto MASTERSLEFT = getMastersOnWorkspace(WORKSPACEID);
|
||||||
static auto SMALLSPLIT = CConfigValue<Hyprlang::INT>("master:allow_small_split");
|
static auto SMALLSPLIT = CConfigValue<Hyprlang::INT>("master:allow_small_split");
|
||||||
|
|
||||||
pWindow->unsetWindowData(PRIORITY_LAYOUT);
|
pWindow->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT);
|
||||||
pWindow->updateWindowData();
|
pWindow->updateWindowData();
|
||||||
|
|
||||||
if (pWindow->isFullscreen())
|
if (pWindow->isFullscreen())
|
||||||
|
|
@ -297,6 +297,8 @@ void CHyprMasterLayout::recalculateMonitor(const MONITORID& monid) {
|
||||||
|
|
||||||
#ifndef NO_XWAYLAND
|
#ifndef NO_XWAYLAND
|
||||||
CBox box = g_pCompositor->calculateX11WorkArea();
|
CBox box = g_pCompositor->calculateX11WorkArea();
|
||||||
|
if (!g_pXWayland || !g_pXWayland->m_wm)
|
||||||
|
return;
|
||||||
g_pXWayland->m_wm->updateWorkArea(box.x, box.y, box.w, box.h);
|
g_pXWayland->m_wm->updateWorkArea(box.x, box.y, box.w, box.h);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -661,7 +663,7 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||||
if (PWINDOW->isFullscreen() && !pNode->ignoreFullscreenChecks)
|
if (PWINDOW->isFullscreen() && !pNode->ignoreFullscreenChecks)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PWINDOW->unsetWindowData(PRIORITY_LAYOUT);
|
PWINDOW->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT);
|
||||||
PWINDOW->updateWindowData();
|
PWINDOW->updateWindowData();
|
||||||
|
|
||||||
static auto PANIMATE = CConfigValue<Hyprlang::INT>("misc:animate_manual_resizes");
|
static auto PANIMATE = CConfigValue<Hyprlang::INT>("misc:animate_manual_resizes");
|
||||||
|
|
@ -706,9 +708,9 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
||||||
Vector2D monitorAvailable = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight -
|
Vector2D monitorAvailable = PMONITOR->m_size - PMONITOR->m_reservedTopLeft - PMONITOR->m_reservedBottomRight -
|
||||||
Vector2D{(double)(gapsOut.m_left + gapsOut.m_right), (double)(gapsOut.m_top + gapsOut.m_bottom)} - Vector2D{2.0 * borderSize, 2.0 * borderSize};
|
Vector2D{(double)(gapsOut.m_left + gapsOut.m_right), (double)(gapsOut.m_top + gapsOut.m_bottom)} - Vector2D{2.0 * borderSize, 2.0 * borderSize};
|
||||||
|
|
||||||
Vector2D minSize = PWINDOW->m_windowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}).clamp(Vector2D{0, 0}, monitorAvailable);
|
Vector2D minSize = PWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}).clamp(Vector2D{0, 0}, monitorAvailable);
|
||||||
Vector2D maxSize =
|
Vector2D maxSize = PWINDOW->isFullscreen() ? Vector2D{INFINITY, INFINITY} :
|
||||||
PWINDOW->isFullscreen() ? Vector2D{INFINITY, INFINITY} : PWINDOW->m_windowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY}).clamp(Vector2D{0, 0}, monitorAvailable);
|
PWINDOW->m_ruleApplicator->maxSize().valueOr(Vector2D{INFINITY, INFINITY}).clamp(Vector2D{0, 0}, monitorAvailable);
|
||||||
calcSize = calcSize.clamp(minSize, maxSize);
|
calcSize = calcSize.clamp(minSize, maxSize);
|
||||||
|
|
||||||
calcPos += (availableSpace - calcSize) / 2.0;
|
calcPos += (availableSpace - calcSize) / 2.0;
|
||||||
|
|
@ -760,9 +762,9 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne
|
||||||
const auto PNODE = getNodeFromWindow(PWINDOW);
|
const auto PNODE = getNodeFromWindow(PWINDOW);
|
||||||
|
|
||||||
if (!PNODE) {
|
if (!PNODE) {
|
||||||
*PWINDOW->m_realSize =
|
*PWINDOW->m_realSize = (PWINDOW->m_realSize->goal() + pixResize)
|
||||||
(PWINDOW->m_realSize->goal() + pixResize)
|
.clamp(PWINDOW->m_ruleApplicator->minSize().valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}),
|
||||||
.clamp(PWINDOW->m_windowData.minSize.valueOr(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), PWINDOW->m_windowData.maxSize.valueOr(Vector2D{INFINITY, INFINITY}));
|
PWINDOW->m_ruleApplicator->maxSize().valueOr(Vector2D{INFINITY, INFINITY}));
|
||||||
PWINDOW->updateWindowDecos();
|
PWINDOW->updateWindowDecos();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -917,7 +919,7 @@ void CHyprMasterLayout::fullscreenRequestForWindow(PHLWINDOW pWindow, const eFul
|
||||||
*pWindow->m_realPosition = pWindow->m_lastFloatingPosition;
|
*pWindow->m_realPosition = pWindow->m_lastFloatingPosition;
|
||||||
*pWindow->m_realSize = pWindow->m_lastFloatingSize;
|
*pWindow->m_realSize = pWindow->m_lastFloatingSize;
|
||||||
|
|
||||||
pWindow->unsetWindowData(PRIORITY_LAYOUT);
|
pWindow->m_ruleApplicator->resetProps(Desktop::Rule::RULE_PROP_ALL, Desktop::Types::PRIORITY_LAYOUT);
|
||||||
pWindow->updateWindowData();
|
pWindow->updateWindowData();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue